全部例程

W55MH32使用MQTT协议连接阿里云

W55MH32

更新于 2026年9月16日

本篇总结

本例程在 W55MH32 上通过 MQTT 协议接入阿里云物联网平台,实现温湿度数据上报与属性设置主题的订阅。

🔑 KEIL MDK、UART调试、硬件TOE引擎、MQTT、DNS、DHCP

硬件平台:本例程基于 W55MH32L-EVB 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W55MH32L-EVB

本示例演示如何在 W55MH32 上通过 MQTT(消息队列遥测传输)协议连接阿里云物联网平台,实现设备与云端的双向数据交互。设备通过 TCP 连接阿里云 MQTT 服务器,使用一机一密方式(HMAC-SHA256 签名)进行认证登录,发布物模型数据,订阅属性设置主题接收云端指令。

前置工具准备

开始本例程前,请确认以下工具已安装:

  • WIZ UartTool V1.0:串口调试工具:点击下载
  • 阿里云物联网平台账号:注册并登录 阿里云物联网平台,创建产品和设备,获取 ProductKey、DeviceName、DeviceSecret
  • MQTT 客户端参数生成工具(可选):用于生成阿里云 MQTT 连接所需的 ClientId、Username、Password:参考文档

MQTT 协议简介

MQTT 是一种基于 发布/订阅模式的轻量级通信协议,构建于 TCP/IP 协议之上。由 IBM 在 1999 年发布,专为带宽有限、网络不稳定的远程通信场景设计,是物联网领域应用最广泛的协议之一。MQTT 协议的最大优点是:能以最少的代码和有限的带宽,为远程设备提供实时可靠的消息服务。

MQTT 协议的三个核心角色:

  • 发布者:向 Broker 发布消息,指定一个主题(Topic)
  • 订阅者:向 Broker 订阅感兴趣的主题,接收匹配的消息
  • Broker:消息代理,负责接收发布者的消息并转发给订阅者
特性说明
传输层基于 TCP 协议,端口 1883(明文)/ 8883(TLS 加密)
报文类型CONNECT、CONNACK、PUBLISH、SUBSCRIBE、PINGREQ 等 14 种
QoS 等级0(至多一次)、1(至少一次)、2(只有一次)
主题层级支持 "/" 分层和 "+"、"#" 通配符

阿里云物联网平台简介

阿里云物联网平台提供设备接入、设备管理、数据订阅和规则引擎等能力。本例程使用一机一密认证方式,设备需要预置 ProductKey、DeviceName、DeviceSecret 三个凭证。连接时根据阿里云规则生成 ClientId、Username、Password(HMAC-SHA256 签名)。接入域名格式为 {instanceId}.mqtt.iothub.aliyuncs.com:1883(企业版实例)。

硬件连接与拓扑

请注意:

本示例需要访问互联网,请确保 W55MH32 的网络环境及配置能够正常访问互联网(路由器需连接外网)。

  1. Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
  2. 网线连接开发板 RJ45 网口 到路由器 LAN 口,路由器需连接互联网
┌───────────┐ ┌─────────────────┐ ┌──────────────────┐
│ W55MH32 │──网线──│ 路由器/网关 │──互联网──│ 阿里云 IoT 平台 │
│ (MQTT │ │ (DHCP/DNS) │ │ {instanceId}.mqtt│
│ Client) │ │ 192.168.1.1 │ │ .iothub.aliyuncs│
└───────────┘ └─────────────────┘ │ .com :1883 │
└──────────────────┘
↑
DEBUG USB ──→ WIZ UartTool
网络拓扑:W55MH32 通过路由器接入互联网,连接阿里云物联网平台 MQTT 服务器(端口 1883)

工程结构

工程位于 SDK 内 1.SDK\ModuleDemo\WZTOE\MQTT_Aliyun\,核心文件如下:

MQTT_Aliyun/
├── Project/
│   └── Project.uvprojx       ← Keil 工程文件
└── USER/
    ├── main.c                ← 硬件初始化 + MQTT 主循环
    ├── do_mqtt/
    │   ├── do_mqtt.c         ← MQTT 主流程(mqtt_init / do_mqtt / json_decode)
    │   └── do_mqtt.h         ← MQTT 连接参数、消息结构
    ├── do_dns/
    │   ├── do_dns.c          ← DNS 域名解析
    │   └── do_dns.h
    ├── wiz_interface/
    │   ├── wiz_interface.c   ← PHY 检测 / 网络信息打印
    │   └── wiz_interface.h
    ├── tim/
    │   ├── bsp_tim.c         ← TIM3 1ms 定时器(MQTT/DHCP/DNS 时基)
    │   └── bsp_tim.h
    ├── uart/
    │   ├── bsp_uart.c        ← 调试串口 + printf 重定向
    │   └── bsp_uart.h
    └── delay/
        └── delay.c/h          ← SysTick 毫秒延时

