手把手教你一步步使用基于HAL库的STM32的完成ESP8266/ESP01S通信OneNET物联网平台

(一)模块介绍:ESP8266 WiFi 模块

1. 模块核心介绍

型号:ESP8266-01S(通用串口 WiFi 模块);

  • 通信方式:UART 串口(TTL 电平),默认波特率115200,8N1;

  • 协议:通过AT 指令实现 MQTT 协议对接OneNet 物联网平台;

  • 核心功能:将 STM32 采集的温湿度、甲醛、CO₂浓度等数据上传至云端,实现远程监测;

  • 硬件接口:VCC(3.3V)、GND、TX、RX。

2. 硬件连接规则

(一)STM32  ↔ ESP8266最小系统板

  • 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 配置步骤

本工程使用 USART3 与 ESP8266 通信,配置如下:

步骤 1:USART3 串口配置

  • 左侧 Connectivity → 选择 USART3;

  • 模式选择:Asynchronous(异步通信);

  • 参数设置(与 ESP8266 一致):

  • 波特率:115200

  • 字长:8 Bits

  • 校验位:None

  • 停止位:1

  • 默认引脚:TX=PB10,RX=PB11。

步骤 2:开启串口接收中断

  1. 左侧 System Core → NVIC;

  2. 勾选 USART3 global interrupt 使能中断;

  3. 优先级默认即可。

步骤 3:生成工程代码

点击 GENERATE CODE 生成工程,准备添加 ESP8266 驱动。

(三)核心代码:esp8266.h + esp8266.c 完整文件

1. ESP8266 头文件 esp8266.h

#ifndef _esp8266_h#define _esp8266_h#include <stdarg.h>#include "bsp_config.h"// ==================== 物联网平台 / WiFi 配置宏 ====================#define WIFI_SSID                     "leo"  #define WIFI_PASSWORD                 "123456789"// OneNet 平台核心参数#define WIFI_ONENET_PRODUCT_ID        "XXX"#define WIFI_ONENET_DEVICE_NAME       "XXX"#define WIFI_ONENET_TOKEN             "vXXX"// MQTT 服务器参数#define MQTT_HOST_URL                 "mqtts.heclouds.com"#define MQTT_HOST_PORT                1883#define MQTT_TOPIC_POST_REPLY         "$sys/" WIFI_ONENET_PRODUCT_ID "/" WIFI_ONENET_DEVICE_NAME "/thing/property/post/reply"#define MQTT_TOPIC_PROPERTY_SET       "$sys/" WIFI_ONENET_PRODUCT_ID "/" WIFI_ONENET_DEVICE_NAME "/thing/property/set"#define AT_MQTT_USERCFG               "AT+MQTTUSERCFG=0,1,\"" WIFI_ONENET_DEVICE_NAME "\",\"" WIFI_ONENET_PRODUCT_ID "\",\"" WIFI_ONENET_TOKEN "\",0,0,\"\""#define AT_MQTT_CONN                  "AT+MQTTCONN=0,\"" MQTT_HOST_URL "\",1883,1"#define AT_MQTT_SUB_POST_REPLY        "AT+MQTTSUB=0,\"" MQTT_TOPIC_POST_REPLY "\",0"#define 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);#endif

2. ESP8266 驱动文件 esp8266.c

#include "esp8266.h"#include <string.h>#include <stdio.h>#include "main.h"#include "usart.h"#define TX_SIZE     245#define RX_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);    // 连接WiFi    while(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)

USART3 接收中断绑定 ESP8266 接收函数,是数据通信的核心:

#include "bsp_it.h"#include "esp8266.h"uint8_t rx3;void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){    // ESP8266 对应 USART3    if(huart->Instance == USART3)    {        uart_rx_esp866();  // 调用ESP8266接收处理函数    }}

2. 主函数初始化 + 数据上传(bsp.c loop)

#include "bsp.h"#include "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();              // 连接WiFi    OLED_PrintString(0, 16,"WIFI_OK!", &font16x16, OLED_COLOR_NORMAL);    OLED_ShowFrame();    mqtt_init();              // 连接OneNet MQTT    OLED_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. 定时上传数据到OneNet    static 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作为中间人

        先把这个CH340接入到ESP8266上,确保数据正确

  • 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:发送指令

默认波特是115200,数据位:8,校验位:无,停止位:1。

测试指令

指令

响应

功能

AT

OK

测试AT指令

复位指令

指令

响应

功能

AT+RST

OK

软件复位

还原指令

指令

响应

功能

AT+RESTORE

OK

恢复所有参数为默认值,并重启

设置为WIFI模块指令

指令

响应

功能

AT+CWMODE=1

OK

设置Wi-Fi为Station模式可以去连接热点

连接WIFI指令(确保手机是2.4G的而不是5G 的wifi)

指令

响应

功能

AT+CWJAP="leo","123456789"


  1. WIFI CONNECTED

  2. WIFI GOT IP

  3. OK


连接到2.4GHz wifi

leo是热点名称

123456789是密码

设置 MQTT 用户属性

指令

响应

功能

AT+MQTTUSERCFG=0,1,"dev","dev-ID","XXXX",0,0,""

OK

配置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

OK

连接MQTT服务器

订阅响应

指令

响应

功能

AT+MQTTSUB=0,"$sys/id/dev1/thing/property/post/reply",0

OK

订阅“设备属性上报响应”主题

注意id和dev1的修改

订阅请求

指令

响应

功能

AT+MQTTSUB=0,"$sys/id/dev1/thing/property/set",0

OK

订阅“设备属性设置请求”主题

发送数据到物联网

指令

响应

功能

"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);

OK

发送数据到Onenet
步骤 4:单片机发送测试

     如果上述直接使用CH340向ESP8266模块发送数据没问题,下一步将代码一直到单片机中,单片机发送串口数据,将单片机和CH340相连,单片机发送数据根据数据正确与否,手动发送OK,当数据测试全部完成后,将串口助手获得到的单片机数据保存,将数据用于CH340和ESP8266模块做最后尝试,若没问题可以正常上传,说明万事大吉。







发表评论