
前言上一篇教程中我们已经完成了TCP Server 服务端通信的开发实现了面向连接、稳定可靠的 TCP 数据交互。而在局域网设备快速通信、低延迟指令下发等场景中UDP 协议凭借更轻量、更高效的特性成为嵌入式开发的重要选择。WIZnet W5500 内置硬件 TCP/IP 协议栈搭配树莓派 Pico RP2040 主控使用 C 语言 开发可实现极致低延迟、无阻塞、高可靠的 UDP 数据交互完美适配传感器上报、局域网设备发现、批量指令下发等场景。本文将基于 W55RP20-EVB-MKR 开发板使用标准 C 语言 实现UDP 客户端和UDP 服务端双模式通信学完本文你将掌握UDP 协议 C 语言 实现核心逻辑W5500 硬件协议栈 C 语言 底层初始化流程UDP 客户端定时发送数据UDP 服务端非阻塞接收 自动回环通信网络调试助手联调 C 语言 网络程序C 语言 版 UDP 通信异常一站式排查系列教程学习路径本专栏共 15 篇循序渐进覆盖 W55RP20-EVB-MKR 模块 MicroPython 开发全流程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 软件准备1.2 硬件准备2. 开发环境配置3. 硬件连接4. UDP 通信核心原理5. 核心代码解析C 语言5.1 UDP 客户端代码定时发送数据5.2 UDP 服务端代码非阻塞接收 自动回复6. 代码关键步骤说明6.1 UDP 客户端关键逻辑6.2 UDP 服务端关键逻辑7. 运行结果与测试验证7.1 UDP 客户端运行日志7.2 UDP 服务端运行日志7.3 联调方法8. 常见问题一站式排查指南8.1 编译 / 烧录问题8.2 网络不通8.3 UDP 收发失败9. W5500 硬件协议栈 C 语言 优势10. 典型应用场景11. 系列预告1. 准备工作1.1 软件准备软件名称用途Visual Studio Code MKR SDKC 语言 开发、编译、烧录环境网络调试助手UDP 数据收发测试串口调试工具查看日志、打印信息1.2 硬件准备W55RP20-EVB-MKR 开发板Micro USB 数据线支持数据传输网线路由器 / 电脑网口W55RP20-EVB-MKR模块已集成以太网相关器件无需额外焊接飞线配合 RP2040 开发板可快速搭建开发环境大幅降低接线错误和硬件故障概率。2. 开发环境配置安装 Raspberry Pi MKR SDKC 语言 编译环境集成 WIZnet 官方 W5500 驱动库配置 SPI、GPIO、串口底层驱动支持一键编译生成 UF2 固件环境配置完成后可直接编译本文提供的 C 语言 代码。3. 硬件连接USB 连接Micro USB 连接开发板与电脑用于供电、烧录、串口日志输出以太网连接网线连接开发板网口与路由器 LAN 口 / 电脑网口无需额外接线W55RP20-EVB-MKR 板载集成 W5500自动匹配 SPI 引脚4. UDP 通信核心原理UDP用户数据报协议是无连接、轻量、低延迟的传输层协议不需要三次握手建立连接不保证数据可靠性但速度极快以数据报为单位收发自带目标 IP / 端口适合传感器上报、设备发现、短指令、局域网广播C 语言 W5500 工作流程硬件初始化 → 网络配置 → 创建 UDP Socket → 数据收发 → 循环运行5. 核心代码解析C 语言本文提供两套可直接编译运行的代码UDP 客户端定时向目标设备发送数据UDP 服务端非阻塞监听端口接收后自动回复5.1 UDP 客户端代码定时发送数据功能开发板作为 UDP 客户端每隔 1 秒向电脑发送测试数据#include stdio.h #include string.h #include pico/stdlib.h #include port_common.h #include wizchip_conf.h #include wizchip_spi.h #include socket.h // 缓冲区与Socket配置 #define ETHERNET_BUF_MAX_SIZE (1024 * 2) #define SOCKET_UDP 0 #define PORT_UDP 8083 // 网络参数静态IP static wiz_NetInfo g_net_info { .mac {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, .ip {192, 168, 1, 100}, .sn {255, 255, 255, 0}, .gw {192, 168, 1, 1}, .dns {8, 8, 8, 8}, #if _WIZCHIP_ W5500 .ipmode NETINFO_STATIC_ALL #else .dhcp NETINFO_STATIC #endif }; // 发送缓冲区 static uint8_t g_buf[ETHERNET_BUF_MAX_SIZE] {0}; // 目标设备IP填写你的电脑IP static uint8_t dest_ip[4] {192, 168, 1, 139}; int main() { // 串口初始化 stdio_init_all(); sleep_ms(100); printf(\n); printf( UDP Client (C Language)\n); printf( Board IP: 192.168.1.100\n); printf( Target IP: 192.168.1.139:%d\n, PORT_UDP); printf(\n); // W5500 硬件初始化 wizchip_spi_initialize(); wizchip_cris_initialize(); wizchip_reset(); wizchip_initialize(); network_initialize(g_net_info); print_network_information(g_net_info); // 创建UDP Socket printf(UDP Socket Initializing...\n); socket(SOCKET_UDP, Sn_MR_UDP, 0, 0); printf(UDP Socket Ready!\n); // 加载发送数据 const char* send_data Hello from W5500 C Client!; strcpy((char*)g_buf, send_data); // 主循环定时发送 while (1) { sendto(SOCKET_UDP, g_buf, strlen(send_data), dest_ip, PORT_UDP); printf(UDP Sent: %s\n, send_data); sleep_ms(1000); } }5.2 UDP 服务端代码非阻塞接收 自动回复功能开发板作为 UDP 服务端监听本地端口收到数据后立即原路回复回环测试#include stdio.h #include pico/stdlib.h #include port_common.h #include wizchip_conf.h #include wizchip_spi.h #include socket.h #define ETHERNET_BUF_MAX_SIZE (1024 * 2) #define SOCKET_UDP 0 #define PORT_UDP 8083 // 网络配置 static wiz_NetInfo g_net_info { .mac {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, .ip {192, 168, 1, 100}, .sn {255, 255, 255, 0}, .gw {192, 168, 1, 1}, .dns {8, 8, 8, 8}, #if _WIZCHIP_ W5500 .ipmode NETINFO_STATIC_ALL #else .dhcp NETINFO_STATIC #endif }; static uint8_t g_ethernet_buf[ETHERNET_BUF_MAX_SIZE] {0}; int main() { stdio_init_all(); sleep_ms(100); printf(\n); printf( UDP Server (C Language)\n); printf( Board IP: 192.168.1.100\n); printf( Listen Port: %d\n, PORT_UDP); printf(\n); // W5500 底层初始化 wizchip_spi_initialize(); wizchip_cris_initialize(); wizchip_reset(); wizchip_initialize(); network_initialize(g_net_info); print_network_information(g_net_info); // 初始化UDP服务端绑定端口 printf(Opening UDP Socket...\n); if(socket(SOCKET_UDP, Sn_MR_UDP, PORT_UDP, 0) 0) { printf(Socket Init Failed!\n); while(1); } printf(UDP Server Started!\n); uint16_t rx_len; uint8_t remote_ip[4]; uint16_t remote_port; // 非阻塞主循环 while(1) { // 查询是否收到数据 if((rx_len getSn_RX_RSR(SOCKET_UDP)) 0) { // 读取数据 来源IP/端口 recvfrom(SOCKET_UDP, g_ethernet_buf, rx_len, remote_ip, remote_port); // 打印接收信息 printf(Recv %d bytes from %d.%d.%d.%d:%d\n, rx_len, remote_ip[0], remote_ip[1], remote_ip[2], remote_ip[3], remote_port); // 自动回传 sendto(SOCKET_UDP, g_ethernet_buf, rx_len, remote_ip, remote_port); printf(Data Echo Back Success!\n); } // 每秒心跳证明程序运行正常 static uint32_t heart_tick 0; if(to_ms_since_boot(get_absolute_time()) - heart_tick 1000) { printf([Heartbeat] UDP Server Running...\n); heart_tick to_ms_since_boot(get_absolute_time()); } } }6. 代码关键步骤说明6.1 UDP 客户端关键逻辑硬件初始化SPI W5500 驱动加载网络配置静态 IP 直接入网Socket 创建socket(..., Sn_MR_UDP, ...)发送数据sendto()指定目标 IP 端口定时发送1 秒间隔上报数据6.2 UDP 服务端关键逻辑绑定端口监听局域网数据非阻塞查询getSn_RX_RSR()判断是否有数据读取数据recvfrom()自动获取发送方 IP / 端口自动回环sendto()原路返回数据心跳打印实时监控程序运行状态7. 运行结果与测试验证7.1 UDP 客户端运行日志 UDP Client (C Language) Board IP: 192.168.1.100 Target IP: 192.168.1.139:8083 Network Information: IP:192.168.1.100 UDP Socket Ready! UDP Sent: Hello from W5500 C Client! UDP Sent: Hello from W5500 C Client!7.2 UDP 服务端运行日志 UDP Server (C Language) Board IP: 192.168.1.100 Listen Port: 8083 UDP Server Started! [Heartbeat] UDP Server Running... Recv 12 bytes from 192.168.1.139:8083 Data Echo Back Success!7.3 联调方法电脑打开网络调试助手选择UDP 模式填写开发板 IP192.168.1.100端口8083发送数据 → 开发板自动回复查看串口日志验证通信8. 常见问题一站式排查指南8.1 编译 / 烧录问题提示驱动缺失添加 WIZnet 官方驱动库UF2 无法烧录重新进入 BOOTSEL 模式8.2 网络不通网口灯不亮更换网线 / 网口无法 ping 通检查静态 IP 是否在同一网段电脑无法发送关闭电脑防火墙8.3 UDP 收发失败收不到数据检查端口一致、防火墙关闭发送失败确认目标 IP 正确程序卡死去掉wizchip_check()函数9. W5500 硬件协议栈 C 语言 优势对比维度W5500 硬件协议栈方案外接 PHY 芯片方案BOM 成本中MCU 网络模块无需额外器件中高MCU PHY 芯片 外围器件PCB 面积小模块集成度高仅需预留模块安装空间大需预留芯片、布线空间及外围电路开发难度低MicroPython 固件已封装底层少量代码实现 UDP 组播/广播中高需调试协议栈、编写底层驱动对研发能力要求高网络稳定性极高WIZnet 专注硬件 TCP/IP 协议栈 25 年抗干扰能力强UDP 丢包率低不定依赖研发人员对协议栈和网络开发的掌握程度UDP 易丢包CPU 资源占用0%协议栈完全由硬件处理不占用 MCU 资源不影响数据发送频率50%以上协议栈运行在 MCU 上占用大量 CPU 和内存影响 UDP 发送效率硬件 Socket 数量W5500 8个独立硬件 Socket支持多组播/广播同时进行视 MCU 能力而定理论支持多路拓展但实际受 CPU 资源限制网络吞吐量W5500 最高 15MbpsUDP 数据传输流畅无明显延迟视 MCU 能力而定普遍低于硬件协议栈方案多设备通信易卡顿接口易用性SPI 接口接线简单适配大多数 MCU支持高速通信需 MCU 带有 MII/RMII 等专用接口适配性有限部署难度低MicroPython 成熟固件应用层协议均有库文件多设备组网可快速部署高应用层协议需要手动移植开源库适配调试成本高10. 典型应用场景工业传感器局域网数据上报多设备 UDP 自动发现低延迟实时指令控制量产型物联网终端工业串口转网口网关11. 系列预告下一篇我们将讲解C 语言 实现 UDP 组播 广播通信实现局域网内一对多设备批量控制为多节点物联网项目打下基础。