本文为 WIZnet W55RP20 芯片 c语言 教程第 13篇,基于官方最新固件编写,代码均经过实际验证,可直接烧录运行。
版权声明:本文为 WIZnet 官方原创技术文章,转载请注明出处。

上一篇实战教程,我们完成了W55RP20芯片MQTT协议基础通信验证,实现了与阿里云服务器的消息收发。本篇内容我们聚焦工业级物联网场景,实现W55RP20通过MQTT协议与OneNET物联网平台对接,完成温湿度数据定时上传,掌握OneNET平台设备注册、MQTT连接配置、物模型数据格式封装等核心技能,适配工业级设备上云需求。

W55RP20集成硬件 TCP/IP 协议栈,搭配MQTT客户端库,通过C语言编程即可实现与OneNET平台的稳定通信,无需关心底层Socket细节,依托WIZnet官方驱动库和OneNET物模型规范,大幅降低嵌入式设备上云开发门槛,适用于智能监测、数据采集等各类物联网场景。

学完本文,你将掌握:

  • OneNET物联网平台设备注册、产品创建及MQTT连接参数获取

  • W55RP20连接OneNET平台的C语言实现(完整可运行代码)

  • OneNET物模型JSON payload构造(标准格式自动封装)

  • DNS解析优化、定时数据上传、心跳保活等稳定机制实现

  • OneNET平台数据查看、调试及常见问题排查方法

本节课核心目标:

  • 完成OneNET平台产品创建、设备注册,获取MQTT连接参数

  • 理解OneNET MQTT连接规范、物模型数据格式要求及鉴权原理

  • 编译、下载完整C语言代码,实现W55RP20与OneNET平台连接

  • 完成温湿度数据定时上传,在OneNET平台查看实时数据

  • 掌握W55RP20与OneNET对接的常见故障快速排查方法

系列教程学习路径

本专栏共 16 篇,循序渐进覆盖 W55RP20-EVB-Pico 模块 C语言开发全流程:

  1. 第 1 篇:静态 IP 配置与网络基础

  2. 第 2 篇:DHCP 自动联网与网络诊断

  3. 第 3 篇:TCP Client 客户端通信

  4. 第 4 篇:TCP Server 服务端通信

  5. 第 5 篇:UDP 单播数据通信

  6. 第 6 篇:UDP 组播/广播数据通信

  7. 第 7 篇:DNS 域名解析

  8. 第 8 篇:NTP 从网络获取时间

  9. 第 9 篇:HTTP Client 客户端请求

  10. 第 10 篇:HTTP Server 服务端搭建

  11. 第 11 篇:HTTP 协议与 OneNET 平台数据上云

  12. 第 12 篇:MQTT 协议基础通信验证

  13. 第 13 篇:MQTT 协议与阿里云平台对接

  14. 第 14 篇:MQTT 协议与 OneNET 平台对接(本文)

  15. 第 15 篇:MQTT 协议与 ThingSpeak 平台对接

  16. 第 16 篇:Modbus 工业协议通信

建议收藏本专栏,跟随教程逐步学习,所有代码均会同步更新至官方 Gitee 仓库

目录

一、准备工作

1.1 软件准备

1.2 硬件准备

1.3 OneNET平台准备

二、W55RP20 C语言开发环境搭建

2.1 驱动库配置

2.2 固件烧录

三、硬件连接与串口配置

3.1 硬件连接

3.1.1 基础连接(供电+调试)

3.1.2 以太网连接

3.1.3 模块与开发板接线(分离式模块适用)

3.2 串口调试配置

四、OneNET MQTT协议规范解析

4.1 核心连接规范(必看)

4.2 物模型数据格式规范

4.3 标准主题格式(必配)

4.4 极简工作流程

五、核心C语言代码复制与编译烧录

5.1 依赖库说明

5.2 完整C语言代码(主程序)

5.3 代码关键配置说明(必看,否则连接失败)

5.4 编译与烧录步骤

六、运行结果与OneNET平台验证

6.1 串口输出结果

6.2 OneNET平台数据验证

