RP2350-POE-ETH 使用教程

产品特性

  • 采用了 Raspberry Pi 研发的 RP2350A 微控制器芯片
  • 独特的双核、双架构,搭载了双核 ARM Cortex-M33 处理器和双核 Hazard3 RISC-V 处理器,时钟运行频率高达 150MHz,支持用户在两种架构间灵活切换
  • 内置 520KB 的 SRAM 和 16MB 的片上 Flash
  • 采用 Type-C 接口,紧跟时代潮流,无需纠结正反插
  • 板载 W6300,集成 TCP/IP 协议栈
  • 支持 USB1.1 主机和设备
  • 邮票孔设计,可直接焊接集成到用户自主设计的底板上
  • 可通过 USB 识别为大容量存储器进行拖放式下载
  • 引出 20 个 GPIO,兼容部分 Pico 扩展板
  • 精确的片上时钟和定时器
  • 内置温度传感器,可实时监测芯片温度
  • 12 个可编程 I/O (PIO) 状态机,用于自定义外设支持

板载资源


  1. USB Type-C 接口 可以用于下载程序,并且支持 USB1.1 主机和从设备
  2. WS2812 酷炫 RGB LED
  3. BOOT 按键 复位时按下,进入下载模式
  4. RESET 按键 复位按键
  5. RP2350A 双核、双架构处理器,高达 150MHz 运行频率
  6. PoE 模块接口及供电口 支持外接 PoE 供电模块,可通过网线为整板供电。
  7. 百兆 RJ45 网口 以太网接口
  8. Debug 接口 支持在线仿真、Debug
  9. 低压降线性稳压器 Vout=3.3V,最大电流800mA
  10. 16MB NOR-Flash 用于程序与数据存储
  11. W6300 以太网驱动芯片

接口介绍



产品尺寸



MicroPython 开发

本章节包含以下部分,请按需阅读:

MicroPython 入门教程

初次接触 Pico MicroPython 开发,想要快速上手?我们为您准备了一套通用的入门教程。此教程旨在帮助开发者快速熟悉 Thonny IDE 并上手开发。教程内容涵盖环境搭建、项目创建、组件使用及外设编程等,帮助您迈出 MicroPython 编程的第一步。

配置开发环境

请参考 安装和配置 Thonny IDE 教程 下载安装 Thonny IDE。

示例程序

MicroPython 示例程序位于 示例程序包 的 examples\MicroPython 目录中。

示例程序基础例程说明依赖库
01_MQTTMQTT 示例程序-

01_MQTT

【程序说明】

  • 该示例演示 RP2350-POE-ETH 在 MicroPython 下,通过 W6300 以太网连接公网 MQTT Broker(默认 broker.emqx.io:1883),并实现:
    • 订阅主题:Sub/ed229f15
    • 发布主题:Pub/ed229f15
    • 上电后发布一次设备状态 JSON,随后 每 10 秒发布一次(包含 CPU 主频、温度、VSYS 电压、USB/POE 插入状态、运行时间等)
  • 开源使用注意(强烈建议首次使用就修改,避免多人/多设备冲突)
    • MQTT Broker 通常要求 Client ID 在同一时刻全局唯一:两台设备使用相同 MQTT_CLIENT_ID 登录时,后连入的会把先连入的挤掉,表现为设备频繁掉线。
    • Topic 如果使用固定值,多台设备的数据会混在一起,且容易被其它人误订阅/误控制。
    • 建议至少修改:MQTT_CLIENT_IDMQTT_SUB_TOPICMQTT_PUB_TOPIC;如你自建 Broker 或启用了鉴权,也要修改 MQTT_USERNAMEMQTT_PASSWORD

对应到本示例的源代码,相关配置在以下位置:

  • main.py:Topic 定义 + 从 config.py 读取 MQTT 参数
# Constants for MQTT Topics
MQTT_SUB_TOPIC = 'Sub/ed229f15'
MQTT_PUB_TOPIC = 'Pub/ed229f15'