本例程相比 DNS 章节的核心新增:阿里云 MQTT 签名认证和 发布/订阅状态机。

步骤1:注册 MQTT 定时中断函数

文件:USER/tim/bsp_tim.c — 将 MilliTimer_Handler() 注册到 1ms 定时器中断中,为 MQTT 协议栈提供时基。同时每 1000ms 执行一次 DHCP 和 DNS 的时间处理。

void TIM3_IRQHandler(void)
{
    static uint32_t tim3_1ms_count = 0;
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        tim3_1ms_count++;
        MilliTimer_Handler();

        if (tim3_1ms_count >= 1000)
        {
            DHCP_time_handler();
            DNS_time_handler();
            tim3_1ms_count = 0;
        }

        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}

步骤2:配置阿里云连接参数

文件:USER/do_mqtt/do_mqtt.c — 定义 MQTT 连接参数,包括服务器域名、端口、客户端 ID、用户名、密码(HMAC-SHA256 签名)、发布主题、订阅主题。在阿里云物联网平台创建产品和设备后,获取 ProductKey、DeviceName、DeviceSecret,并按阿里云规则生成 ClientId、Username 和 Password。

mqttconn mqtt_params = {
    .mqttHostUrl = "iot-06z00dbroeg8dx3.mqtt.iothub.aliyuncs.com",
    .server_ip   = {0},
    .port        = 1883,
    .clientid    = "ieojgBm5q2c.W55MH32|securemode=2,signmethod=hmacsha256,timestamp=1737098648080|",
    .username    = "W55MH32&XXXXXXXXXXX",
    .passwd      = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    .pubtopic    = "/sys/iXXXXXXXXXXX/W55MH32/thing/event/property/post",
    .subtopic    = "/sys/iXXXXXXXXXXX/W55MH32/thing/service/property/set",
    .pubQoS      = QOS0,
};

如果你想自定义

  • mqttHostUrl → 接入域名格式:{instanceId}.mqtt.iothub.aliyuncs.com(企业版实例)或 {ProductKey}.iot-as-mqtt.{RegionId}.aliyuncs.com(公共实例)
  • clientid → 格式:{instanceId}.{DeviceName}|securemode=2,signmethod=hmacsha256,timestamp={timestamp}|,securemode=2 为 TCP 直连
  • username → 格式:{DeviceName}&{instanceId}
  • passwd → 由 DeviceSecret 对拼接字符串进行 HMAC-SHA256 签名生成
  • pubtopic → 属性上报:/sys/{instanceId}/{DeviceName}/thing/event/property/post
  • subtopic → 属性设置:/sys/{instanceId}/{DeviceName}/thing/service/property/set

步骤3:MQTT 初始化与连接

文件:USER/do_mqtt/do_mqtt.c — 函数 mqtt_init() 完成 DNS 解析、TCP 连接、MQTT 客户端初始化和连接参数配置。阿里云使用明文 MQTT(端口 1883),通过 HMAC-SHA256 签名进行认证。

void mqtt_init(uint8_t sn, uint8_t *send_buf, uint8_t *recv_buf)
{
    wiz_NetInfo get_info = {0};
    wizchip_getnetinfo(&get_info);

    /* DNS 解析阿里云接入域名 */
    if (do_dns(send_buf, (uint8_t *)mqtt_params.mqttHostUrl, mqtt_params.server_ip))
    {
        while (1);
    }

    NewNetwork(&n, sn);
    ConnectNetwork(&n, mqtt_params.server_ip, mqtt_params.port);
    MQTTClientInit(&c, &n, 1000, send_buf, MQTT_ETHERNET_MAX_SIZE, recv_buf, MQTT_ETHERNET_MAX_SIZE);

    /* MQTT 连接参数 */
    data.MQTTVersion       = 4;
    data.clientID.cstring  = mqtt_params.clientid;
    data.username.cstring  = mqtt_params.username;
    data.password.cstring  = mqtt_params.passwd;
    data.keepAliveInterval = 30;
    data.cleansession      = 1;
}

执行逻辑:先通过 do_dns() 解析阿里云接入域名获取 IP,再建立 TCP 连接、初始化 MQTT 客户端,最后填入连接参数(客户端 ID、用户名、密码、keepAlive 30s、clean session)。

