(一)模块介绍:ESP8266 WiFi 模块
1. 模块核心介绍
型号:ESP8266-01S(通用串口 WiFi 模块);
-
通信方式:UART 串口(TTL 电平),默认波特率115200,8N1;
-
协议:通过AT 指令实现 MQTT 协议对接OneNet 物联网平台;
-
核心功能:将 STM32 采集的温湿度、甲醛、CO₂浓度等数据上传至云端,实现远程监测;
-
硬件接口:VCC(3.3V)、GND、TX、RX。
2. 硬件连接规则
-
VCC ↔ 3.3V
-
GND ↔ GND
- USART3_TX(PB10)↔ ESP_RX
- USART3_RX(PB11) ↔ ESP_TX
(二)STM32 ↔ ESP01S
-
VCC ↔ 3.3V
-
GND ↔ GND
- USART3_TX(PB10) ↔ ESP_RX
- USART3_RX(PB11)↔ ESP_TX
-
EN↔VCC或者接入某个引脚
3. 云平台配置
-
WiFi 名称:
leo,WiFi 密码:123456789 -
对接OneNet 物联网平台,通过 MQTT 协议上传环境监测数据。
(二)初始化:STM32CUBEMX 配置步骤
步骤 1:USART3 串口配置
-
左侧 Connectivity → 选择 USART3;
-
模式选择:Asynchronous(异步通信);
-
参数设置(与 ESP8266 一致):
-
波特率:115200
-
字长:8 Bits
-
校验位:None
-
停止位:1
-
默认引脚:TX=PB10,RX=PB11。
步骤 2:开启串口接收中断
-
左侧
System Core→NVIC; -
勾选
USART3 global interrupt使能中断; -
优先级默认即可。
步骤 3:生成工程代码
(三)核心代码:esp8266.h + esp8266.c 完整文件
1. ESP8266 头文件 esp8266.h
_esp8266_h_esp8266_h<stdarg.h>"bsp_config.h"// ==================== 物联网平台 / WiFi 配置宏 ====================WIFI_SSID "leo"WIFI_PASSWORD "123456789"// OneNet 平台核心参数WIFI_ONENET_PRODUCT_ID "XXX"WIFI_ONENET_DEVICE_NAME "XXX"WIFI_ONENET_TOKEN "vXXX"// MQTT 服务器参数MQTT_HOST_URL "mqtts.heclouds.com"MQTT_HOST_PORT 1883MQTT_TOPIC_POST_REPLY "$sys/" WIFI_ONENET_PRODUCT_ID "/" WIFI_ONENET_DEVICE_NAME "/thing/property/post/reply"MQTT_TOPIC_PROPERTY_SET "$sys/" WIFI_ONENET_PRODUCT_ID "/" WIFI_ONENET_DEVICE_NAME "/thing/property/set"AT_MQTT_USERCFG "AT+MQTTUSERCFG=0,1,\"" WIFI_ONENET_DEVICE_NAME "\",\"" WIFI_ONENET_PRODUCT_ID "\",\"" WIFI_ONENET_TOKEN "\",0,0,\"\""AT_MQTT_CONN "AT+MQTTCONN=0,\"" MQTT_HOST_URL "\",1883,1"AT_MQTT_SUB_POST_REPLY "AT+MQTTSUB=0,\"" MQTT_TOPIC_POST_REPLY "\",0"AT_MQTT_SUB_PROPERTY_SET "AT+MQTTSUB=0,\"" MQTT_TOPIC_PROPERTY_SET "\",0"// ==================== 函数声明 ====================void esp8266_printf(char* fmt, ...);void esp8266_rx_init(void);char esp8266_send_cmd(char *cmd, int timeout);char wifi_init(void);char mqtt_init(void);char esp8266_connect_send(const char* paramName, int value, int timeout);void uart_rx_esp8266(void);
2. ESP8266 驱动文件 esp8266.c
"esp8266.h"<string.h><stdio.h>"main.h""usart.h"TX_SIZE 245RX_SIZE 245char at_txbuffer[TX_SIZE] = {0};char at_rxbuffer[RX_SIZE] = {0};uint8_t at_rxindex = 0;uint8_t at_rx = 0;/*** @brief ESP8266 串口接收中断处理* @param 无* @retval 无*/void uart_rx_esp8266(void){if(at_rxindex < RX_SIZE - 1){at_rxbuffer[at_rxindex++] = at_rx;at_rxbuffer[at_rxindex] = '\0';}else{at_rxindex = 0;memset(at_rxbuffer, 0, RX_SIZE);}HAL_UART_Receive_IT(&huart3, &at_rx, 1);}/*** @brief 格式化发送数据(AT指令专用)* @param fmt 格式化字符串* @retval 无*/void esp8266_printf(char* fmt, ...){memset(at_txbuffer, 0, TX_SIZE);va_list ap;va_start(ap, fmt);vsprintf(at_txbuffer, fmt, ap);va_end(ap);uint16_t length = strlen(at_txbuffer);HAL_UART_Transmit(&huart3, (uint8_t*)at_txbuffer, length, 2000);}/*** @brief ESP8266 接收初始化* @param 无* @retval 无*/void esp8266_rx_init(void){at_rxindex = 0;memset(at_rxbuffer, 0, RX_SIZE);HAL_UART_Receive_IT(&huart3, &at_rx, 1);}/*** @brief 发送AT指令并等待返回* @param cmd 指令* @param timeout 超时时间* @retval 0成功 / -1失败*/char esp8266_send_cmd(char *cmd, int timeout){at_rxindex = 0;memset(at_rxbuffer, 0, RX_SIZE);esp8266_printf("%s\r\n", cmd);HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 2000);while(timeout--){HAL_Delay(1);if(strstr(at_rxbuffer, "OK") != NULL ||strstr(at_rxbuffer, "ready") != NULL ||strstr(at_rxbuffer, ">") != NULL){return 0;}else if(strstr(at_rxbuffer, "ERROR") != NULL){return -1;}}return -1;}/*** @brief WiFi 初始化连接* @param 无* @retval 0*/char wifi_init(void){HAL_Delay(2500);esp8266_printf("AT+RESTORE\r\n");HAL_Delay(2500);// 设置Station模式while(esp8266_send_cmd("AT+CWMODE=1", 1500) == -1);// 连接WiFiwhile(esp8266_send_cmd("AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PASSWORD "\"", 5000) == -1);return 0;}/*** @brief MQTT 初始化(连接OneNet)* @param 无* @retval 0*/char mqtt_init(void){// 配置MQTT用户信息while(esp8266_send_cmd(AT_MQTT_USERCFG, 4000) == -1);// 连接MQTT服务器while(esp8266_send_cmd(AT_MQTT_CONN, 4000) == -1);// 订阅主题while(esp8266_send_cmd(AT_MQTT_SUB_POST_REPLY, 4000) == -1);while(esp8266_send_cmd(AT_MQTT_SUB_PROPERTY_SET, 1500) == -1);return 0;}/*** @brief 向OneNet上传传感器数据* @param paramName 数据名称* @param value 数据值* @param timeout 超时* @retval 0成功 / -1失败*/char esp8266_connect_send(const char* paramName, int value, int timeout){char cmd[256];sprintf(cmd, "AT+MQTTPUB=0,\"$sys/%s/%s/thing/property/post\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d}}}\",0,0",WIFI_ONENET_PRODUCT_ID,WIFI_ONENET_DEVICE_NAME,paramName,value);return esp8266_send_cmd(cmd, timeout);}
(四)使用实例:主函数中调用 ESP8266 驱动
1. 中断回调绑定(bsp_it.c)
"bsp_it.h""esp8266.h"uint8_t rx3;void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){// ESP8266 对应 USART3if(huart->Instance == USART3){uart_rx_esp866(); // 调用ESP8266接收处理函数}}
2. 主函数初始化 + 数据上传(bsp.c loop)
"bsp.h""esp8266.h"// 环境监测变量uint16_t co2_dat; // CO2浓度uint16_t jiaquan_dat; // 甲醛浓度uint16_t temp_dat; // 温度uint16_t humi_dat; // 湿度void bsp_init(){// 1. 外设初始化MG90_Init();OLED_Init();co2_init();// 2. ESP8266初始化(核心)esp8266_rx_init(); // 初始化串口接收OLED_NewFrame();OLED_PrintString(0, 0, "OneNetConnect...", &font16x16, OLED_COLOR_NORMAL);OLED_ShowFrame();wifi_init(); // 连接WiFiOLED_PrintString(0, 16,"WIFI_OK!", &font16x16, OLED_COLOR_NORMAL);OLED_ShowFrame();mqtt_init(); // 连接OneNet MQTTOLED_PrintString(0, 32,"MQTT_OK!", &font16x16, OLED_COLOR_NORMAL);OLED_ShowFrame();HAL_Delay(500);}void loop(){// 1. 更新环境数据(略)DHT11_ReadData(&DH11);humi_dat = DH11.humi_int;temp_dat = DH11.temp_int;jiaquan_dat = formaldehyde_concentration;co2_dat = eco2_concentration;// 2. 定时上传数据到OneNetstatic uint8_t send_times = 0;send_times++;if(send_times == 1) esp8266_connect_send("Humi", humi_dat, 100);if(send_times == 45) esp8266_connect_send("Temp", temp_dat, 100);if(send_times == 80) esp8266_connect_send("JiaQuan", jiaquan_dat, 100);if(send_times == 110){send_times = 0;esp8266_connect_send("CO2", co2_dat, 100);}HAL_Delay(7);}
(四)调试技巧
步骤 1:使用CH340作为中间人
-
VCC ↔ 3.3V
-
GND ↔ GND
-
ESP_RX↔ CH340_TX
-
ESP_TX↔ CH340_RX
-
ESP_EN↔3.3V(如果EN引脚没有接入)
将正确的AT指令通过串口助手发给CH340,CH340再将数据传入给ESP8266模块,比如发送“AT”,ESP8266模块会自动回复“OK”,保证原始数据以及ESP8266模块没有问题。
如果ESP8266模块未回复可能:①波特率不正确②连接线错误③固件 重新烧录带AT指令的固件。
详细指令集可以查看乐鑫官网:
https://espressif-docs.readthedocs-hosted.com/projects/esp-at/zh-cn/release-v2.2.0.0_esp8266/AT_Command_Set/index.html
步骤 2:发送指令
测试指令
复位指令
还原指令
设置为WIFI模块指令
连接WIFI指令(确保手机是2.4G的而不是5G 的wifi)
|
|
设置 MQTT 用户属性
|
AT+MQTTUSERCFG=0,1,"dev","dev-ID","XXXX",0,0,"" |
配置MQTT参数 |
dev:设备名称,dev-ID设备ID,XXX设备密钥,可查开Onenet官网查看
https://open.iot.10086.cn/doc/mqtt/book/manual/auth/tool.html
连接MQTT服务器
|
AT+MQTTCONN=0,"mqtts.heclouds.com",1883,1 |
连接MQTT服务器 |
订阅响应
|
AT+MQTTSUB=0,"$sys/id/dev1/thing/property/post/reply",0 |
订阅“设备属性上报响应”主题 |
注意id和dev1的修改
订阅请求
|
AT+MQTTSUB=0,"$sys/id/dev1/thing/property/set",0 |
订阅“设备属性设置请求”主题 |
发送数据到物联网
|
"AT+MQTTPUB=0,\"$sys/%s/%s/thing/property/post\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d}}}\",0,0", WIFI_ONENET_PRODUCT_ID, WIFI_ONENET_DEVICE_NAME,paramName, value); |
发送数据到Onenet |
步骤 4:单片机发送测试
如果上述直接使用CH340向ESP8266模块发送数据没问题,下一步将代码一直到单片机中,单片机发送串口数据,将单片机和CH340相连,单片机发送数据根据数据正确与否,手动发送OK,当数据测试全部完成后,将串口助手获得到的单片机数据保存,将数据用于CH340和ESP8266模块做最后尝试,若没问题可以正常上传,说明万事大吉。