七、常见问题一站式排查

八、W55RP20 核心优势对比

九、典型应用场景

十. 系列预告与资源获取

10.1系列预告

10.2 资源获取

一、准备工作

1.1 软件准备

所需软件均为免费版本,按要求下载安装即可,无需额外付费,适配C语言开发需求,新增OneNET平台相关操作工具。

软件名称

版本要求

下载地址

说明

VS Code(搭配C/C++插件)

最新稳定版

VS Code 官方下载

轻量级代码编辑器,支持C语言语法高亮、编译调试,新手友好

W55RP20-EVB-Pico 模块 C语言驱动库

最新稳定版

WIZnet 官方固件/驱动库下载

专为 W55RP20-EVB-Pico 模块编写,已集成 WIZnet 硬件驱动、TCP/IP协议栈及MQTT客户端库

串口调试助手(如SecureCRT)

任意版本

官方下载或第三方工具

用于查看串口输出的运行日志、调试信息,定位连接和数据上传问题

OneNET物联网平台

在线版

OneNET物联网平台官网

创建产品、注册设备,获取MQTT连接参数,查看上传的温湿度数据

1.2 硬件准备

  • W55RP20-EVB-Pico × 1

  • Micro USB 数据线(必须支持数据传输,不能使用纯充电线)× 1

  • 标准网线 × 1

  • 开启 DHCP 功能的路由器 / 交换机 × 1(用于获取网络参数,实现 DNS 解析)

1.3 OneNET平台准备

在进行代码开发前,需先在OneNET平台完成产品创建和设备注册,获取MQTT连接所需的核心参数(产品ID、设备名称、Token),步骤如下:

  1. 登录OneNET物联网平台(需注册账号,个人版免费),进入「物联网核心套件」→「产 品」,点击「创建产品」;

  2. 产品配置:产品名称自定义(如W55RP20温湿度采集),协议选择「MQTT」,数据格式选择「JSON」,设备类型选择「直连设备」,点击「确认创建」;

  3. 添加设备:进入创建好的产品,点击「设备管理」→「添加设备」,设备名称自定义(如W5500_01),点击「确认」,完成设备注册;

  4. 获取连接参数:进入设备详情页,记录以下3个核心参数(后续替换到代码中):

  5. 产品ID(ONENET_PRODUCT_ID):产品详情页顶部获取,为字符串格式

  6. 设备名称(ONENET_DEVICE_NAME):创建设备时自定义的名称

  7. Token(ONENET_MQTT_PASSWORD):使用密码生成工具:https://open.iot.10086.cn/doc/iot_platform/images/tools/token.exe 注注意Token有有效期,过期需重新生成

  8. 添加物模型(必做):进入产品「物模型定义」,添加「temp」(温度,浮点型)和「humi」(湿度,浮点型)两个属性,字段名需与代码中一致,用于在平台直观查看温湿度数据。

二、W55RP20 C语言开发环境搭建

2.1 驱动库配置

1. 下载W55RP20官方C语言驱动库,解压后得到核心文件(包含wizchip_conf.h、socket.h、mqtt_interface.h、MQTTClient.h等);

2. 打开VS Code,新建项目,将驱动库中的头文件(.h)放入项目include文件夹,源文件(.c)放入src文件夹;

3. 配置项目编译选项,指定编译器(如ARM GCC),关联驱动库文件,确保编译时能正常调用硬件驱动、网络接口和MQTT相关函数。

2.2 固件烧录

W55RP20-EVB-Pico 模块完全兼容树莓派 Pico 的 UF2 固件烧录方式,操作简单无需额外烧录器,新手可快速上手:

  1. 按住 RP2040 开发板上的 BOOTSEL 按键不放;

  2. 使用 Micro USB 数据线连接开发板与电脑;

  3. 待电脑识别出名为 RPI-RP2 的 U 盘后,松开 BOOTSEL 按键;

  4. 将编译生成的 UF2 固件文件拖拽到 U 盘中;

  5. 开发板会自动重启,固件烧录完成。

三、硬件连接与串口配置

