CH394Q TCP 热拔插

测试硬件:CH32v307 + CH394Q开发板,直连电脑

网络调试工具:TCPIPDebug

1.如何判断网线何时断开?

因为CH394和CH395/CH392不同,他没有中断来指示PHY是否断开,所以只有通过两种途径来查询PHY的连接状态:

①查询硬件LINK脚(25脚)的电平状态,一般这个脚都是接到网口灯,低电平表示PHY已协商,高电平表示未连接

②查询芯片的PHY配置寄存器(0x002E)

该寄存器的bit[0]可以指示物理层是否建立链接

 2.如何操作实现功能

(1)写disconnect命令断开,拔掉网线再插上后,芯片发出FIN包,调试工具返回RST释放连接,芯片收到RST后进入断开中断。断开中断中重新开启socket和开启监听,客户端重新发起连接即可。

抓包如下:

代码:(可开启定时器,定时查询,延时可去掉)

 1         if((CH394Q_GetPHYStatus() & 0x01) == 0)
 2         {
 3             printf("DOWN\r\n");
 4             if(down_flag == 0)
 5             {
 6                 printf("DOWN11\r\n");
 7                 CH394Q_SetSn_CTRL(0, Sn_CTRL_DISCONNECT);
 8                 while (CH394Q_GetSn_CTRL(0) != 0x00);
 9                 down_flag = 1;
10             }
11             Delay_Ms(500);
12         }
13         else {
14             printf("up\r\n");
15             down_flag = 0;
16             Delay_Ms(500);
17         }

 (2)写close命令断开,芯片不会发任何包,直接关掉socket。所以不会进断开中断,需要代码做处理。拔掉网线再插上后,可直接建立连接

代码:

 1         if((CH394Q_GetPHYStatus() & 0x01) == 0)
 2         {
 3             printf("DOWN\r\n");
 4             if(down_flag == 0)
 5             {
 6                 printf("DOWN11\r\n");
 7                 CH394Q_SetSn_CTRL(0, Sn_CTRL_CLOSE);
 8                 while (CH394Q_GetSn_CTRL(0) != 0x00);
 9                 down_flag = 1;
10                 link_flag = 1;
11             }
12             Delay_Ms(500);
13         }
14         else {
15             printf("up\r\n");
16             if(link_flag == 1)
17             {
18                 printf("up11\r\n");
19                 CH394Q_ReopenSocket(0);
20                 link_flag = 0;
21                 down_flag = 0;
22             }
23             Delay_Ms(500);
24         }

(3)依据KeepAlive机制+超时实现断开

①利用协议栈自动发送keepAlive包

 功能介绍:

代码:

当芯片发出的keepAlive包对端没有回复且重传结束,则会触发超时中断,在超时中断里有重新打开socket和发起连接的动作,直到和服务器连上为止。(重传时间和次数可以依实际情况改变,注意394在tcp连接建立后,需要传输一包数据后keepAlive功能才会起效)

1     CH394Q_SetSn_KEEPALIVE(0,1);////首先使能socket_0的keepAlive功能,这里的0代表socket0,1代表芯片每隔5秒发送一次keepAlive包
2     CH394Q_SetRTIME(2000);//设置重传时间,200ms
3     CH394Q_SetRCNT(2);//设置重试次数,2次
 1   //超时中断里调用ReopneSocket重新打开socket
 2     if (Sn_INT_state & Sn_INT_TIMEOUT)
 3     {
 4         printf(" TIMEOUT\r\n");
 5         CH394Q_SetSn_INT(sockindex, Sn_INT_TIMEOUT);
 6         if (socketmode[sockindex] != UDP)
 7         {
 8             while (CH394Q_GetSn_STA(sockindex) != 0x00);
 9             CH394Q_ReopenSocket(sockindex);
10         }
11     }

②手动发送keeplive

 

CH394还支持手动发送keepAlive包,即芯片主动向对端发送一次心跳包,如果超时未获得应答,则触发超时中断(这种方式一样,也要传输一包后再去调用下面代码才会发出keepAlive包)

 代码:

1                 CH394Q_SetSn_CTRL(0, Sn_CTRL_SEND_KEEP);
2                 while (CH394Q_GetSn_CTRL(0));

 

posted on 2025-06-03 17:26  Lqqq123  阅读(201)  评论(0)    收藏  举报

导航