单芯片解决方案,开启全新体验——W55MH32 高性能以太网单片机
W55MH32是WIZnet重磅推出的高性能以太网单片机,它为用户带来前所未有的集成化体验。这颗芯片将强大的组件集于一身,具体来说,一颗W55MH32内置高性能Arm® Cortex-M3核心,其主频最高可达216MHz;配备1024KB FLASH与96KB SRAM,满足存储与数据处理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP协议栈、内置MAC以及PHY,拥有独立的32KB以太网收发缓存,可供8个独立硬件socket使用。如此配置,真正实现了All-in-One解决方案,为开发者提供极大便利。
在封装规格上,W55MH32提供了两种选择:QFN100和QFN68。
W55MH32L采用QFN100封装版本,尺寸为12x12mm,其资源丰富,专为各种复杂工控场景设计。它拥有66个GPIO、3个ADC、12通道DMA、17个定时器、2个I2C、5个串口、2个SPI接口(其中1个带I2S接口复用)、1个CAN、1个USB2.0以及1个SDIO接口。如此丰富的外设资源,能够轻松应对工业控制中多样化的连接需求,无论是与各类传感器、执行器的通信,还是对复杂工业协议的支持,都能游刃有余,成为复杂工控领域的理想选择。同系列还有QFN68封装的W55MH32Q版本,该版本体积更小,仅为8x8mm,成本低,适合集成度高的网关模组等场景,软件使用方法一致。更多信息和资料请进入http://www.w5500.com/网站或者私信获取。
此外,本W55MH32支持硬件加密算法单元,WIZnet还推出TOE+SSL应用,涵盖TCP SSL、HTTP SSL以及 MQTT SSL等,为网络通信安全再添保障。
为助力开发者快速上手与深入开发,基于W55MH32L这颗芯片,WIZnet精心打造了配套开发板。开发板集成WIZ-Link芯片,借助一根USB C口数据线,就能轻松实现调试、下载以及串口打印日志等功能。开发板将所有外设全部引出,拓展功能也大幅提升,便于开发者全面评估芯片性能。
若您想获取芯片和开发板的更多详细信息,包括产品特性、技术参数以及价格等,欢迎访问官方网页:http://www.w5500.com/,我们期待与您共同探索W55MH32的无限可能。

第七章 W55MH32 DNS解析域名示例
本篇文章,我们将详细介绍如何在W55MH32芯片上面实现DNS域名解析功能。并通过实战例程,为大家讲解如何将wiznet.io的域名解析为实际IP地址,供大家参考。
该例程用到的其他网络协议,例如DHCP,请参考相关章节。有关W55MH32的初始化过程,也请参考相关章节,这里将不再赘述。
1 DNS协议简介
在学习DNS协议之前,我们先区分一下IP地址和域名这两个概念:
IP地址:一长串能够唯一地标记网络上地计算机的数字。
域名:又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识,例如:wiznet.io。
如何理解域名和网址的概念,可以这么理解,网址里面包含域名。举个例子:https://wiznet.io/Products就是一个网址,而wiznet.io就是域名。
因为 IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,所以设计出了域名,并通过域名解析协议(DNS,Domain Name System)来将域名和 IP地址相互映射,使人能够更方便地访问互联网,而不用去记住能够被机器直接读取的 IP地址数串。将域名映射成 IP地址称为DNS正向解析,将 IP地址映射成域名称为DNS反向解析。
DNS协议可以使用UDP或者TCP进行传输,使用的端口号都为53,但大多数情况下DNS都是用UDP进行传输。
以上是DNS协议的简介,如想深入了解该协议,请参考mozilla网站上的介绍:DNS - MDN Web文档术语表:Web相关术语的定义 | MDN
2 DNS域名介绍
DNS域名通常分为以下几类:
根域名服务器:根域名服务器是DNS系统的顶层,负责管理整个DNS命名空间的根区(Root Zone)。它主要用于引导查询,指向顶级域(TLD)的权威服务器。
顶级域名服务器:负责特定顶级域(如.com、.org、.net)或国家/地区代码顶级域(ccTLD,如.cn、.uk)的解析。
权威DNS服务器:负责存储并提供特定域名的DNS记录信息
本地DNS服务器:本地域名服务器是电脑解析时的默认域名服务器,即电脑中设置的首选 DNS 服务器和备选 DNS 服务器。常见的有电信、联通、谷歌、阿里等的本地 DNS服务。
3 DNS查询方式
DNS查询方式分为以下两种:
递归查询:指由DNS客户端(如用户设备或本地域名服务器)向DNS服务器发起的查询请求,DNS服务器负责全程完成查询过程,并将最终的解析结果返回给客户端。
迭代查询:指DNS服务器返回给客户端或请求者的下一步建议,而不是直接返回最终结果,由客户端自行完成多次查询,逐步获取解析结果。
下面两张图则是递归查询和迭代查询的工作流程图。


