前期已学习如何用ESP8266连接WIFI,并发送数据到服务器。现在只需要在单片机与nodeMCU之间建立起串口通信,这样单片机就可以将传感器测到的数据:光照,温度,湿度等等传递给8266了,然后8266再对数据进行打包,发送到服务器。
51单片机和nodeMCU的连线方式如下

它们串口的两根线交叉连接,二者的USB供电端一起接在电脑的USB口上。如果它们不是用的同一套供电系统,就需要注意共地的问题!
51单片机的主体代码大致如下;

主要就是测量一些数据,然后通过串口发送到nodeMCU
nodeMCU的代码如下:
- #include <ESP8266WiFi.h>
- #include <PubSubClient.h>
- #include <ArduinoJson.h>
- const char* ssid = "iPhone"; //WIFI名称 自己补上你的WIFI
- const char* password = "12345678"; //WIFI密码 自己补上你的密码
- const char* mqtt_server = "broker-cn.emqx.io"; //mqtt服务器地址 (IP/域名) 不改
- const char *pubTopic="my_pubtopic";
- const char *subTopic="my_subtopic";
-
-
- WiFiClient espClient;
- PubSubClient client(espClient);
-
- char information[80]="";
- int value = 0;
-
- void setup_wifi() {
-
- delay(10);
- // We start by connecting to a WiFi network
- Serial.println();
- Serial.print("Connecting to ");
- Serial.println(ssid);
-
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
-
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
-
- randomSeed(micros());
-
- Serial.println("");
- Serial.println("WiFi connected");
- Serial.println("IP address: ");
- Serial.println(WiFi.localIP());
- }
-
- void callback(char* topic, byte* payload, unsigned int length) {
- String cmd="";
- for (int i = 0; i < length; i++) {
- cmd+=(char)payload[i];
- }
- const size_t capacity = JSON_OBJECT_SIZE(1) + 10; //计算buffer的大小 ...SIZE(1)表明buffer中只有一个对象
- DynamicJsonBuffer jsonBuffer(capacity); //创建动态的jsonbuffer
- JsonObject& root = jsonBuffer.parseObject(cmd); //解析Json对象字符串
- Serial.println("get");
- if(root.containsKey("led")) //判断是否包含某个键
- {
- int led = root["led"];
- if(led==1)
- {
- Serial.println("1");
- }
- else
- Serial.println("2");
- }
- if(root.containsKey("beep")) //判断是否包含某个键
- {
- int beep = root["beep"];
- if(beep==1)
- {
- Serial.println("3");
- }
- else
- Serial.println("4");
- }
- }
-
- void reconnect() {
- // Loop until we're reconnected
- while (!client.connected()) {
- Serial.print("Attempting MQTT connection...");
- // Create a random client ID
- String clientId = "ESP8266Client-";
- clientId += String(random(0xffff), HEX);
- // Attempt to connect
- if (client.connect(clientId.c_str())) {
- Serial.println("connected");
- // Once connected, publish an announcement...
- client.publish(pubTopic, "hello world");
- // ... and resubscribe
- client.subscribe(subTopic);
- } else {
- Serial.print("failed, rc=");
- Serial.print(client.state());
- Serial.println(" try again in 5 seconds");
- // Wait 5 seconds before retrying
- delay(5000);
- }
- }
- }
- void setup() {
- Serial.begin(9600);
- setup_wifi();
- client.setServer(mqtt_server, 1883);
- client.setCallback(callback);
- }
- void loop() {
- if (!client.connected()) {
- reconnect();
- }
- client.loop();
- value=0;
- while(!Serial.available()); //等待数据传送过来,若没有数据,一直等待,即执行到本行不向下执行
- while(Serial.available())
- {
- information[value]=(char)Serial.read();
- value++;
- delay(3);
- }
- client.publish(pubTopic, information);
- Serial.print(information);
- // }
- }
51单片机发送给nodeMCU的数据,全部存在了这个数组里面

所以这个数组要足够大,至少要大于你发送的内容。不然就会导致nodeMCU出现堆栈溢出的错误。(本人在这里卡了好几个小时) 希望大家可以避免类似的错误
在nodeMCU将数据发送到服务器的同时,可以使用nodeMCU的串口,将数据打印出来,方便调试,看看是否正确的接收到了数据。如下图所示,这种是正确接收的效果。


如果通信出现错误,没有准确接收,那么它会显示一群乱码,根本看不清楚是什么!!!
如果你发现你接收到的数据总是不准确,或者总是有乱码,可以尝试调整这个延时时间


如上图所示,服务器已经可以成功接收到单片机发送的数据了!!!
此时,只需要开发一个MQTT协议的手机APP,就可以实现单片机数据在手机上显示的效果!