核心目标:掌握 STM32 通过 WiFi 模块(ESP8266)实现无线通信,将温湿度数据上传到阿里云 IoT 平台,实现 “开发板→WiFi→云平台→手机 APP” 的完整物联网链路 —— 这是从 “单机设备” 到 “联网智能设备” 的关键一步,也是智能家居、工业监控等场景的核心技术。
一、物联网通信基础:从 “单机” 到 “联网”(20 分钟)
1. 为什么需要 WiFi 模块?
STM32 本身通常没有 WiFi 功能,需通过外接 WiFi 模块(如 ESP8266、ESP32)实现无线联网。ESP8266 是性价比极高的选择,支持 802.11b/g/n 协议,可通过串口(AT 指令)与 STM32 通信,无需深入底层网络协议开发。
2. 核心通信链路
传感器(AHT10)→ STM32(数据处理)→ ESP8266(WiFi传输)→ 云平台(数据存储/展示)→ 手机APP(远程查看)
3. AT 指令:STM32 控制 WiFi 模块的 “语言”
ESP8266 默认支持 AT 指令(类似 “命令行”),STM32 通过串口发送 AT 指令,即可控制模块连接 WiFi、发送数据。常用 AT 指令:
AT:测试模块是否响应(返回 “OK”);AT+CWJAP="WiFi名","密码":连接 WiFi;AT+MQTTUSERCFG=...:配置 MQTT 协议(云平台常用通信协议);AT+MQTTPUB=...:发布数据到云平台。
二、硬件准备与接线(10 分钟)
1. 硬件清单
- STM32F103C8T6 开发板、AHT10 温湿度传感器(I2C);
- ESP8266 WiFi 模块(如 ESP-01S)、USB-TTL 模块(给 ESP8266 供电和调试);
- 杜邦线、面包板、5V 电源(ESP8266 需 3.3V 供电,电流可能较大,建议独立供电)。
2. 接线方式
| 设备 | 引脚连接(STM32 ↔ ESP8266) | 说明 |
|---|---|---|
| STM32 USART2_TX(PA2) | → ESP8266 RX | STM32 发送 AT 指令到 ESP8266 |
| STM32 USART2_RX(PA3) | → ESP8266 TX | STM32 接收 ESP8266 的响应 |
| STM32 GND | → ESP8266 GND | 共地保证通信电平一致 |
| ESP8266 VCC | → 3.3V 电源 | 严禁接 5V,会烧毁模块 |
| AHT10 | 同第八天(SCL→PB6,SDA→PB7) | 温湿度数据采集 |
三、阿里云 IoT 平台配置(30 分钟,关键!)
云平台是数据的 “中转站” 和 “展示中心”,以阿里云 IoT 为例,步骤如下:
1. 创建产品与设备
- 登录阿里云 IoT 控制台(https://iot.console.aliyun.com/);
- 左侧 “设备管理→产品”→“创建产品”:
- 产品名称:
SmartTempHumi; - 所属品类:
自定义品类; - 节点类型:
设备; - 联网方式:
WiFi; - 数据格式:
JSON(便于解析);
- 产品名称:
- 产品创建后,进入 “设备”→“添加设备”:
- 设备名称:
Device001; - 记录设备 “三元组”(ProductKey、DeviceName、DeviceSecret)—— 后续认证必须用到。
- 设备名称:
2. 定义物模型(数据格式)
物模型用于规范设备上传的数据格式(如温度、湿度的字段名和类型):
- 进入产品→“功能定义”→“添加自定义功能”:
- 功能名称:
temperature,标识符:temp,数据类型:float,单位:℃; - 功能名称:
humidity,标识符:humi,数据类型:float,单位:%RH;
- 功能名称:
- 点击 “发布上线”,物模型生效。
3. 获取 MQTT 连接参数
阿里云 IoT 基于 MQTT 协议通信,需计算连接参数:
- 客户端 ID:
设备名称|securemode=3,signmethod=hmacsha1|; - 用户名:
设备名称&产品Key; - 密码:通过三元组和连接参数计算的签名(可用阿里云提供的工具生成,后续代码中会实现签名函数)。
四、STM32 代码实现(60 分钟,分模块开发)
核心逻辑:STM32 定时采集温湿度→通过 USART2 向 ESP8266 发送 AT 指令→控制 ESP8266 连接 WiFi 和阿里云→上传数据到云平台。
1. 配置 CubeIDE 工程
- 启用外设:
- I2C1(AHT10)、USART2(与 ESP8266 通信,波特率 115200)、USART1(调试串口,波特率 9600);
- TIM3(1 秒定时,触发数据采集)、FreeRTOS(创建 2 个任务:采集任务、WiFi 通信任务)。
2. 核心代码:ESP8266 控制与云平台通信
c
/* USER CODE BEGIN 0 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sha1.h> // 需要添加SHA1加密库(用于计算阿里云签名)
// AHT10相关(复用第八天代码)
#define AHT10_ADDR 0x38<<1
float temp = 0.0, humi = 0.0;
uint8_t AHT10_Init(I2C_HandleTypeDef *hi2c) { ... }
uint8_t AHT10_ReadData(I2C_HandleTypeDef *hi2c, float *t, float *h) { ... }
// ESP8266相关
#define ESP_USART &huart2 // 与ESP8266通信的串口
#define DEBUG_USART &huart1 // 调试串口
uint8_t esp_recv_buf[256]; // ESP8266响应缓冲区
// 阿里云三元组(替换为你的设备信息)
#define PRODUCT_KEY "a1XXXXXXXXX"
#define DEVICE_NAME "Device001"
#define DEVICE_SECRET "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#define MQTT_HOST PRODUCT_KEY ".iot-as-mqtt.cn-shanghai.aliyuncs.com" // 阿里云MQTT域名
#define MQTT_PORT 1883 // MQTT端口
// 发送AT指令并等待响应
uint8_t ESP_SendATCmd(char *cmd, char *resp, uint32_t timeout) {
memset(esp_recv_buf, 0, sizeof(esp_recv_buf));
HAL_UART_Transmit(ESP_USART, (uint8_t*)cmd, strlen(cmd), 100);
HAL_Delay(100); // 等待模块响应
// 读取响应
if (HAL_UART_Receive(ESP_USART, esp_recv_buf, sizeof(esp_recv_buf)-1, timeout) != HAL_OK) {
return 1; // 超时
}
// 调试:将ESP8266响应通过USART1输出
HAL_UART_Transmit(DEBUG_USART, esp_recv_buf, strlen((char*)esp_recv_buf), 100);
// 判断是否包含目标响应
if (strstr((char*)esp_recv_buf, resp) != NULL) {
return 0; // 成功
} else {
return 1; // 失败
}
}
// 初始化ESP8266并连接WiFi
uint8_t ESP_InitAndConnectWiFi(char *ssid, char *pwd) {
// 1. 测试模块连接
if (ESP_SendATCmd("AT\r\n", "OK", 1000) != 0) {
return 1; // 模块无响应
}
// 2. 重置模块
if (ESP_SendATCmd("AT+RST\r\n", "ready", 3000) != 0) {
return 1;
}
HAL_Delay(1000);
// 3. 连接WiFi
char cmd[100];
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);
if (ESP_SendATCmd(cmd, "WIFI GOT IP", 10000) != 0) { // 连接超时10秒
return 1;
}
return 0;
}
// 计算阿里云MQTT签名(核心!)
void Aliyun_Sign(char *sign, char *productKey, char *deviceName, char *deviceSecret, char *timestamp) {
// 签名源字符串格式:clientId{deviceName}deviceName{deviceName}productKey{productKey}timestamp{timestamp}
char src[256];
sprintf(src, "clientId%sdeviceName%sproductKey%stimestamp%s", deviceName, deviceName, productKey, timestamp);
// 使用SHA1和deviceSecret计算HMAC-SHA1签名(需实现或调用库函数)
hmac_sha1((uint8_t*)src, strlen(src), (uint8_t*)deviceSecret, strlen(deviceSecret), (uint8_t*)sign);
// 签名结果转Base64(阿里云要求)
base64_encode(sign, sign, strlen(sign));
}
// 连接阿里云IoT平台
uint8_t Aliyun_Connect() {
char cmd[512], sign[128], timestamp[20];
sprintf(timestamp, "%ld", HAL_GetTick()/1000); // 时间戳(秒)
// 1. 计算签名
Aliyun_Sign(sign, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, timestamp);
// 2. 配置MQTT客户端
sprintf(cmd, "AT+MQTTUSERCFG=0,1,\"NULL\",\"%s&%s\",\"%s\",0,0,\"\"\r\n",
DEVICE_NAME, PRODUCT_KEY, sign);
if (ESP_SendATCmd(cmd, "OK", 2000) != 0) return 1;
// 3. 连接MQTT服务器
sprintf(cmd, "AT+MQTTCLIENTID=0,\"%s|securemode=3,signmethod=hmacsha1,timestamp=%s|\"\r\n",
DEVICE_NAME, timestamp);
if (ESP_SendATCmd(cmd, "OK", 2000) != 0) return 1;
// 4. 连接阿里云MQTT主机
sprintf(cmd, "AT+MQTTCONN=0,\"%s\",%d,1\r\n", MQTT_HOST, MQTT_PORT);
if (ESP_SendATCmd(cmd, "MQTT CONNECTED", 5000) != 0) return 1;
return 0;
}
// 上传温湿度数据到阿里云
uint8_t Aliyun_UploadData(float t, float h) {
char cmd[512], payload[128];
// 1. 构建JSON payload(符合物模型定义)
sprintf(payload, "{\"temp\":%.1f,\"humi\":%.1f}", t, h);
// 2. MQTT发布主题(阿里云固定格式:/sys/{productKey}/{deviceName}/thing/event/property/post)
char topic[200];
sprintf(topic, "/sys/%s/%s/thing/event/property/post", PRODUCT_KEY, DEVICE_NAME);
// 3. 发送AT指令发布数据
sprintf(cmd, "AT+MQTTPUB=0,\"%s\",\"%s\",0,0\r\n", topic, payload);
if (ESP_SendATCmd(cmd, "OK", 2000) != 0) return 1;
return 0;
}
/* USER CODE END 0 */
3. FreeRTOS 任务实现
c
/* 任务1:温湿度采集任务 */
void TempHumi_Collect_Task(void const * argument) {
AHT10_Init(&hi2c1);
for(;;) {
AHT10_ReadData(&hi2c1, &temp, &humi);
vTaskDelay(1000); // 1秒采集一次
}
}
/* 任务2:WiFi通信任务 */
void WiFi_Comm_Task(void const * argument) {
// 1. 初始化ESP8266并连接WiFi(替换为你的WiFi名和密码)
if (ESP_InitAndConnectWiFi("你的WiFi名", "你的WiFi密码") != 0) {
HAL_UART_Transmit(DEBUG_USART, (uint8_t*)"WiFi连接失败!\r\n", 16, 100);
vTaskDelete(NULL); // 连接失败,删除任务
}
// 2. 连接阿里云IoT平台
if (Aliyun_Connect() != 0) {
HAL_UART_Transmit(DEBUG_USART, (uint8_t*)"阿里云连接失败!\r\n", 18, 100);
vTaskDelete(NULL);
}
// 3. 循环上传数据
for(;;) {
if (Aliyun_UploadData(temp, humi) == 0) {
HAL_UART_Transmit(DEBUG_USART, (uint8_t*)"数据上传成功\r\n", 14, 100);
} else {
HAL_UART_Transmit(DEBUG_USART, (uint8_t*)"数据上传失败\r\n", 14, 100);
}
vTaskDelay(5000); // 5秒上传一次
}
}
五、测试与验证(30 分钟)
- 模块调试:先用 USB-TTL 连接 ESP8266,通过串口助手发送 AT 指令,确认模块能正常响应、连接 WiFi;
- 代码下载:将程序下载到 STM32,通过 USART1 调试串口观察输出(WiFi 连接状态、云平台连接状态);
- 云平台查看:登录阿里云 IoT 控制台→设备→“运行状态”,可看到上传的温湿度数据;
- 手机查看:在阿里云 IoT 控制台 “产品→交互开发” 中配置简易 APP,扫码即可在手机上实时查看数据。
六、第十二天必掌握的 3 个核心点
- ESP8266 控制:通过 AT 指令实现 WiFi 连接(
AT+CWJAP)和 MQTT 配置,理解 “串口指令→模块动作” 的映射关系; - 云平台对接:掌握阿里云 IoT 的产品 / 设备创建、物模型定义、MQTT 连接参数(三元组、签名)的核心作用;
- 数据链路:清晰 “传感器→STM32→WiFi 模块→云平台” 的全链路数据流向,能通过调试串口定位通信失败问题(如 WiFi 密码错误、签名计算错误)。
总结
今天实现了嵌入式设备的 “联网能力”,这是物联网开发的核心环节。通过 WiFi 模块和云平台,设备从 “单机运行” 升级为 “可远程监控的智能设备”,后续可扩展为:
- 接收云平台指令(如远程修改温湿度阈值);
- 集成 GPS 模块,上传位置信息;
- 使用 ESP32(带 WiFi + 蓝牙)替代 ESP8266,提升性能。

6939

被折叠的 条评论
为什么被折叠?