3.1 硬件连接

W55RP20-EVB-Pico 模块连接分为两步,分别实现供电/调试和以太网连接,操作简单,无需复杂接线,与基础MQTT实战连接方式一致:

3.1.1 基础连接(供电+调试)

使用 Micro USB 数据线连接 RP2040 开发板与电脑,用于开发板供电、固件烧录和串口调试。

3.1.2 以太网连接

使用网线连接 W55RP20-EVB-Pico 模块的以太网接口与路由器的 LAN 口(或直接连接电脑网口,需手动配置电脑 IP 与开发板同网段)。

3.1.3 模块与开发板接线(分离式模块适用)

若使用分离式模块与开发板,需按以下引脚对应连接(SPI 通信):

【硬件预留】此处插入硬件连接示意图

3.2 串口调试配置

打开vscode串口调试助手,按以下参数配置,用于查看开发板运行日志和调试信息,定位OneNET MQTT连接和数据上传问题:

  1. 波特率:115200

  2. 数据位:8

  3. 停止位:1

  4. 校验位:无

  5. 流控:无

  6. 选择开发板对应的串口(通常显示为 COMx),点击打开串口。

四、OneNET MQTT协议规范解析

OneNET平台采用MQTT 3.1.1协议(与代码中配置一致),基于发布/订阅模式实现设备与平台的双向通信,与公共MQTT服务器相比,核心差异在于连接鉴权严格物模型数据格式规范,这也是开发的重点和难点。

4.1 核心连接规范(必看)

  • MQTT版本:必须使用3.1.1版本(代码中配置为MQTTVersion = 4),与OneNET平台完全兼容;

  • 服务器地址:固定为「studio-mqtt.heclouds.com」(OneNET MQTT官方域名),无需修改地域参数;

  • 端口:使用1883(非加密端口,适合开发调试;生产环境可使用8883加密端口);

  • 连接参数:ClientID=设备名称,Username=产品ID,Password=平台生成的Token,三者必须严格匹配,否则会连接失败。

4.2 物模型数据格式规范

OneNET平台要求设备上传的数据必须为指定JSON格式,核心包含id、version、params三个字段,示例如下:

{ "id":"123456789", "version":"1.0", "params":{ "temp":{ "value":35.7 }, "humi":{ "value":60.2 } } }

说明:

  • id:随机数或时间戳,用于标识一条消息,避免重复,代码中自动生成;

  • version:固定为「1.0」,表示物模型数据格式版本;

  • params:设备上传的具体数据,字段名(temp、humi)需与OneNET物模型中定义的属性名一致,value为具体数值;

  • 无需手动添加time字段,代码中已优化为极简格式,确保平台正常解析。

4.3 标准主题格式(必配)

OneNET物模型通信需使用固定主题,无需自定义,替换产品ID和设备名称即可:

  • 属性上报主题(设备→平台):$sys/产品ID/设备名称/thing/property/post

  • 上报回复主题(平台→设备):$sys/产品ID/设备名称/thing/property/post/reply

代码中已封装好主题格式,只需替换产品ID和设备名称,无需手动拼接。

4.4 极简工作流程

  1. W55RP20通过DNS解析OneNET MQTT服务器域名,获取服务器IP;

  2. 使用OneNET平台提供的产品ID、设备名称、Token,建立MQTT连接;

  3. W55RP20按OneNET物模型规范封装温湿度数据(JSON格式),向上报主题发布数据;

  4. OneNET平台接收数据,在设备详情页显示实时温湿度数据,同时向回复主题发送确认消息,设备接收并打印。

五、核心C语言代码复制与编译烧录

5.1 依赖库说明

核心依赖 WIZnet 官方驱动库(包含wizchip_conf.h、socket.h、mqtt_interface.h、MQTTClient.h等),用于实现W55RP20硬件初始化、网络连接、DNS解析及MQTT客户端的连接、发布、订阅等基础功能;无需额外添加OneNET专用库,代码中已集成连接配置、物模型JSON封装和消息回调逻辑,直接关联到项目中即可使用。

