W55RP20-EVB-Pico 模块 C语言实战 (DNS示例):快速实现域名解析
本文为 W55RP20-EVB-Pico 模块 MicroPython 教程专项篇,基于官方最新固件编写,代码均经过实际验证,可直接烧录运行。 版权声明:本文为 WIZnet 官方原创技术文章,转载请注明出处。
前言
上一篇教程中,我们已经完成了 UDP 组播 / 广播 开发,实现了局域网多设备批量通信。而在实际物联网项目中,设备除了需要局域网通信,还必须具备访问公网服务器的能力,这就离不开 DNS 域名解析 功能。
当我们结合 WIZnet W5500 硬件 TCP/IP 协议栈,使用 C 语言 开发时,设备的稳定性、实时性和资源利用率达到最优。W5500 芯片内置硬件协议栈,完全独立处理 DNS、DHCP、TCP、UDP 等网络功能,不占用 RP2040 任何 CPU 资源,让嵌入式设备轻松实现域名解析、远程连接、云平台接入。
本文将带你使用 C 语言 快速实现 W55RP20-EVB-Pico 模块的 DNS 域名解析,学完本文,你将掌握:
- DNS 协议核心原理与工业级工作流程
- W55RP20 C 语言开发环境与硬件初始化
- DHCP + DNS 联动实现全自动域名解析
- 多域名解析、超时重试、异常处理
- DNS 解析测试与故障排查
- WIZnet 硬件协议栈在 DNS 处理中的优势
系列教程学习路径
本专栏共 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 仓库。
目录
2. 烧录 W55RP20-EVB-Pico 模块 C 语言固件
1. 准备工作
1.1 软件准备
所需软件均为免费版本,按要求下载安装即可,无需额外付费。
| 软件名称 | 版本要求 | 说明 |
|---|---|---|
| Raspberry Pi Pico SDK | 1.5.0 及以上 | W55RP20 C 语言官方开发环境 |
| VS Code | 最新版 | C 语言代码编辑、编译、调试 |
| 串口调试工具 | 通用版 | 查看日志、DNS 解析结果打印 |
| 网络调试助手 | 最新版 | 辅助网络连通性测试 |
1.2 硬件准备