4 DNS协议的基本工作流程
接下来,我们以PC端正向解析www.baidu.com为例,了解下DNS解析的工作流程。
1)首先搜索「浏览器的 DNS缓存」,缓存中维护一张域名与 IP地址的对应表;
2)若没有命中,则继续搜索「操作系统的 DNS缓存」;
3)若仍然没有命中,则操作系统将域名发送至「本地域名服务器」,本地域名服务器查询自己的 DNS缓存,查找成功则返回结果(注意:主机和本地域名服务器之间的查询方式是「递归查询」);
4)若本地域名服务器的 DNS 缓存没有命中,则本地域名服务器向上级域名服务器进行查询,通过以下方式进行「迭代查询」(注意:本地域名服务器和其他域名服务器之间的查询方式是迭代查询,防止根域名服务器压力过大):
首先本地域名服务器向「根域名服务器」发起请求,根域名服务器是最高层次的,它并不会直接指明这个域名对应的 IP地址,而是返回顶级域名服务器的地址,也就是说给本地域名服务器指明一条道路,让他去这里寻找答案。
本地域名服务器拿到这个「顶级域名服务器」的地址后,就向其发起请求,获取「权限域名服务器」的地址
本地域名服务器根据权限域名服务器的地址向其发起请求,最终得到该域名对应的 IP地址
5)本地域名服务器将得到的 IP地址返回给操作系统,同时自己将 IP地址缓存起来
6)操作系统将 IP地址返回给浏览器,同时自己也将 IP地址缓存起来
7)至此,浏览器就得到了域名对应的 IP地址,并将 IP地址缓存起来
配合下图直观理解:

