news 2026/6/23 12:49:15

STM32F103ZET6 + W5500编程遇到的问题与解决过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103ZET6 + W5500编程遇到的问题与解决过程

W5500是韩国公司WIZNET出品的爆款网络芯片,它集成了TCP/IP协议栈和以太网PHY接口,能让不具备网络功能的单片机通过 SPI 接口便捷地实现上网功能,目前国内兼容的芯片有沁恒公司的CH394。我最近开发的一款数据采集卡产品就是使用STM32F103ZET6+W5500实现了网络功能,网络部分代码由野火开发板配套提供,而野火的代码也是在官方代码基础上修改而来。使用配套代码很容易就实现了我的应用,但是在稳定性测试中也发现了一些问题,下面就是遇到的问题以及解决办法。

1. 拔插网线后无法再次连接

建立连接成功后,将网线拔插,模拟网络故障,结果在网线插上后可以PING通,但是连接一直超时,通过单片机的调试串口输出可以看出W5500的状态一直处于SOCK_ESTABLISHED,说明它没有收到网络断开的通知。网上搜索解决方法,需要启动Keep-Alive功能,因此在网络初始化代码中添加相应代码启动Keep-Alive功能:

启动Keep-Alive功能函数声明如下:

//s参数表示对应的socket号,times参数表示超时次数

void setSn_KPALVTR(SOCKET s, uint8 times);

函数定义如下:

void setSn_KPALVTR(SOCKET s, uint8 times)

{

//IINCHIP_WRITE是官方提供的寄存器操作函数

//官方手册中每个时间单位是5S,times=1表示检验周期是5S

IINCHIP_WRITE(Sn_KPALVTR(s),times);

}

官方手册描述如下:

Sn_KPALVTR 配置了 SOCKET n 的‘KEEP ALIVE(KA)’在线验证心跳包传输时

间。他只在TCP模式下生效,在其他模式下将会被忽略。单位时间为5秒。

KA 包会在Sn_SR变为SOCK_ESTABLISHED 且与对方至少进行过一次收或发的通

讯后进行传输。如果‘Sn_KPALVTR > 0’,W5500 在一定时间周期会自动传输 KA

包以检查 TCP 的连接状态(自动在线验证)。如果‘Sn_KPALVTR = 0’,将不会

启动自动在线验证,主机可以通过 SEND_KEEP 配置命令发送 KA 包(手动在线验

证)。在‘Sn_KPALVTR > 0’时,将会无视手动在线验证。

如果对方不能在超时计数期内反馈在线心跳包,这个连接将会被关闭并

触发超时中断。

从官方手册来看,下面的代码应该是最长5S+超时计数秒数后就关闭连接,程序超时计数描述设置的是32秒,拔掉网线后测试了几次,基本都是36、37秒W5500的socket变成关闭连接状态,符合预期。

//0是SOCKET,也就是W5500的通道0

setSn_KPALVTR(0, 1);

也可以手动发送心跳包,函数如下(我的代码中没有手动发送,主要是没想好发送的时机,所以还是设置自动发送更简单):

//发送心跳包函数声明

void sendKA(SOCKET s);

//发送心跳包函数定义

void sendKA(SOCKET s)

{

IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND_KEEP);

}

拔掉网线后需要等待半分钟多才能再次连接上,这个时间还是有些长,如果能检测到网线断开后马上就关闭连接,这样就可以在插上网线后快速的进行连接,从而提升用户体验。 检测网络断开的代码如下,为了节约系统开销,这里使用了宏定义:

#define NET_DISCONNECT ((IINCHIP_READ(PHYCFGR) & 0x01) == 0)

NET_DISCONNECT可以直接当作布尔变量使用,断开为真,连接为假。

在检测到网络断开后,直接使用close函数关闭对应socket就可以让单片机马上处于等待连接的状态。

2. 卡在SOCK_SYNRECV很长时间