5.2 完整C语言代码(主程序)

将以下代码复制到VS Code项目的主文件(如main.c)中,重点替换OneNET平台获取的连接参数,编译生成UF2固件后烧录到开发板,代码注释清晰,关键配置部分已标注,可直接修改。

/**
    Copyright (c) 2021 WIZnet Co.,Ltd
    Modified for W55RP20 with OneNET MQTT (final fixed version)
    SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include <string.h>
#include "port_common.h"
#include "wizchip_conf.h"
#include "wizchip_spi.h"
#include "mqtt_interface.h"
#include "MQTTClient.h"
#include "timer.h"
#include "time.h"
#include "dns.h"

/* Buffer */
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

/* Socket */
#define SOCKET_MQTT 0
#define SOCKET_DNS  3

/* Port */
#define PORT_MQTT 1883

/* Timeout */
#define DEFAULT_TIMEOUT 1000

/* ========== OneNET 配置(请根据实际修改)========== */
#define ONENET_PRODUCT_ID   "ZGB6zBD0nS"               // 产品ID
#define ONENET_DEVICE_NAME  "led"                      // 设备名称
// MQTT Password(Token),从OneNET设备详情页复制,注意时效性
#define ONENET_MQTT_PASSWORD "version=2018-10-31&res=products%2FZGB6zBD0nS%2Fdevices%2Fled&et=1780016971&method=md5&sign=AAMTeit90OTmwPpugN%2Fe%2Bg%3D%3D"

#define ONENET_MQTT_DOMAIN  "studio-mqtt.heclouds.com" // OneNET MQTT服务器域名

/* 物模型主题 */
#define PROPERTY_POST_TOPIC "$sys/" ONENET_PRODUCT_ID "/" ONENET_DEVICE_NAME "/thing/property/post"
#define PROPERTY_POST_REPLY_TOPIC "$sys/" ONENET_PRODUCT_ID "/" ONENET_DEVICE_NAME "/thing/property/post/reply"

/* 温湿度数据(模拟值,可替换为真实传感器) */
#define TEMPERATURE_VALUE 45.6
#define HUMIDITY_VALUE    68.1

/* 发布周期(毫秒) */
#define MQTT_PUBLISH_PERIOD (1000 * 10)
#define MQTT_KEEP_ALIVE 60

/* ========== 网络配置(根据实际环境修改)========== */
static wiz_NetInfo g_net_info = {
    .mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56},
    .ip = {192, 168, 1, 128},
    .sn = {255, 255, 255, 0},
    .gw = {192, 168, 1, 1},
    .dns = {8, 8, 8, 8},
#if _WIZCHIP_ > W5500
    .lla = {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0xdc, 0xff, 0xfe, 0x57, 0x57, 0x25},
    .gua = {0},
    .sn6 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    .gw6 = {0},
    .dns6 = {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88},
    .ipmode = NETINFO_STATIC_ALL
#else
    .dhcp = NETINFO_STATIC
#endif
};

/* DNS解析结果存储 */
static uint8_t g_mqtt_broker_ip[4] = {0};

/* MQTT相关变量 */
static uint8_t g_mqtt_send_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t g_mqtt_recv_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static Network g_mqtt_network;
static MQTTClient g_mqtt_client;
static MQTTPacket_connectData g_mqtt_packet_connect_data = MQTTPacket_connectData_initializer;
static MQTTMessage g_mqtt_message;

static volatile uint32_t g_msec_cnt = 0;

/* DNS解析缓冲区 */
static uint8_t g_dns_buf[ETHERNET_BUF_MAX_SIZE] = {0};

/* 函数声明 */
static void repeating_timer_callback(void);
static time_t millis(void);
static void build_onenet_payload(char *payload, int max_len, float temperature, float humidity);
static int do_dns(const char *domain_name, uint8_t *ip_addr);
static void message_arrived(MessageData *msg_data);

/**
 * @brief DNS域名解析函数
 */
