一、硬件选型与网络配置
推荐STM32型号
STM32F407ZGT6:内置以太网MAC,支持LWIP协议栈(适合有线连接)
STM32F103C8T6 + ESP8266:通过UART连接Wi-Fi模块(适合无线场景)
网络接口初始化
以太网配置(以STM32F4为例):
// 初始化以太网MAC和PHY ETH_InitTypeDef ETH_InitStruct = { 0}; ETH_InitStruct.Instance = ETH; ETH_InitStruct.Init.ClockRange = ETH_CLOCK_RANGE_0; ETH_InitStruct.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; HAL_ETH_Init(Ð_InitStruct);Wi-Fi配置(ESP8266 AT指令):
HAL_UART_Transmit(&huart2, (uint8_t*)"AT+RST\r\n", 8, 1000); // 重启模块 HAL_Delay(2000); HAL_UART_Transmit(&huart2, (uint8_t*)"AT+CWMODE=1\r\n", 12, 1000); // STA模式 HAL_Delay(500);```
二、MQTT二次开发包选择
推荐库
Eclipse Paho MQTT Embedded-C:轻量级,支持MQTT 3.1.1,适合资源受限设备
MQTT-C:极简设计,代码量少(约2KB),适合STM32F1等低内存型号
库文件集成
将
MQTTClient.h、MQTTConnect.c、MQTTPublish.c等文件添加到工程配置编译器头文件路径:
INC_DIRS += -I./Middlewares/Third_Party/Paho_MQTT/Inc```
三、核心代码实现
1. MQTT客户端初始化
#include "MQTTClient.h"
#define MQTT_CLIENT_ID "STM32_001"
#define MQTT_SERVER_IP "192.168.1.100"
#define MQTT_SERVER_PORT 1883
MQTTClient mqtt_client;
MQTTNetwork mqtt_net;
MQTTConnectOptions conn_opts = MQTTConnectOptions_initializer;
void mqtt_init() {
MQTTClient_Init(&mqtt_client, &mqtt_net, 256, mqtt_tx_buf, 256, mqtt_rx_buf, 256);
conn_opts.keepAliveInterval = 60; // 心跳间隔
conn_opts.cleansession = 1; // 清除会话
conn_opts.username.cstring = "user";
conn_opts.password.cstring = "pass";
MQTTConnect(&mqtt_client, &conn_opts);
}
2. 消息发布
void mqtt_publish(float temp, float humi) {
MQTTMessage msg;
msg.qos = QOS0;
msg.retained = 0;
msg.payload = (void*)"{\"temp\":%.2f,\"humi\":%.2f}", msg.payloadlen = 30;
MQTTPublish(&mqtt_client, "sensor/data", &msg);
}
3. 消息订阅与回调
void mqtt_subscribe() {
MQTTSubscribe(&mqtt_client, "cmd/control", QOS0, message_arrived);
}
void message_arrived(MessageData* md) {
MQTTMessage* msg = md->message;
printf("Received: %s (topic: %s)\r\n", msg->payload, md->topicName->cstring);
}
4. 心跳与网络维护
void mqtt_keepalive_timer() {
MQTTClient_Ping(&mqtt_client); // 发送PINGREQ
}
// 在FreeRTOS定时器回调中调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance == TIM2) {
mqtt_keepalive_timer();
}
}
四、网络适配层实现
TCP发送/接收函数
int32_t mqtt_network_send(MQTTNetwork* net, uint8_t* data, uint16_t len) { HAL_UART_Transmit(&huart2, data, len, 1000); // 通过UART发送到ESP8266 return len; } int32_t mqtt_network_recv(MQTTNetwork* net, uint8_t* data, uint16_t len, uint32_t timeout) { return HAL_UART_Receive(&huart2, data, len, timeout); }Wi-Fi连接管理
void wifi_connect() { HAL_UART_Transmit(&huart2, (uint8_t*)"AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n", 32, 5000); HAL_Delay(5000); }
参考代码 STM32MQTT客户端实现,使用MQTT二次开发包 www.youwenfan.com/contentalh/101781.html
五、测试流程
本地测试
使用Mosquitto搭建本地MQTT服务器:
mosquitto -c mosquitto.conf -p 1883
云端测试
阿里云IoT平台配置:
创建Product并定义Topic(如
/stm32/data)设备证书配置(ProductKey、DeviceName、DeviceSecret)
调试工具
MQTT.fx:模拟MQTT服务器,验证消息收发
Wireshark:抓包分析MQTT协议报文
六、常见问题解决
| 问题现象 | 解决方案 |
|---|---|
| 连接超时 | 检查IP地址、防火墙设置 |
| 消息丢失 | 提高QoS等级至1或2 |
| TLS握手失败 | 验证证书格式与服务器匹配 |
| 内存溢出 | 缩小MQTT_TX_BUF_SIZE |
七、扩展应用
OTA固件升级
- 通过MQTT发布OTA指令,触发STM32下载新固件
void handle_ota_cmd(char* payload) { if (strcmp(payload, "OTA_START") == 0) { download_firmware("ota_server_url"); } }多节点组网
- 使用MQTT桥接模式实现STM32集群通信
MQTTClient_subscribe(&client, "group/command", QOS1, group_message_handler);