上位机windows操作系统,使用VS2022的C++编程,设置断线重连,有的时候能马上连接,有的时候要等半分钟才能连接成功,查看单片机的调试串口输出,可以看到W5500的网络状态卡在了SOCK_SYNRECV处很长时间,直到超时关闭连接后,上位机才能再次连接成功。将上位机连接超时从1秒改成5秒后,连接延迟的现象有所改善,但是仍然会出现,估计是在单片机等待连接再次建立的时候,刚好出现在超时临界点,导致接收不到SOCK_SYNRECV的应答信号,就一直卡在那里了,决定使用下面的思路解决。

添加SOCK_SYNRECV超时判断,W5500进入SOCK_LISTEN状态后,复位超时;进入SOCK_SYNRECV状态后,开始计时,如果计时时间到,仍然处在SOCK_SYNRECV状态中,则关闭socket。相关函数与代码如下:

//函数声明

uint8 SYNRECVTimeOut(uint8 resetTime,uint16 timeOutMS);

//resetTime=0表示不复位超时定时器

//resetTime=1表示复位超时定时器

//timeOutS是超时秒数

//函数定义

uint8 SYNRECVTimeOut(uint8 resetTime,uint16 timeOutMS)

{

static uint64_t lastMS = 0;

if (resetTime) {

lastMS = get_ms();

}

else {

if (get_ms() - lastMS > timeOutMS)

return 1;

}

return 0;

}

//网络处理代码片段

……

case SOCK_LISTEN:

//复位超时定时器

SYNRECVTimeOut(1, 0);

break;

case SOCK_SYNRECV:

//此状态超过1S则关闭端口

if (SYNRECVTimeOut(0, 1000))

close(SOCK_TCPS);

break;

……

经过上面两个处理,拔插数据采集卡的网线,上位机重连基本都可以在1秒内完成。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 5:55:55

【2025年AI 编程时代的热点】

AI 编程与团队组织变革 AI 编程的成熟将显著改变团队结构和人才需求。传统开发团队中编码占比高的角色可能缩减,而具备AI工具链整合能力、业务理解深度和跨领域协作能力的人才需求上升。团队结构趋向扁平化,产品经理、工程师与AI工具的协作更紧密&#…

作者头像 李华
网站建设 2026/6/23 15:51:02

【C++ 笔记】从 C 到 C++:核心过渡 (中)

前言: 前文中,我们系统学习了 namespace 机制(有效地解决了命名冲突问题,包含指定访问、部分展开和全部展开三种使用方式),同时了解了 cin/cout 输入输出流(具备自动类型识别和支持自定义类…

作者头像 李华
网站建设 2026/6/23 15:54:53

SQL约束解析

约束分类:NOT NULL 非空约束:字段必须有值UNIQUE 唯一约束:值不能重复,但允许多个 NULLPRINARY KEY 主键约束:既是 NOT NULL 又是 UNIQUEDEFAULT 默认约束: 保存数据时.如果未指定该字段的值,则采用默认值CHECK 检查约束:保证字段满足某一个值FOREIGN KEY 外键约束…

作者头像 李华
网站建设 2026/6/23 15:51:48

地铁调研12-17

今天地铁调研主要内容包括:1.跟随工人使用道尺进行巡检。主要测量内容:轨道内距,轨道水平情况。记录:/-x,毫米。2.涂油板(道岔变轨部分)的油是否还有。3.扣配件的螺栓是否松动扣配件的情况&…

作者头像 李华
网站建设 2026/6/22 19:04:16

现代软件测试工具全景对比与选型指南

随着敏捷开发与DevOps实践的普及,软件测试工具生态呈现百花齐放态势。截至2025年末,测试工具已从简单的BUG记录工具发展为覆盖自动化测试、性能监控、安全检测的完整解决方案。本文将通过功能性对比、适用场景分析及成本效益评估三个维度,为测…

作者头像 李华
网站建设 2026/6/23 15:47:06

基于 Apache POI 的体检报告 Word 生成实战文档

基于 Apache POI 的体检报告 Word 生成实战文档一 项目目标与总体设计 目标:基于模板快速生成排版规范的体检报告,支持文本替换、动态表格、图片插入,并可一键导出 PDF 用于归档与打印。技术选型: Apache POI XWPF:操作…

作者头像 李华