步骤4:do_mqtt() 状态机处理

文件:USER/do_mqtt/do_mqtt.c — 函数 do_mqtt() 采用状态机方式运行:连接服务器(CONN)→ 订阅主题(SUB)→ 发布消息(PUB_MESSAGE)→ 保活(KEEPALIVE)→ 接收处理(RECV)。

void do_mqtt(void)
{
    uint8_t ret;
    switch (run_status)
    {
    case CONN:
    {
        ret = MQTTConnect(&c, &data);
        printf("Connect to the MQTT server: %d.%d.%d.%d:%d\r\n",
               mqtt_params.server_ip[0], mqtt_params.server_ip[1],
               mqtt_params.server_ip[2], mqtt_params.server_ip[3],
               mqtt_params.port);
        printf("Connected:%s\r\n\r\n", ret == SUCCESSS ? "success" : "failed");
        if (ret != SUCCESSS)
        {
            run_status = ERR;
        }
        else
        {
            run_status = SUB;
        }
        break;
    }
    case SUB:
    {
        ret = MQTTSubscribe(&c, mqtt_params.subtopic, mqtt_params.subQoS, messageArrived);
        printf("Subscribing to %s\r\n", mqtt_params.subtopic);
        printf("Subscribed:%s\r\n\r\n", ret == SUCCESSS ? "success" : "failed");
        if (ret != SUCCESSS)
        {
            run_status = ERR;
        }
        else
        {
            run_status = PUB_MESSAGE;
        }
        break;
    }
    case PUB_MESSAGE:
    {
        pubmessage.qos = QOS0;
        pubmessage.payload = "{\"id\":\"123\",\"version\":\"1.0\",\"params\":{\"CurrentTemperature\":26.6,},\"method\":\"thing.event.property.post\"}";
        pubmessage.payloadlen = strlen(pubmessage.payload);
        ret = MQTTPublish(&c, (char *)&(mqtt_params.pubtopic), &pubmessage);
        if (ret != SUCCESSS)
        {
            run_status = ERR;
        }
        else
        {
            printf("publish:%s,%s\r\n\r\n", mqtt_params.pubtopic, (char *)pubmessage.payload);
            run_status = KEEPALIVE;
        }
        break;
    }
    case KEEPALIVE:
    {
        if (MQTTYield(&c, 30) != SUCCESSS)
        {
            run_status = ERR;
        }
    }
    case RECV:
    {
        if (mqtt_recv_flag)
        {
            mqtt_recv_flag = 0;
            json_decode(mqtt_recv_msg);
        }
        break;
    }
    case ERR:
        printf("system ERROR!");
        delay_ms(1000);
        break;
    default:
        break;
    }
}

发布消息使用阿里云物模型 JSON 数据格式:{"id":"123","version":"1.0","params":{"CurrentTemperature":26.6,},"method":"thing.event.property.post"},包含 id、version、params 和 method 字段。

步骤5:接收消息处理机制

文件:USER/do_mqtt/do_mqtt.c — 当设备收到阿里云平台下发的订阅消息后,先进入 messageArrived() 回调函数打印消息并保存,随后主状态机在 RECV 分支中调用 json_decode() 用 cJSON 解析 JSON 数据并完成 LED 状态判断。

void messageArrived(MessageData *md)
{
    char topicname[64] = {0};
    char msg[512] = {0};

    sprintf(topicname, "%.*s", (int)md->topicName->lenstring.len, md->topicName->lenstring.data);
    sprintf(msg, "%.*s", (int)md->message->payloadlen, (char *)md->message->payload);
    printf("recv:%s,%s\r\n\r\n", topicname, msg);

    mqtt_recv_flag = 1;
    memset(mqtt_recv_msg, 0, sizeof(mqtt_recv_msg));
    memcpy(mqtt_recv_msg, msg, strlen(msg));
}

json_decode() 用 cJSON 解析阿里云下发的 JSON 指令,从 params 字段中提取 LEDSwitch 的值,并打印 LED 状态。

void json_decode(char *msg)
{
    cJSON *jsondata = NULL;
    cJSON *params = NULL;
    cJSON *LED = NULL;

    jsondata = cJSON_Parse(msg);
    if (jsondata == NULL)
    {
        printf("json parse fail.\r\n");
        return;
    }

    params = cJSON_GetObjectItem(jsondata, "params");
    LED = cJSON_GetObjectItem(params, "LEDSwitch");

    if (LED->valueint == 1)
    {
        printf("LED ON\r\n");
    }
    else
    {
        printf("LED OFF\r\n");
    }

    cJSON_Delete(jsondata);
}