- W55RP20-EVB-Pico × 1
- Micro USB 数据线(支持数据传输)× 1
- 标准网线 × 1
- 开启 DHCP 功能的路由器 / 交换机 × 1
W55RP20-EVB-Pico 模块已集成以太网相关器件,无需额外焊接飞线,配合 RP2040 开发板可快速搭建开发环境,大幅降低接线错误和硬件故障概率。
2. 烧录 W55RP20-EVB-Pico 模块 C 语言固件
W55RP20-EVB-Pico 完全兼容树莓派 Pico UF2 烧录方式:
- 按住开发板上 BOOTSEL 按键不放;
- 使用 Micro USB 数据线连接开发板与电脑;
- 电脑识别出 RPI-RP2 盘符后松开按键;
- 将编译好的 UF2 固件 拖拽到 U 盘中;
- 开发板自动重启,烧录完成。
注意:如果电脑没有识别出 RPI-RP2 U 盘,请尝试更换 USB 数据线、重新插拔开发板,或更换电脑 USB 接口(优先使用 USB 2.0 接口)。
3. 硬件连接与开发环境配置
3.1 硬件连接
3.1.1 基础连接(供电 + 调试)
使用 Micro USB 数据线连接开发板与电脑,用于供电、代码烧录、串口打印。
3.1.2 以太网连接
使用网线连接 W55RP20-EVB-Pico 网口与路由器 LAN 口,确保设备能访问外网。
3.1.3 硬件默认接线
模块集成 SPI 硬件驱动,无需手动接线,即插即用。
3.2 C 语言开发环境配置
- 安装 Raspberry Pi Pico SDK
- 集成 WIZnet 官方驱动库
- 配置串口打印、SPI 通信、定时器
- 编译工程生成 UF2 固件
- 烧录并打开串口查看日志
4. DNS 域名解析原理
4.1 DNS 协议简介
DNS(Domain Name System)域名系统,是互联网核心服务之一。作用:将人类易记的域名(如 www.baidu.com)转换为机器识别的 IP 地址。
相当于互联网的 “电话簿”。
4.2 DNS 工作流程(C 语言硬件版)
- 开发板上电 → W5500 硬件初始化
- 启动 DHCP → 自动获取 IP、网关、DNS 服务器
- 向 DNS 服务器发送解析请求
- W5500 硬件独立处理请求,不占用 MCU
- 接收 DNS 服务器返回的 IP 地址
- 解析成功 → 输出 IP → 可用于 TCP/HTTP/MQTT 连接
4.3 DNS 核心优势
- 无需记忆复杂 IP 地址
- 服务器 IP 变更不影响设备使用
- 支持负载均衡、容灾切换
- 物联网设备上云必备基础功能
4.4 典型应用场景
- 物联网设备接入云平台
- HTTP/HTTPS 访问服务器 API
- MQTT 远程通信
- 远程控制、固件升级
- 工业网关数据上传
5. 核心代码解析(C 语言)
5.1 完整可运行代码
/**
Copyright (c) 2021 WIZnet Co.,Ltd
SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "port_common.h"
#include "wizchip_conf.h"
#include "wizchip_spi.h"
#include "dhcp.h"
#include "dns.h"
#include "timer.h"
/* Buffer */
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
/* Socket */
#define SOCKET_DHCP 0
#define SOCKET_DNS 1
/* Retry count */
#define DHCP_RETRY_COUNT 5
#define DNS_RETRY_COUNT 5
/* Network */
static wiz_NetInfo g_net_info = {
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56},
.ip = {192, 168, 11, 2},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 11, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP
};
static uint8_t g_ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t g_dhcp_get_ip_flag = 0;
static uint8_t g_dns_target_domain[] = "www.wiznet.io";
static uint8_t g_dns_target_ip[4] = {0};
static uint8_t g_dns_get_ip_flag = 0;
static volatile uint16_t g_msec_cnt = 0;
/* DHCP */
static void wizchip_dhcp_init(void);
static void wizchip_dhcp_assign(void);
static void wizchip_dhcp_conflict(void);
/* Timer */
static void repeating_timer_callback(void);
int main() {
uint8_t retval = 0;
uint8_t dhcp_retry = 0;
uint8_t dns_retry = 0;
stdio_init_all();
sleep_ms(3000);
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize();
wizchip_check();
wizchip_delay_ms(2000);
wizchip_1ms_timer_initialize(repeating_timer_callback);
if (g_net_info.dhcp == NETINFO_DHCP) {
wizchip_dhcp_init();
} else {
network_initialize(g_net_info);
print_network_information(g_net_info);
}
DNS_init(SOCKET_DNS, g_ethernet_buf);
while (1) {
/* DHCP 运行 */
if (g_net_info.dhcp == NETINFO_DHCP) {
retval = DHCP_run();
if (retval == DHCP_IP_LEASED) {
if (g_dhcp_get_ip_flag == 0) {
printf("DHCP 配置成功\n");
g_dhcp_get_ip_flag = 1;
}
} else if (retval == DHCP_FAILED) {
g_dhcp_get_ip_flag = 0;
dhcp_retry++;
if (dhcp_retry <= DHCP_RETRY_COUNT) {
printf("DHCP 超时,重试:%d\n", dhcp_retry);
}
}
if (dhcp_retry > DHCP_RETRY_COUNT) {
printf("DHCP 失败\n");
DHCP_stop();
while (1);
}
wizchip_delay_ms(1000);
}
/* DNS 解析 */
if ((g_dns_get_ip_flag == 0) && (retval == DHCP_IP_LEASED)) {
while (1) {
if (DNS_run(g_net_info.dns, g_dns_target_domain, g_dns_target_ip) > 0) {
printf("\nDNS 解析成功!\n");
printf("目标域名: %s\n", g_dns_target_domain);
printf("解析IP: %d.%d.%d.%d\n",
g_dns_target_ip[0], g_dns_target_ip[1],
g_dns_target_ip[2], g_dns_target_ip[3]);
g_dns_get_ip_flag = 1;
break;
} else {
dns_retry++;
if (dns_retry <= DNS_RETRY_COUNT) {
printf("DNS 超时,重试: %d\n", dns_retry);
}
}
if (dns_retry > DNS_RETRY_COUNT) {
printf("DNS 解析失败\n");
while (1);
}
wizchip_delay_ms(1000);
}
}
}
}
/* DHCP 初始化 */
static void wizchip_dhcp_init(void) {
printf("DHCP 客户端运行中...\n");
DHCP_init(SOCKET_DHCP, g_ethernet_buf);
reg_dhcp_cbfunc(wizchip_dhcp_assign, wizchip_dhcp_assign, wizchip_dhcp_conflict);
}
static void wizchip_dhcp_assign(void) {
getIPfromDHCP(g_net_info.ip);
getGWfromDHCP(g_net_info.gw);
getSNfromDHCP(g_net_info.sn);
getDNSfromDHCP(g_net_info.dns);
g_net_info.dhcp = NETINFO_DHCP;
network_initialize(g_net_info);
print_network_information(g_net_info);
printf("DHCP 租期: %ld 秒\n", getDHCPLeasetime());
}
static void wizchip_dhcp_conflict(void) {
printf("DHCP IP 冲突\n");
while (1);
}
/* 定时器回调 */
static void repeating_timer_callback(void) {
g_msec_cnt++;
if (g_msec_cnt >= 1000 - 1) {
g_msec_cnt = 0;
DHCP_time_handler();
DNS_time_handler();
}
}
5.2 代码功能说明
- 硬件初始化:SPI、W5500、定时器、串口全硬件启动
- DHCP 自动获取:无需配置静态 IP,即插即用
- DNS 解析:调用官方 DNS 库,硬件处理,稳定高效
- 超时重试机制:DHCP 5 次重试,DNS 5 次重试
- 异常处理:IP 冲突、解析失败自动停机保护
- 串口打印:实时输出 IP、域名、解析结果
- 工业级鲁棒性:适合长期稳定运行
6. 运行结果与测试验证
6.1 串口输出结果
DHCP 客户端运行中...
MAC: 00:08:DC:12:34:56
IP: 192.168.1.100
SN: 255.255.255.0
GW: 192.168.1.1
DNS: 8.8.8.8
DHCP 租期: 86400 秒
DHCP 配置成功
DNS 解析成功!
目标域名: www.wiznet.io
解析IP: 203.253.128.164
6.2 验证方法
- 电脑 ping 解析出的 IP
ping 203.253.128.164 - 更换域名测试修改代码中的:
static uint8_t g_dns_target_domain[] = "www.baidu.com"; - 重新编译烧录,查看是否解析成功
7. 常见问题一站式排查指南
7.1 DHCP 无法获取 IP
- 网线未插好 / 路由器未开 DHCP
- 网口接在 WAN 口,应接 LAN 口
- 更换网线 / 网口
- 重启开发板与路由器
7.2 DNS 解析失败
- 设备无法访问外网
- DNS 配置错误(改为 8.8.8.8 或 114.114.114.114)
- 域名拼写错误
- 防火墙屏蔽 UDP 53 端口
- 更换手机热点测试
7.3 串口无输出
- 数据线不支持数据传输
- 串口波特率错误
- 固件烧录失败
7.4 IP 冲突
- 局域网内有重复 IP
- DHCP 分配异常,重启路由器解决
8. WIZnet 硬件协议栈核心优势对比
|
对比维度 |
W5500 硬件协议栈方案 |
外接 PHY 芯片方案 |
外接串口转以太网模块方案 |
|---|---|---|---|
|
BOM 成本 |
中(MCU + 网络模块,无需额外器件) |
中高(MCU + PHY 芯片 + 外围器件) |
高(MCU + 串口转网口模块) |
|
PCB 面积 |
小(模块集成度高,仅需预留模块安装空间) |
大(需预留芯片、布线空间及外围电路) |
中(需预留模块安装空间) |
|
开发难度 |
低(MicroPython 固件已封装底层,一行代码实现联网) |
中高(需调试协议栈、编写底层驱动,对研发能力要求高) |
低(模块已集成驱动,仅需串口通信) |
|
网络稳定性 |
极高(WIZnet 专注硬件 TCP/IP 协议栈 25 年,抗干扰能力强) |
不定(依赖研发人员对协议栈和网络开发的掌握程度) |
不定(视模块厂商研发能力和产品质量) |
|
CPU 资源占用 |
0%(协议栈完全由硬件处理,不占用 MCU 资源) |
50%以上(协议栈运行在 MCU 上,占用大量 CPU 和内存) |
0%(模块独立处理网络逻辑) |
|
硬件 Socket 数量 |
W5500 8个独立硬件 Socket |
视 MCU 能力而定,理论支持多路拓展 |
一般为单路透传,多连接需额外配置 |
|
网络吞吐量 |
W5500 最高 15Mbps |
视 MCU 能力而定,普遍低于硬件协议栈方案 |
约 3-5Mbps,速率较低 |
|
接口易用性 |
SPI 接口,接线简单,适配大多数 MCU |
需 MCU 带有 MII/RMII 等专用接口,适配性有限 |
TTL 串口接口,适配性强,但速率受限 |
|
部署难度 |
低(MicroPython 成熟固件,应用层协议均有库文件,可灵活部署) |
高(应用层协议需要手动移植开源库适配,调试成本高) |
中(无集成功能需自行封包拆包,灵活性不足) |
9. 典型应用场景
- 物联网设备远程上云
- 工业数据采集与上传
- 智能硬件远程控制
- 环境监测传感器网络
- 嵌入式网关、DTU
- 教育实验平台
10. 系列预告与资源获取
10.1 系列预告
下一篇教程我们将讲解 NTP 网络时间同步(C 语言),实现嵌入式设备精准计时、时间戳、定时任务、防时钟漂移等工业级功能,为日志记录、数据上报、时序控制打下基础。
10.2 资源获取
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)