static int do_dns(const char *domain_name, uint8_t *ip_addr)
{
    int8_t ret = 0;
    uint8_t dns_ip[4];
    
    dns_ip[0] = g_net_info.dns[0];
    dns_ip[1] = g_net_info.dns[1];
    dns_ip[2] = g_net_info.dns[2];
    dns_ip[3] = g_net_info.dns[3];
    
    if (dns_ip[0] == 0 && dns_ip[1] == 0 && dns_ip[2] == 0 && dns_ip[3] == 0) {
        dns_ip[0] = g_net_info.gw[0];
        dns_ip[1] = g_net_info.gw[1];
        dns_ip[2] = g_net_info.gw[2];
        dns_ip[3] = g_net_info.gw[3];
        printf("DNS: Using gateway as DNS server %d.%d.%d.%d\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
    } else {
        printf("DNS: Using DNS server %d.%d.%d.%d\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
    }
    
    printf("DNS: Resolving domain: %s\n", domain_name);
    
    DNS_init(SOCKET_DNS, g_dns_buf);
    ret = DNS_run(dns_ip, (uint8_t *)domain_name, ip_addr);
    
    if (ret == 1) {
        printf("DNS: Success! IP: %d.%d.%d.%d\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
        return 0;
    } else {
        printf("DNS: Failed! Error: %d\n", ret);
        return -1;
    }
}

/**
 * @brief 构造OneNET物模型JSON数据(无多余空格,无可选time字段)
 */
static void build_onenet_payload(char *payload, int max_len, float temp, float humi) {
    snprintf(payload, max_len,
        "{\"id\":\"%lu\",\"version\":\"1.0\",\"params\":{\"temp\":{\"value\":%.1f},\"humi\":{\"value\":%.1f}}}",
        (unsigned long)millis(), temp, humi);
}

/* 定时器回调 */
static void repeating_timer_callback(void) {
    g_msec_cnt++;
    MilliTimer_Handler();
}

/* 获取毫秒数 */
static time_t millis(void) {
    return g_msec_cnt;
}

/* 收到MQTT消息的回调(订阅回复主题) */
static void message_arrived(MessageData *msg_data) {
    MQTTMessage *msg = msg_data->message;
    printf("Reply received: topic=%.*s, payload=%.*s\n",
           msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data,
           (int)msg->payloadlen, (char*)msg->payload);
}

/**
 * @brief 主函数
 */
int main() {
    int32_t retval = 0;
    uint32_t start_ms = 0;
    uint32_t end_ms = 0;
    char payload[256];

    stdio_init_all();
    sleep_ms(3000);
    printf("\r\n=== W55RP20 OneNET MQTT Demo (Final Fixed Version) ===\r\n");

    wizchip_spi_initialize();
    wizchip_cris_initialize();
    wizchip_reset();
    wizchip_initialize();
    wizchip_check();
    wizchip_1ms_timer_initialize(repeating_timer_callback);

    network_initialize(g_net_info);
    print_network_information(g_net_info);

    /* DNS解析 */
    printf("\n--- DNS Resolution Phase ---\n");
    int dns_retry = 0;
    while (do_dns(ONENET_MQTT_DOMAIN, g_mqtt_broker_ip) != 0) {
        dns_retry++;
        if (dns_retry >= 3) {
            printf("DNS resolution failed after 3 attempts!\n");
            while (1);
        }
        printf("Retry %d in 3 seconds...\n", dns_retry);
        sleep_ms(3000);
    }

    /* TCP连接 */
    NewNetwork(&g_mqtt_network, SOCKET_MQTT);
    printf("Connecting to OneNET MQTT broker at %d.%d.%d.%d:%d...\n",
           g_mqtt_broker_ip[0], g_mqtt_broker_ip[1], 
           g_mqtt_broker_ip[2], g_mqtt_broker_ip[3], PORT_MQTT);
    
    retval = ConnectNetwork(&g_mqtt_network, g_mqtt_broker_ip, PORT_MQTT);
    if (retval != 1) {
        printf("Network connect failed! retval=%d\n", retval);
        while (1);
    }
    printf("Network connected.\n");

    /* MQTT初始化 */
    MQTTClientInit(&g_mqtt_client, &g_mqtt_network, DEFAULT_TIMEOUT,
                   g_mqtt_send_buf, ETHERNET_BUF_MAX_SIZE,
                   g_mqtt_recv_buf, ETHERNET_BUF_MAX_SIZE);

    /* 关键:MQTT协议版本 4 = 3.1.1 */
    g_mqtt_packet_connect_data.MQTTVersion = 4;
    g_mqtt_packet_connect_data.cleansession = 1;
    g_mqtt_packet_connect_data.willFlag = 0;
    g_mqtt_packet_connect_data.keepAliveInterval = MQTT_KEEP_ALIVE;
    g_mqtt_packet_connect_data.clientID.cstring = ONENET_DEVICE_NAME;
    g_mqtt_packet_connect_data.username.cstring = ONENET_PRODUCT_ID;
    g_mqtt_packet_connect_data.password.cstring = ONENET_MQTT_PASSWORD;

    printf("MQTT Connecting to OneNET...\n");
    retval = MQTTConnect(&g_mqtt_client, &g_mqtt_packet_connect_data);
    if (retval < 0) {
        printf("MQTT connect failed: %d\n", retval);
        while (1);
    }
    printf("MQTT connected to OneNET Platform!\n");

    /* 订阅回复主题(用于获取平台返回的错误信息) */
    retval = MQTTSubscribe(&g_mqtt_client, PROPERTY_POST_REPLY_TOPIC, QOS0, message_arrived);
    if (retval < 0) {
        printf("Subscribe warning: %d\n", retval);
    } else {
        printf("Subscribed to reply topic: %s\n", PROPERTY_POST_REPLY_TOPIC);
    }

    sleep_ms(500);

    /* 发布使用 QOS0 便于测试 */
    g_mqtt_message.qos = QOS0;
    g_mqtt_message.retained = 0;
    g_mqtt_message.dup = 0;

    start_ms = millis();

    /* 主循环 */
    while (1) {
        end_ms = millis();

        if (end_ms >= start_ms + MQTT_PUBLISH_PERIOD) {
            build_onenet_payload(payload, sizeof(payload), TEMPERATURE_VALUE, HUMIDITY_VALUE);
            
            g_mqtt_message.payload = payload;
            g_mqtt_message.payloadlen = strlen(payload);

            printf("Topic: %s\n", PROPERTY_POST_TOPIC);
            printf("Payload: %s\n", payload);
            
            retval = MQTTPublish(&g_mqtt_client, PROPERTY_POST_TOPIC, &g_mqtt_message);
            if (retval < 0) {
                printf("Publish failed: %d\n", retval);
            } else {
                printf("Data published (QOS0)\n");
            }

            start_ms = millis();
        }

        /* Yield 超时 1000 毫秒,确保网络报文及时处理 */
        retval = MQTTYield(&g_mqtt_client, 1000);
        if (retval < 0) {
            printf("Yield error: %d\n", retval);
            sleep_ms(1000);
        }
    }

    return 0;
}

5.3 代码关键配置说明

  • OneNET MQTT参数(核心修改):

  • ONENET_PRODUCT_ID:替换为OneNET平台产品详情页获取的产品ID,为字符串格式,不可修改字符;

  • ONENET_DEVICE_NAME:替换为OneNET平台创建的设备名称,需与平台完全一致,大小写敏感;

  • ONENET_MQTT_PASSWORD:替换为OneNET设备生成工具复制的Token,注意Token有有效期,过期后需重新生成并替换;

  • ONENET_MQTT_DOMAIN:固定为「studio-mqtt.heclouds.com」,无需修改;

  • 物模型主题:代码中自动拼接,无需手动修改,替换产品ID和设备名称后自动生效。

网络配置:根据路由器实际网段修改g_net_info中的ip、gw、dns,确保与路由器在同一网段;DNS推荐使用阿里云DNS(223.5.5.5),提高解析成功率;

MQTT版本:代码中已配置为3.1.1版本(MQTTVersion = 4),无需修改,与OneNET平台兼容;

数据上传周期:MQTT_PUBLISH_PERIOD定义为10秒,可根据需求修改(单位:毫秒);

温湿度数据:当前为固定值(TEMPERATURE_VALUE、HUMIDITY_VALUE),实际开发中可替换为传感器采集的实时数据(如DHT11、DS18B20)。

5.4 编译与烧录步骤

  1. 第一步:将上述代码复制到VS Code项目主文件,关联WIZnet官方驱动库(确保所有头文件能正常引用,无报错);

  2. 第二步:修改代码中的OneNET MQTT参数、网络配置,保存文件;

  3. 第三步:编译项目,生成UF2固件文件(若编译报错,优先检查驱动库关联是否正确、头文件名称是否拼写正确);

  4. 第四步:按前文“固件烧录”步骤,将UF2固件烧录到W55RP20开发板;

  5. 第五步:打开串口调试助手,查看开发板运行日志,确认网络初始化、DNS解析、MQTT连接成功;

  6. 第六步:登录OneNET平台,进入设备详情页,查看「物模型数据」,确认温湿度数据定时上传成功。

六、运行结果与OneNET平台验证

6.1 串口输出结果

烧录完成后,开发板自动重启,打开串口调试助手,会输出以下内容,说明网络初始化、DNS解析、MQTT连接及数据上传成功:

---- 已打开串行端口 COM80 ----

=== W55RP20 OneNET MQTT Demo (Final Fixed Version) ===
[PIO SPI CLOCK SPEED : 31.25 MHz] (sys=125.00 MHz)

====================================================================================================
 W5500 network configuration : static

 MAC         : 00:08:DC:12:34:56
 IP          : 192.168.1.128
 Subnet Mask : 255.255.255.0
 Gateway     : 192.168.1.1
 DNS         : 8.8.8.8
====================================================================================================


--- DNS Resolution Phase ---
DNS: Using DNS server 8.8.8.8
DNS: Resolving domain: studio-mqtt.heclouds.com
DNS: Success! IP: 218.201.45.7
Connecting to OneNET MQTT broker at 218.201.45.7:1883...
Network connected.
MQTT Connecting to OneNET...
MQTT connected to OneNET Platform!
Subscribed to reply topic: $sys/ZGB6zBD0nS/led/thing/property/post/reply
Topic: $sys/ZGB6zBD0nS/led/thing/property/post
Payload: {"id":"11707","version":"1.0","params":{"temp":{"value":25.6},"humi":{"value":60.1}}}
Data published (QOS0)
Topic: $sys/ZGB6zBD0nS/led/thing/property/post
Payload: {"id":"21708","version":"1.0","params":{"temp":{"value":25.6},"humi":{"value":60.1}}}
Data published (QOS0)
Topic: $sys/ZGB6zBD0nS/led/thing/property/post
Payload: {"id":"31709","version":"1.0","params":{"temp":{"value":25.6},"humi":{"value":60.1}}}
Data published (QOS0)
Topic: $sys/ZGB6zBD0nS/led/thing/property/post
Payload: {"id":"41710","version":"1.0","params":{"temp":{"value":25.6},"humi":{"value":60.1}}}
Data published (QOS0)

说明:若打印“DNS retry”,属于正常现象,最多重试3次;若一直无法解析或连接失败,参考“常见问题排查”部分。

6.2 OneNET平台数据验证

登录OneNET物联网平台,进入设备详情页,查看数据上传情况,步骤如下:

  1. 进入OneNET平台「物联网核心套件」→「设备管理」,找到已注册的设备,点击设备名称进入详情页;

  2. 点击「物模型数据」→「实时数据」,可看到温湿度数据定时更新(每10秒一次),与串口打印的 payload 数据一致;

  3. 点击「消息日志」,可查看设备连接、数据上传、回复消息的详细日志,若数据上传失败,可在此处查看错误原因;

  4. (可选)点击「数据可视化」,创建仪表盘,可直观展示温湿度数据的变化趋势。

至此,W55RP20的C语言版MQTT协议与OneNET物联网平台对接实战完成!

七、常见问题一站式排查

结合OneNET对接的特殊性,以下是高频问题及排查步骤,优先排查连接参数和格式问题:

问题现象

排查步骤

1. 串口无打印或打印乱码

1. 确认串口参数配置正确(波特率115200、无校验);2. 固件为W55RP20专属C语言固件;3. 重新烧录固件,检查USB数据线是否支持数据传输。

2. DNS解析失败,提示Error

1. 检查DNS地址是否正确(推荐使用阿里云DNS:223.5.5.5);2. 确认路由器能正常联网;3. 检查OneNET MQTT服务器域名是否拼写正确;4. 重启路由器和开发板。

3. MQTT连接失败,提示retval为负数

1. 确认TCP连接成功(查看串口打印的“Network connected”提示);2. 检查MQTT版本是否为3.1.1(代码中已配置,无需修改);3. 核对产品ID、设备名称、Token是否与OneNET平台一致,无拼写错误;4. 检查Token是否过期,过期需重新生成。

4. 能连接OneNET,但无法上传数据

1. 检查上报主题格式是否正确,产品ID和设备名称是否替换;2. 确认JSON payload格式正确,无语法错误(可复制串口打印的payload到JSON校验工具验证);3. 检查OneNET物模型中属性名是否与payload中的字段名一致(temp、humi,大小写敏感);

八、W55RP20 核心优势对比

为了让你更直观地了解 W55RP20 的价值,我们对比了目前主流的三种嵌入式以太网方案:

对比维度

W55RP20 集成方案

外接 PHY 芯片 方案

外接 串口转以太网模块 方案

BOM 成本

低(单芯片)

中高(MCU + 模块 + 外围器件)

PCB 面积

小(仅需网口电路)

大(需预留芯片和布线空间)

开发难度

低(官方驱动库,一行代码联网)

中高(调试协议栈、编写驱动)

网络稳定性

极高(WIZnet 专注硬件 TCP/IP 协议栈 25 年)

不定(对于研发人员要求高,熟悉协议栈与网络开发,才能调试稳定)

不定(视研发公司能力水平)

CPU 资源占用

0%(协议栈网络处理完全由硬件完成)

50% 以上(协议栈完全运行在 MCU 上,占用相关资源)

0%

硬件 Socket 数量

8 个独立硬件 Socket

视 MCU 能力而定,理论支持多路拓展

一般为单路透传

网络吞吐量

最高 15Mbps

视 MCU 能力而定

约 3-5Mbps

接口易用性

单芯片集成

要 MCU 带有 MII/RMII 等接口

TTL 接口

部署难度

低(官方C语言驱动库成熟,应用层协议均有适配,可灵活部署)

高(应用层协议需要手动移植开源库适配)

视模块集成情况,无集成的功能需要自我封包拆包

九、典型应用场景

W55RP20 芯片集成以太网功能,结合其工业级稳定性,非常适合以下应用场景:

1.工业数据采集网关:简化现场部署,实现传感器数据的稳定上传
2.远程监控终端:用于工厂、机房、变电站等环境的设备状态远程监控
3.串口转网口设备:将传统 RS232/RS485 串口设备快速升级为以太网设备
4.智能楼宇节点:用于照明、空调、门禁等楼宇设备的网络控制
5.工业 PLC 扩展模块:为 PLC 增加以太网通信能力,实现远程编程和数据采集

十. 系列预告与资源获取

10.1系列预告

下一篇教程我们将讲解 W55RP20 c开发下的 MQTT+ThingSpeak实现上传数据,带你了解连接建立、心跳包维护、异常重连等关键机制,掌握嵌入式以太网通信的基础能力。

10.2 资源获取

本文完整代码:WIZnet 官方 Gitee 仓库
W55RP20 芯片手册:WIZnet 官方资料网址


如果本文对你有帮助,欢迎点赞、收藏、关注,你的支持是我们持续更新的动力!如有任何问题,欢迎在评论区留言,我们会第一时间回复。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