# MQTT Parameters
MQTT_SERVER = config.mqtt_server
MQTT_PORT = config.mqtt_port
MQTT_USERNAME = config.mqtt_username
MQTT_PASSWORD = config.mqtt_password
MQTT_CLIENT_ID = config.mqtt_client_id
MQTT_KEEPALIVE = config.mqtt_keepalive
  • config.py:MQTT Broker 与账号信息
mqtt_server = b'broker.emqx.io'
mqtt_port = 1883
mqtt_client_id = b'ed229f15'
mqtt_keepalive = 60
mqtt_username = b'w6300_test'
mqtt_password = b'0123456789'

【硬件连接】

  • 使用 USB 线将开发板连接电脑(用于供电、烧录与串口日志查看)
  • 插入网线到 RJ45 口,并确保网络可访问公网(能访问 broker.emqx.io:1883
  • 可选:插入 POE 网线为板子供电(程序上报 JSON 中体现 poe_inserted 状态)

【代码分析】

  • 入口文件 main.py
    • 以太网初始化 ethernet_init()
      • network.WIZNET6K() 初始化以太网接口
      • nic.ifconfig('dhcp') 开启 DHCP 获取 IP,并等待 nic.isconnected()
    • MQTT 连接 mqtt_connect()
      • 使用 from umqtt.simple import MQTTClient
      • 连接成功后设置回调 client.set_callback(mqtt_recv_callback) 并订阅 MQTT_SUB_TOPIC
    • 发布主题与订阅主题(默认写在 main.py 顶部常量区):
MQTT_SUB_TOPIC = 'Sub/ed229f15'
MQTT_PUB_TOPIC = 'Pub/ed229f15'
  • 上报(启动一次 + 每 10 秒一次)
    • PUBLISH_INTERVAL = 10
    • 发布的 JSON 由 device/system/message 三部分组成(当前代码中 get_network_info() 已实现但未加入 payload,你可以按需扩展):
{
"device": { "chip": "RP2350A", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"message": "Hello, waveshare!"
}
  • 订阅消息回调 mqtt_recv_callback(topic, message)
    • 订阅主题收到消息后,会尝试将 payload 解析为 JSON,并按字段执行指令(支持一个 payload 同时带多个字段):
      • {"adc": 1}:读取 VSYS 电压(GPIO29 ADC),并向 Pub/... 回包
      • {"led": 2}:设置 WS2812 颜色(GPIO25,取值 0-8
      • {"io_dect": 1}:读取 USB/POE 插入状态(GPIO24/23),并向 Pub/... 回包
    • 回包示例:
{"vsys_voltage":5.021,"vsys_adc_raw":2048}
{"led_color":2,"led_name":"RED"}
{"usb_inserted":true,"poe_inserted":false}
  • MQTT 库 lib/umqtt/
    • simple.py:基础 MQTT 协议实现(connect/publish/subscribe/wait_msg/check_msg)
    • robust.py:在 simple.py 上封装自动重连逻辑(本示例当前使用 umqtt.simple,如需更强韧性可自行切换)

【运行效果】

运行前请先完成 【硬件连接】,并按以下步骤完成烧录与部署:

  1. 烧录 MicroPython 固件(UF2)
    • 进入 BOOT 模式后,将firmware\MicroPython目录下的 RP2350-POE-ETH.uf2 拖拽/复制到开发板的 U 盘盘符中完成烧录。
  2. 上传示例代码到开发板文件系统,并在 Thonny 执行运行mian.py
    • examples\MicroPython\01_MQTT目录下文件:
      • main.py(MicroPython 上电自启动入口)
      • config.py
      • lib/umqtt/simple.py
      • lib/umqtt/robust.py
    • 说明:lib/ 目录需要保持目录结构,最终在板子上应类似:
/
main.py
config.py
lib/
umqtt/
simple.py
robust.py
  1. 烧录并上传文件后复位开发板,串口会打印类似日志(不同网络环境会略有差异):
Initialize Ethernet (W6300)
Waiting for Ethernet connection...
Ethernet connection successful!
IP address: 192.168.1.100
Subscribe to topic: Sub/ed229f15
Published: {...} -> Pub/ed229f15
...
  1. 使用任意 MQTT 客户端验证(推荐 MQTTX)

    • MQTTX 客户端设置:


    • RP2350-POE-ETH连接参数:
      • Host:broker.emqx.io
      • Port:1883
      • Username:w6300_test
      • Password:0123456789
      • Client ID:ed229f15
    • 订阅主题:Pub/ed229f15,可收到开发板每 10 秒上报的 JSON
    • 向主题 Sub/ed229f15 发布控制指令(payload 为 JSON 字符串),例如:
{"led":2}
{"adc":1,"io_dect":1}



C/C++ 开发

本章节包含以下部分,请按需阅读:

配置开发环境

请参考 安装和配置 Pico C/C++ 开发环境教程 下载安装 Pico VS Code。

示例程序

C/C++ 示例程序位于 示例程序包 的 examples\C 目录中。

示例程序基础例程说明依赖库
01_MQTTMQTT 示例程序-

01_MQTT

【程序说明】

  • 该示例演示 RP2350-POE-ETH 使用 Pico SDK(C 工程)通过以太网连接公网 MQTT Broker(默认 broker.emqx.io:1883),并实现:
    • 订阅主题:Sub/ed229f15
    • 发布主题:Pub/ed229f15
    • 每 10 秒发布一次设备状态 JSON(包含 MAC、Client ID、温度、VSYS 电压、USB/POE 插入状态、运行时间、网络参数等)
  • 程序使用 DHCP 自动获取 IP,并通过 DNS 解析域名 broker.emqx.io 得到 Broker IP 后连接;也支持切换为静态 IPv4 与静态 Broker IP。
  • 串口日志通过 USB CDC 输出(工程配置为 pico_enable_stdio_usb(main 1)),用于调试与查看 MQTT 交互过程。
  • 开源使用注意(强烈建议首次使用就修改,避免多人/多设备冲突)
    • MQTT Broker 通常要求 Client ID 在同一时刻全局唯一:两台设备使用相同 MQTT_CLIENT_ID 登录时,后连入的会把先连入的挤掉,表现为设备频繁掉线。
    • Topic 如果使用固定值,多台设备的数据会混在一起,且容易被其它人误订阅/误控制。
    • 建议至少修改:MQTT_CLIENT_IDMQTT_PUBLISH_TOPICMQTT_SUBSCRIBE_TOPIC;如你自建 Broker 或启用了鉴权,也要修改 MQTT_USERNAMEMQTT_PASSWORD

示例默认配置位于 mqtt_app/mqtt_app.c(宏定义区):

#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#define MQTT_PASSWORD "0123456789"

#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"

【硬件连接】

  • 使用 USB 线将开发板连接电脑(用于供电、烧录与 USB CDC 串口日志查看)
  • 插入网线到 RJ45 口,并确保网络可访问公网(能访问 broker.emqx.io:1883
  • 可选:插入 POE 网线为板子供电(程序会在上报 JSON 中体现 poe_inserted 状态)

【代码分析】

  • 入口文件 main.c

    • 本工程使用 main() 作为入口;完成板级/外设/网络初始化后进入 mqtt_service_run() 的无限循环(内部 while(1)),负责 MQTT 保活、收包处理与定时发布。
    • main() 核心流程(文字说明)
      • 系统初始化:DEV_Module_Init()(时钟/stdio 等)+ WS2812_init()(状态指示灯)
      • 电源/温度相关初始化:bsp_adc_voltage_detection_init(...)(VSYS 采样配置)+ adc_set_temp_sensor_enabled(true)(温度通道)
      • IO 初始化:usb_detect_io_init() / poe_detect_io_init()
      • 业务启动:mqtt_app_init()(以太网 + DHCP/DNS + MQTT)→ mqtt_service_run()(MQTT 主循环:保活/收包/定时发布)
      • 异常处理:任一步骤返回非 0 时进入 while(1) 并点亮错误指示(LED_INDICATOR_ERROR()
  • MQTT 逻辑文件 mqtt_app/mqtt_app.c

    • 关键配置(宏定义区)
      • Broker
        • g_dns_target_domain = "broker.emqx.io":Broker 域名(默认走 DNS 解析)
        • PORT_MQTT (1883):MQTT TCP 端口
        • 如网络禁用 DNS 或想固定 Broker IP:把 mqtt_connect() 中的 #if 0 改为 #if 1,使用 MQTT_BROKER_IP_0~3
      • MQTT_CLIENT_ID / MQTT_USERNAME / MQTT_PASSWORD:连接 Broker 的账号信息(示例默认写死固定值;也支持基于 Unique ID 自动生成)
      • MQTT_PUBLISH_TOPIC / MQTT_SUBSCRIBE_TOPIC:发布/订阅主题
      • MQTT_PUBLISH_PERIOD (10s):定时发布周期
    • 静态/动态切换(建议只改这一处源码就能切换)
      • 网络地址:静态 IP ↔ DHCP(动态)
        • 默认(DHCP)
static eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP,
.ipmode = NETINFO_DHCP_V4
};
  • 说明:DHCP 模式下,以上 .ip/.sn/.gw/.dns 是占位值,会在 ethchip_dhcp_run() 成功后被路由器下发的参数覆盖;网关与 DNS 也由路由器下发
  • DHCP 入口(成功获取到租约后,会在 DHCP 回调里触发重连)
int mqtt_app_init(void)
{
if (g_net_info.dhcp == NETINFO_DHCP) {
ethchip_dhcp_init(ethchip_dhcp_assign, ethchip_dhcp_assign, ethchip_dhcp_conflict);
return ethchip_dhcp_run();
}
return mqtt_connect();
}
  • Broker 地址:静态 IP ↔ DNS(动态解析域名)
    • 默认(DNS 解析域名)
static uint8_t g_dns_target_domain[] = "broker.emqx.io";
#if 0
g_mqtt_broker_ip[0] = MQTT_BROKER_IP_0;
g_mqtt_broker_ip[1] = MQTT_BROKER_IP_1;
g_mqtt_broker_ip[2] = MQTT_BROKER_IP_2;
g_mqtt_broker_ip[3] = MQTT_BROKER_IP_3;
#else
ethchip_dns_init();
ethchip_dns_get_domain_ip(g_net_info.dns, g_dns_target_domain, g_mqtt_broker_ip);
#endif
  • 切换为静态 Broker IP:把上面代码里的 #if 0 改成 #if 1,就会改用 MQTT_BROKER_IP_0~3
  • MQTT 身份:静态 client_id/username ↔ 动态生成(基于 Unique ID)
    • 默认(静态 client_id / username)
#if 1
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s", MQTT_CLIENT_ID);
#else
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s%02X%02X%02X%02X",
MQTT_CLIENT_ID_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif

#if 1
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s", MQTT_USERNAME);
#else
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s%02X%02X%02X%02X",
MQTT_USERNAME_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
  • 切换为动态生成:把上面两段 #if 1 改成 #if 0,就会按前缀 + Unique ID 拼出每台设备独立的身份

  • 注意:当前发布/订阅主题是固定值(多设备会混在一起)

  • message_arrived(MessageData *msg_data)

    • printf("%.*s\n", ...):打印订阅到的消息内容
    • mqtt_parse_and_execute_commands(...):把订阅消息交给命令解析模块(位于 mqtt_execute_commands.c),按 JSON 字段执行指令并回包
static const mqtt_cmd_map_t g_cmd_map[] = {
{"adc", adc_op_handle},
{"led", led_op_handle},
{"io_dect", io_dect_op_handle},
};
  • 支持的控制指令(payload 为 JSON,字段存在且值>=0 才会执行)
    • {"adc":1}:读取 VSYS 电压与 ADC 原始值,并发布一条 JSON 到 MQTT_PUBLISH_TOPIC
{"vsys_voltage":5.021,"vsys_adc_raw":2048}
  • {"led":N}:设置板载 WS2812 颜色(N 范围 0-8),并发布执行结果到 MQTT_PUBLISH_TOPIC
    • 成功示例:
{"led_color":2,"led_name":"RED"}
  • 失败示例(超出范围):
{"error":"invalid_led_color","value":99,"valid_range":"0-8"}
  • {"io_dect":1}:读取 USB/POE 插入检测 IO,并发布状态到 MQTT_PUBLISH_TOPIC
{"usb_inserted":true,"poe_inserted":false}
  • build_mqtt_payload(...)
    • 读取温度、Flash 容量、系统运行时间、VSYS 电压、USB/POE 插入状态、网络参数等,拼成 JSON 字符串作为发布 payload
    • 关键异常处理:电压读取失败会回退为 0,避免上报异常值

【运行效果】

  • 使用 VS Code 导入并编译 01_MQTT 工程,编译完成后,烧录 build 目录下 uf2 尾缀文件,或直接烧录 firmware\C 目录下 01_MQTT.uf2 文件进行快速验证。

  • 烧录示例后,打开 USB 串口(常用串口工具默认 115200),可看到类似日志:

DEV_Module_Init OK

========== Device Identity ==========
MAC: 02:08:DC:xx:xx:xx
ClientID: ed229f15
UserName: w6300_test
======================================

DHCP initialization succeed
DHCP success
DHCP assign succeed
mqtt disconnect
mqtt connect
DNS initialized successfully
DNS success
Target domain : broker.emqx.io
IP of target domain : 34.243.217.54
MQTT connected
Published
Subscribed
Published
Published
...
  • 使用任意 MQTT 客户端验证(推荐 MQTTX)

    • MQTTX 客户端设置:


    • RP2350-POE-ETH连接参数(与宏配置一致):
      • Host:broker.emqx.io
      • Port:1883
      • Username:w6300_test
      • Password:0123456789
      • Client ID:ed229f15
    • 订阅主题:Pub/ed229f15,可以收到开发板每 10 秒上报的 JSON,例如:
{
"device": { "chip": "RP2350A", "mac": "02:08:DC:xx:xx:xx", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"flash_mb": 16,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"network": { "mode": "DHCP", "ip": "192.168.1.100", "subnet": "255.255.255.0", "gateway": "192.168.1.1", "dns": "8.8.8.8" },
"message": "Hello, waveshare!"
}
  • 向主题 Sub/ed229f15 发布任意字符串或 JSON:
    • 发布任意字符串:开发板会原样打印到串口(见前文 message_arrived(...) 代码片段)。

    • 发布 JSON 指令(例如 {"led":2}):会执行对应动作,并把执行结果再次发布到 Pub/ed229f15(建议订阅 Pub/ed229f15 查看执行回包)。

       



Arduino 开发

本章节包含以下部分,请按需阅读:

配置开发环境

请参考 安装和配置 Arduino IDE 教程 下载安装 Arduino IDE。

示例程序

Arduino 示例程序位于 示例程序包 的 examples\Arduino 目录中。

示例程序基础例程说明依赖库
01_MQTTMQTT 示例程序Adafruit_NeoPixel


01_MQTT

【程序说明】

  • 该示例 ws2812 LED 依赖库 Adafruit_NeoPixel ,需要提前安装。
  • 该示例演示 RP2350-POE-ETH 通过以太网连接公网 MQTT Broker(默认 broker.emqx.io:1883),并实现:
    • 订阅主题:Sub/ed229f15
    • 发布主题:Pub/ed229f15
    • 每 10 秒发布一次设备状态 JSON(包含 MAC、IP、温度、VSYS 电压、USB/POE 插入状态、运行时间等)
  • 程序使用 DHCP 自动获取 IP,并通过 DNS 解析域名 broker.emqx.io 得到 Broker IP 后连接。
  • 开源使用注意(强烈建议首次使用就修改,避免多人/多设备冲突)
    • MQTT Broker 通常要求 Client ID 在同一时刻全局唯一:两台设备使用相同 MQTT_CLIENT_ID 登录时,后连入的会把先连入的挤掉,表现为设备频繁掉线。
    • Topic 如果使用固定值,多台设备的数据会混在一起,且容易被其它人误订阅/误控制。
    • 建议至少修改:MQTT_CLIENT_IDMQTT_PUBLISH_TOPICMQTT_SUBSCRIBE_TOPIC;如你自建 Broker 或启用了鉴权,也要修改 MQTT_USERNAMEMQTT_PASSWORD
#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#define MQTT_PASSWORD "0123456789"

#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"

【硬件连接】

  • 使用 USB 线将开发板连接电脑(用于供电、烧录与串口日志查看)
  • 插入网线到 RJ45 口,并确保网络可访问公网(能访问 broker.emqx.io:1883
  • 可选:插入 POE 网线为板子供电(程序会在上报 JSON 中体现 poe_inserted 状态)

【代码分析】

  • 入口文件 01-MQTT.ino

    • extern "C" int _write(...):把 printf() 的输出重定向到 Serial,这样 C 文件里用 printf 打印也能在串口监视器看到。
    • setup()
      • Serial.begin(115200):初始化串口,波特率 115200。
      • DEV_Module_Init():初始化板级硬件(GPIO/SPI/以太网芯片等,具体在工程 BSP 内部实现)。
      • bsp_adc_voltage_detection_init(...):初始化 VSYS 电压检测(后续上报 vsys_voltage_v 与 vsys_adc_raw)。
      • usb_detect_io_init() / poe_detect_io_init():初始化 USB/POE 插入检测 IO(后续上报 usb_inserted/poe_inserted)。
      • mqtt_app_init():初始化以太网 + DHCP/DNS + MQTT 连接。
    • loop()
      • mqtt_service_run():MQTT 主循环(内部是 while(1)),负责保持连接、处理订阅消息、定时发布。
  • MQTT 逻辑文件 mqtt_app.c

    • 关键配置(宏定义区)
      • Broker
        • g_dns_target_domain = "broker.emqx.io":Broker 域名(默认走 DNS 解析)
        • PORT_MQTT (1883):MQTT TCP 端口
        • 如网络禁用 DNS 或想固定 Broker IP:把 mqtt_connect() 中的 #if 0 改为 #if 1,使用 MQTT_BROKER_IP_0~3
      • PORT_MQTT (1883):MQTT TCP 端口。
      • MQTT_CLIENT_ID / MQTT_USERNAME / MQTT_PASSWORD:连接 Broker 的账号信息(示例中写死为固定值)。
      • MQTT_PUBLISH_TOPIC / MQTT_SUBSCRIBE_TOPIC:发布/订阅主题。
      • MQTT_PUBLISH_PERIOD (10s):定时发布周期。
      • g_dns_target_domain = "broker.emqx.io":默认 Broker 域名。
    • 静态/动态切换(建议只改这一处源码就能切换)
      • 网络地址:静态 IP ↔ DHCP(动态)
        • 默认(DHCP)
static eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP,
.ipmode = NETINFO_DHCP_V4
};
  • 说明:DHCP 模式下,以上 .ip/.sn/.gw/.dns 只是占位值,会在 ethchip_dhcp_run() 成功后被路由器分配的参数覆盖;网关(gw)与 DNS 也由路由器下发,无需手动改成“自家路由”
int mqtt_app_init(void)
{
if (g_net_info.dhcp == NETINFO_DHCP) {
ethchip_dhcp_init(ethchip_dhcp_assign, ethchip_dhcp_assign, ethchip_dhcp_conflict);
return ethchip_dhcp_run();
}
return mqtt_connect();
}
  • 切换为静态 IPv4(把 DHCP 关掉,并填写固定 IP 参数)
static eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_STATIC,
.ipmode = NETINFO_STATIC_V4
};
  • 静态 IP 参数怎么填(填错会导致“网络不通 / MQTT 连接失败”)

    • .ip:开发板自己的固定 IP,必须和路由器在同一网段,且不要与局域网内其它设备冲突
      • 例:你的路由器是 192.168.1.1,子网掩码 255.255.255.0,则可选 192.168.1.123
    • .sn(Subnet Mask):子网掩码,必须与路由器的网段配置一致
      • 家用路由器最常见为 255.255.255.0
    • .gw(Gateway):默认网关,一般就是路由器的 LAN IP
      • 例:192.168.1.1
    • .dns:DNS 服务器 IP
      • 可填路由器 IP(如 192.168.1.1),或公共 DNS(如 8.8.8.8114.114.114.114
    • 避坑建议:如果路由器开着 DHCP,尽量把静态 IP 设在 DHCP 地址池之外,或在路由器里做 “IP/MAC 绑定(地址保留)” 避免冲突
  • Broker 地址:静态 IP ↔ DNS(动态解析域名)

    • 默认(DNS 解析域名)
static uint8_t g_dns_target_domain[] = "broker.emqx.io";
#if 0
g_mqtt_broker_ip[0] = MQTT_BROKER_IP_0;
g_mqtt_broker_ip[1] = MQTT_BROKER_IP_1;
g_mqtt_broker_ip[2] = MQTT_BROKER_IP_2;
g_mqtt_broker_ip[3] = MQTT_BROKER_IP_3;
#else
ethchip_dns_init();
ethchip_dns_get_domain_ip(g_net_info.dns, g_dns_target_domain, g_mqtt_broker_ip);
#endif
  • 切换为静态 Broker IP:把上面代码里的 #if 0 改成 #if 1,就会改用 MQTT_BROKER_IP_0~3(当前固定为 34.243.217.54
  • MQTT 身份:静态 client_id/username ↔ 动态生成(基于 Unique ID)
    • 默认(静态 client_id / username)
#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#if 1
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s", MQTT_CLIENT_ID);
#else
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s%02X%02X%02X%02X",
MQTT_CLIENT_ID_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif

#if 1
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s", MQTT_USERNAME);
#else
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s%02X%02X%02X%02X",
MQTT_USERNAME_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
  • 切换为动态生成:把上面两段 #if 1 改成 #if 0,就会按 MQTT_CLIENT_ID_PREFIX / MQTT_USERNAME_PREFIX + Unique ID 拼出每台设备独立的身份
  • 注意:当前发布/订阅主题是固定值(多设备会混在一起)
#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"
  • generate_device_identity()
    • 读取 RP2350 的 Unique ID(pico_get_unique_board_id),生成 MAC 地址(前 3 字节固定 OUI:02:08:DC,后 3 字节取自芯片 Unique ID)。
    • 生成/设置 MQTT client_id 与 username(示例当前走静态宏;也支持根据 Unique ID 自动生成)。
  • mqtt_app_init()
    • 初始化以太网芯片驱动(SPI、复位、检查、1ms 定时器等)。
    • 若 g_net_info.dhcp == NETINFO_DHCP
      • ethchip_dhcp_init(...) + ethchip_dhcp_run():启动 DHCP 获取 IP(成功后会进入 DHCP 回调并自动触发 MQTT 连接)。
    • 若使用静态 IP:直接调用 mqtt_connect() 建立 MQTT。
  • mqtt_connect()
    • network_initialize(g_net_info):把当前网络参数写入以太网芯片(IP/网关/DNS 等)。
    • DNS 路径(默认启用)
      • ethchip_dns_get_domain_ip(...):解析 broker.emqx.io 得到 g_mqtt_broker_ip
      • 也可以切换到静态 IP(把 #if 0 改为 #if 1,使用 MQTT_BROKER_IP_0~3)。
    • ConnectNetwork(...):建立到 Broker 的 TCP 连接。
    • MQTTClientInit(...) + MQTTConnect(...):初始化 MQTT 客户端并完成 CONNECT。
    • MQTTSubscribe(..., message_arrived):订阅 MQTT_SUBSCRIBE_TOPIC,收到消息会进入 message_arrived()
  • message_arrived(MessageData *msg_data)
    • printf("%.*s\n", ...):打印订阅到的消息内容。
    • mqtt_parse_and_execute_commands(...):把订阅消息交给命令解析模块。当前订阅主题为 Sub/ed229f15,收到消息后的行为如下:
        1. 原样打印 payload 到串口
        1. 尝试按“JSON 字段”执行指令(支持一个 payload 同时带多个字段,例如同时控制 LED + 读取电压)
        1. 执行成功/失败的结果会再次发布到 Pub/ed229f15(建议订阅 Pub/ed229f15 查看执行回包)
// 支持的控制指令(payload 为 JSON,字段存在且值>=0 才会执行)
// {"adc":1} 读取 VSYS 电压并上报
// {"led":2} 设置 WS2812 颜色(0-8)
// {"io_dect":1} 读取 USB/POE 插入状态并上报
static const mqtt_cmd_map_t g_cmd_map[] = {
{"adc", adc_op_handle},
{"led", led_op_handle},
{"io_dect", io_dect_op_handle},
};
  • {"adc":1}:读取 VSYS 电压与 ADC 原始值,并发布一条 JSON 到 Pub/ed229f15
{"vsys_voltage":5.021,"vsys_adc_raw":2048}
  • {"led":N}:设置板载 WS2812 颜色(N 范围 0-8,分别为 OFF/WHITE/RED/ORANGE/YELLOW/GREEN/CYAN/BLUE/PURPLE),并发布执行结果到 Pub/ed229f15
    • 成功示例:
{"led_color":2,"led_name":"RED"}
  • 失败示例(超出范围):
{"error":"invalid_led_color","value":99,"valid_range":"0-8"}
  • {"io_dect":1}:读取 USB/POE 插入检测 IO,并发布状态到 Pub/ed229f15
{"usb_inserted":true,"poe_inserted":false}
  • build_mqtt_payload(...)
    • 读取温度(read_chip_temp())、flash 大小、系统运行时间、VSYS 电压、USB/POE 插入状态、网络参数等,拼成 JSON 字符串。
    • 该 JSON 作为发布 payload(g_mqtt_message.payload)。
  • mqtt_service_run()
    • MQTTYield(...):让 MQTT 客户端处理收包/保活/回调等。
    • 每到 MQTT_PUBLISH_PERIOD:调用 MQTTPublish(...) 向 MQTT_PUBLISH_TOPIC 发布一次设备状态。
    • DHCP 模式下会按 DHCP_PERIOD 定期 ethchip_dhcp_run() 维护租约;当 DHCP 重新分配地址时,会在 ethchip_dhcp_assign() 中断开并重连 MQTT。

【运行效果】

  • 烧录示例后,打开串口监视器(115200),可看到类似日志:
=== System Start ===
DHCP initialization succeed
...(获取到 IP 后)...
MQTT connected
Published
Subscribed
Published
Published
...
  • 使用任意 MQTT 客户端验证(推荐 MQTTX)

    • MQTTX 客户端设置:


    • RP2350-POE-ETH连接参数:
      • Host:broker.emqx.io
      • Port:1883
      • Username:w6300_test
      • Password:0123456789
      • Client ID:ed229f15
    • 订阅主题:Pub/ed229f15,可以收到开发板每 10 秒上报的 JSON,例如:
{
"device": { "chip": "RP2350A", "mac": "02:08:DC:xx:xx:xx", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"flash_mb": 16,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"network": { "mode": "DHCP", "ip": "192.168.1.100", "subnet": "255.255.255.0", "gateway": "192.168.1.1", "dns": "8.8.8.8" },
"message": "Hello, waveshare!"
}
  • 向主题 Sub/ed229f15 发布任意字符串,开发板串口会打印收到的消息内容(并进入命令解析函数,方便你二次开发控制逻辑)。

     



相关资料

1. 硬件资料

开发板设计文件

2. 技术手册

数据手册

3. 官方资料

4. 开发软件

5. 示例程序