【嵌入式开发学习】第12天:WiFi 模块通信与云平台对接(物联网入门)

核心目标:掌握 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 RXSTM32 发送 AT 指令到 ESP8266
STM32 USART2_RX(PA3)→ ESP8266 TXSTM32 接收 ESP8266 的响应
STM32 GND→ ESP8266 GND共地保证通信电平一致
ESP8266 VCC→ 3.3V 电源严禁接 5V,会烧毁模块
AHT10同第八天(SCL→PB6,SDA→PB7)温湿度数据采集

三、阿里云 IoT 平台配置(30 分钟,关键!)

云平台是数据的 “中转站” 和 “展示中心”,以阿里云 IoT 为例,步骤如下:

1. 创建产品与设备
  1. 登录阿里云 IoT 控制台(https://iot.console.aliyun.com/);
  2. 左侧 “设备管理→产品”→“创建产品”:
    • 产品名称:SmartTempHumi
    • 所属品类:自定义品类
    • 节点类型:设备
    • 联网方式:WiFi
    • 数据格式:JSON(便于解析);
  3. 产品创建后,进入 “设备”→“添加设备”:
    • 设备名称:Device001
    • 记录设备 “三元组”(ProductKey、DeviceName、DeviceSecret)—— 后续认证必须用到。
2. 定义物模型(数据格式)

物模型用于规范设备上传的数据格式(如温度、湿度的字段名和类型):

  1. 进入产品→“功能定义”→“添加自定义功能”:
    • 功能名称:temperature,标识符:temp,数据类型:float,单位:
    • 功能名称:humidity,标识符:humi,数据类型:float,单位:%RH
  2. 点击 “发布上线”,物模型生效。
3. 获取 MQTT 连接参数

阿里云 IoT 基于 MQTT 协议通信,需计算连接参数:

  • 客户端 ID:设备名称|securemode=3,signmethod=hmacsha1|
  • 用户名:设备名称&产品Key
  • 密码:通过三元组和连接参数计算的签名(可用阿里云提供的工具生成,后续代码中会实现签名函数)。

四、STM32 代码实现(60 分钟,分模块开发)

核心逻辑:STM32 定时采集温湿度→通过 USART2 向 ESP8266 发送 AT 指令→控制 ESP8266 连接 WiFi 和阿里云→上传数据到云平台。

1. 配置 CubeIDE 工程
  1. 启用外设:
    • 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 分钟)

  1. 模块调试:先用 USB-TTL 连接 ESP8266,通过串口助手发送 AT 指令,确认模块能正常响应、连接 WiFi;
  2. 代码下载:将程序下载到 STM32,通过 USART1 调试串口观察输出(WiFi 连接状态、云平台连接状态);
  3. 云平台查看:登录阿里云 IoT 控制台→设备→“运行状态”,可看到上传的温湿度数据;
  4. 手机查看:在阿里云 IoT 控制台 “产品→交互开发” 中配置简易 APP,扫码即可在手机上实时查看数据。

六、第十二天必掌握的 3 个核心点

  1. ESP8266 控制:通过 AT 指令实现 WiFi 连接(AT+CWJAP)和 MQTT 配置,理解 “串口指令→模块动作” 的映射关系;
  2. 云平台对接:掌握阿里云 IoT 的产品 / 设备创建、物模型定义、MQTT 连接参数(三元组、签名)的核心作用;
  3. 数据链路:清晰 “传感器→STM32→WiFi 模块→云平台” 的全链路数据流向,能通过调试串口定位通信失败问题(如 WiFi 密码错误、签名计算错误)。

总结

今天实现了嵌入式设备的 “联网能力”,这是物联网开发的核心环节。通过 WiFi 模块和云平台,设备从 “单机运行” 升级为 “可远程监控的智能设备”,后续可扩展为:

  • 接收云平台指令(如远程修改温湿度阈值);
  • 集成 GPS 模块,上传位置信息;
  • 使用 ESP32(带 WiFi + 蓝牙)替代 ESP8266,提升性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值