在W55MH32上使用DNS正向解析wiznet.io域名时,我们只需要向本地域名服务器发送DNS请求报文,然后解析DNS响应报文即可。
5 DNS报文
DNS报文分为以下五个部分:
报文头部:定义了请求或响应的元信息(如标志、条目数等)。
问题区域:描述了查询的域名和查询类型。
回答区域:包含查询的最终结果(如域名对应的IP地址)。
权威区域:提供权威DNS服务器的信息。
附加区域:包含附加的相关信息(如域名的A记录)。
DNS请求报文主要由报文头部和问题区域组成,回答区域、权威区域和附加区域为空。
报文头部
Transaction ID:固定长度为16bit,唯一标识符,用于匹配请求和响应。
Flags:固定长度为16bit,标志位(例如查询类型、递归期望等)。
Questions:固定长度为16bit,问题区域的条目数,通常为1。
Answer RRs:固定长度为16bit,回答区域的条目数,查询报文中为0。
Authority RRs:固定长度为16bit,权威区域的条目数,查询报文中为0。
Additional RRs:固定长度为16bit,附加区域的条目数,查询报文中为0。
问题区域
QName:查询的域名(以点分形式存储)。
QType:查询的记录类型(如A记录、AAAA记录、MX记录等)。
QClass:查询的记录类别,通常为IN(互联网)。
DNS响应报文包含与请求报文类似的头部和问题区域,并附加回答、权威和附加区域信息。
报文头部:同请求报文,但Flags内容有所变化:
QR:1表示响应(查询报文中为0)
RCODE:返回码,表示响应状态(如0表示无错误,3表示域名不存在)。
AA:权威回答标志(1表示这是权威服务器返回的响应)。
问题区域:与请求报文一致,用于描述客户端的查询。
回答区域:包含查询结果,如域名对应的IP地址。每条回答包含以下字段:
Name:对应的域名
Type:记录类型(如A、AAAA、CNAME等)。
Class:记录类别(通常为IN)。
TTL:记录的生存时间(秒)。
Rdata:记录的具体值(如IP地址)。
权威区域:提供权威服务器的信息,通常包含NS记录。
附加区域:包含额外的解析信息,如权威服务器的A记录和AAAA记录。
请求报文实例:请求解析域名wiznet.io的A记录
|报文头部 | Transaction ID: 0x8D12 Flags: 0x0100 (标准查询、期望递归) Questions: 1 Answer RRs: 0 Authority RRs: 0 Additional RRs: 0 |问题区域 | QName:wiznet.io QType: A QClass: IN |报文原文 | 8D 12 01 00 00 01 00 00 00 00 00 00 06 77 69 7A 6E 65 74 02 69 64 00 00 01 00 01
响应报文实例:DNS服务器返回wiznet.io的A记录解析结果(IP为183.111.138.249)
|报文头部 | Transaction ID: 0x8D12 Flags: 0x8180 (响应、无错误) Questions: 1 Answer RRs: 1 Authority RRs: 0 Additional RRs: 0 |问题区域 | QName:wiznet.io QType: A QClass: IN |回答区域 | Name:wiznet.io Type: A Class: IN TTL: 156 RData: 183.111.138.249 |报文原文 | 8D 12 81 80 00 01 00 01 00 00 00 00 06 77 69 7A 6E 65 74 02 69 6F 00 00 01 00 01 C0 0C 00 01 00 01 00 00 00 9C 00 04 B7 6F 8A F9
6实现过程
接下来,我们看看如何在W55MH32上实现DNS正向解析。
注意:因为本示例需要访问互联网,请确保W55MH32的配置能够访问互联网。
步骤一:注册DNS定时器中断到1s定时器中
/**
* @brief 1ms timer IRQ Handler
* @param none
* @return none
*/
void TIM3_IRQHandler(void)
{
static uint32_t tim3_1ms_count = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
tim3_1ms_count++;
if (tim3_1ms_count >= 1000)
{
DHCP_time_handler();
DNS_time_handler();
tim3_1ms_count = 0;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
注册DNS定时器中断主要为了DNS超时处理。
在dns.h文件中,定义了DNS超时时间、重试次数、端口号和消息ID等内容:
#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ /* * @brief Maxium length of your queried Domain name * @todo SHOULD BE defined it equal as or greater than your Domain name lenght + null character(1) * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. */ #define MAX_DOMAIN_NAME 128 // for example "www.google.com" #define MAX_DNS_RETRY 2 ///< Requery Count #define DNS_WAIT_TIME 3 ///< Wait response time. unit 1s. #define IPPORT_DOMAIN 53 ///< DNS server port number #define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modifyed it any number
步骤二:进行DNS正向解析处理
在do_dns()函数中,我们实现了dns正向解析的过程。
do_dns(ethernet_buf, dns_name, ip_fromdns);
这个函数的三个传参分别为DNS解析所需缓存,带解析域名,解析后的IP地址。
do_dns()函数的内容如下:
/** * @brief DNS domain name resolution * @param ethernet_buff: ethernet buffer * @param domain_name:Domain name to be resolved * @param domain_ip:Resolved Internet Protocol Address * @return 0:success;-1:failed */ int do_dns(uint8_t *buf, uint8_t *domain_name, uint8_t *domain_ip) { int dns_ok_flag = 0; int dns_run_flag = 1; wiz_NetInfo net_info; uint8_t dns_retry_cnt = 0; DNS_init(0, buf); // DNS client init wizchip_getnetinfo(&net_info); while (1) { switch (DNS_run(net_info.dns, domain_name, domain_ip)) // Read the DNS_run return value { case DNS_RET_FAIL: // The DNS domain name is successfully resolved { if (dns_retry_cnt < DNS_RETRY) // Determine whether the parsing is successful or whether the parsing exceeds the number of times { dns_retry_cnt++; } else { printf(" > DNS Failedrn"); dns_ok_flag = -1; dns_run_flag = 0; } break; } case DNS_RET_SUCCESS: { printf("> Translated %s to %d.%d.%d.%drn", domain_name, domain_ip[0], domain_ip[1], domain_ip[2], domain_ip[3]); dns_ok_flag = 0; dns_run_flag = 0; break; } } if (dns_run_flag != 1) { return dns_ok_flag; } } }
然后是在DNS主循环中运行DNS执行函数DNS_run,它的主要作用是进行DNS组包,发送请求,响应内容解析以及超时处理,这里只需要根据DNS_run()函数的返回值进行相应处理即可。
DNS_run()函数内容如下:
/* DNS CLIENT RUN */
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
{
int8_t ret;
struct dhdr dhp;
uint8_t ip[4];
uint16_t len, port;
int8_t ret_check_timeout;
retry_count = 0;
dns_1s_tick = 0;
// Socket open
socket(DNS_SOCKET, Sn_MR_UDP, 0, 0);
#ifdef _DNS_DEBUG_
printf("> DNS Query to DNS Server : %d.%d.%d.%drn", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
while (1)
{
if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
{
if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
len = recvfrom(DNS_SOCKET, pDNSMSG, len, ip, &port);
#ifdef _DNS_DEBUG_
printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %drn", ip[0], ip[1], ip[2],
ip[3],port,len);
#endif
ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
break;
}
// Check Timeout
ret_check_timeout = check_DNS_timeout();
if (ret_check_timeout < 0) {
#ifdef _DNS_DEBUG_
printf(" > DNS Server is not responding : %d.%d.%d.%drn", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
close(DNS_SOCKET);
return 0; // timeout occurred
}
else if (ret_check_timeout == 0) {
#ifdef _DNS_DEBUG_
printf("> DNS Timeoutrn");
#endif
sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
}
}
close(DNS_SOCKET);
// Return value
// 0 > : failed / 1 - success
return ret;
}
7运行结果
烧录例程运行后,首先进行了PHY链路检测,然后是DHCP获取网络地址结果,最后是DNS成功解析出wiznet.io的IP地址为183.111.138.249,如下图所示:
8总结
本文介绍在 W55MH32芯片上实现 DNS域名解析功能的方法,讲解如何将 wiznet.io域名解析为实际 IP地址。阐述了 DNS协议发热概念、域名分类、查询方式和工作流程,介绍了 DNS报文结构及请求、响应报文实例等。展示在W55MH32上的实现过程。
下一篇将讲解在该芯片上实现 HTTP Client功能,介绍向指定网站提交数据的原理和实现步骤。敬请期待!
WIZnet是一家无晶圆厂半导体公司,成立于 1998年。产品包括互联网处理器 iMCU™,它采用 TOE(TCP/IP卸载引擎)技术,基于独特的专利全硬连线 TCP/IP。iMCU™面向各种应用中的嵌入式互联网设备。
WIZnet在全球拥有 70多家分销商,在香港、韩国、美国设有办事处,提供技术支持和产品营销。
香港办事处管理的区域包括:澳大利亚、印度、土耳其、亚洲(韩国和日本除外)。
审核编辑 黄宇
-
以太网
+关注
关注
41文章
5934浏览量
179695 -
DNS
+关注
关注
0文章
228浏览量
21030
发布评论请先 登录
第二章 W55MH32 DHCP示例
第五章 W55MH32 UDP示例
第六章 W55MH32 UDP Multicast示例
第九章 W55MH32 HTTP Server示例
第十章 W55MH32 SNTP示例
第十一章 W55MH32 SMTP示例
第十二章 W55MH32 NetBIOS示例
第十四章 W55MH32 TFTP示例
第十五章 W55MH32 SNMP示例
第十六章 W55MH32 PING示例

第七章 W55MH32 DNS解析域名示例
评论