JSON 解析说明

json_decode() 使用 cJSON 库解析阿里云下发的 JSON,从 params 中提取 LEDSwitch 字段,打印对应状态。阿里云下发的属性设置指令格式为 {"params":{"LEDSwitch":1}}。

运行验证

打开 WIZ UartTool V1.0,连接 DEBUG USB 对应 COM 口(115200 / 8N1)。烧录例程运行后,程序首先进行 PHY 链路检测,然后通过 DHCP 获取网络参数,并完成 DNS 解析与 TCP 连接,最后连接阿里云物联网平台的 MQTT 服务器。预期串口输出如下:

W55MH32 MQTT Aliyun example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
DHCP running
DHCP success!
====================================================================================================
 W55MH32 network configuration : DHCP

 MAC         : 00:08:DC:00:0E:9A
 IP          : 192.168.1.6
 Subnet Mask : 255.255.255.0
 Gateway     : 192.168.1.1
 DNS         : 192.168.1.1
====================================================================================================

> Translated iot-06z00dbroeg8dx3.mqtt.iothub.aliyuncs.com to 101.133.196.127
Connect to the MQTT server: 101.133.196.127:1883
Connected:success

Subscribing to /sys/ieojgBm5q2c/W55MH32/thing/service/property/set
Subscribed:success

连接成功后,设备会订阅属性设置主题,并周期性向属性上报主题发布数据。在阿里云物联网平台的设备详情页可查看上报的数据,也可通过平台在线调试功能下发属性设置指令控制 LED 。

WIZ UartTool 串口输出 — MQTT 连接阿里云全流程(链路检测 → DHCP → DNS 解析 iot-06z00dbroeg8dx3.mqtt.iothub.aliyuncs.com)
WIZ UartTool 串口输出 — 接收阿里云属性设置指令 LEDSwitch:1,执行 LED ON 并回复成功响应


常见问题

Q: 阿里云一机一密认证如何生成 Password

Password 由 DeviceSecret 对拼接字符串进行 HMAC-SHA256 签名生成。拼接内容按字母序排列:clientId{DeviceName}deviceName{DeviceName}productKey{ProductKey}timestamp{timestamp}。signmethod 指定为 hmacsha256。可使用阿里云提供的 MQTT 参数生成工具辅助计算。

Q: MQTT 连接失败如何排查

首先确认网络能正常访问互联网;检查 DNS 是否成功解析接入域名;确认 ClientId、Username、Password 配置正确(Password 为 HMAC-SHA256 签名);检查 securemode 是否正确(TCP 直连为 2);阿里云平台确认设备已创建且处于启用状态;检查 ProductKey、DeviceName、DeviceSecret 是否匹配。

Q: 阿里云物模型的 Topic 命名规则是什么

阿里云物模型使用 /sys/{instanceId}/{DeviceName}/thing/... 格式。属性上报:/sys/{instanceId}/{DeviceName}/thing/event/property/post;属性设置:/sys/{instanceId}/{DeviceName}/thing/service/property/set。其中 instanceId 为企业版实例 ID。

Q: 发布的 JSON 数据格式有什么要求

阿里云物模型要求 JSON 数据包含 id、version、params、method 字段。params 中为属性键值对,属性名需与平台定义的物模型属性标识一致。method 固定为 thing.event.property.post。例如 {"id":"123","version":"1.0","params":{"CurrentTemperature":26.6},"method":"thing.event.property.post"}。

Q: securemode 有什么区别

securemode=2 为 TCP 直连模式(明文,端口 1883);securemode=3 为 TLS 直连模式(加密,端口 8883)。本例程使用 securemode=2 的 TCP 直连方式。如果需要更高安全性,可使用 securemode=3 配合 TLS 加密,参考 MQTTS 章节。

总结

本文讲解了如何在 W55MH32 芯片上通过 MQTT 协议连接阿里云物联网平台,通过实战例程展示了完整的接入流程:

  • MQTT 协议:基于发布/订阅模式的轻量级物联网通信协议,运行在 TCP 之上
  • 阿里云接入:DNS 解析 → TCP 连接 → 一机一密签名认证登录 → 订阅/发布
  • 认证机制:使用 HMAC-SHA256 签名生成 Password,ClientId 携带 securemode 和 signmethod 参数
  • 关键 API:MQTTConnect / MQTTSubscribe / MQTTPublish 实现连接、订阅和发布
  • 消息收发:messageArrived() 回调接收,json_decode() 用 cJSON 解析阿里云下发的 JSON 指令

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5 配套开发板

Andy

W5500 技术支持专家