国产100M以太网PHY:沁恒CH182H2性能测试应用看这篇就够了

博主:旭日财富者旭日财富者 2026-02-15 3094

一、前言

二、开发板CH32V307V-EVT-R3介绍

三、CH182H2介绍

四、性能测试

五、总结建议

六、基于MounRiver_Studio开发(保姆级操作)

一、前言

本文分享一款100M以太网PHY芯片,CH182H2。并分享基于官方的开发板CH32V307V-EVT-R3来评估下这款芯片的应用,以及性能测试。具体的性能,参数,特点等可以参考数据手册,这里主要描述一些个人觉得比较有意思的点。

本文会着重描述该芯片的基本应用,包括原理图分析,官方开发板Demo测试,RAW发送,TCP收发性能测试等,如果是初次使用该芯片的朋友,可以参考本文。

二、开发板CH32V307V-EVT-R3介绍

官方的CH32V307V-EVT-R3开发板,可以用于评估CH182H2芯片。

wKgZPGmNsTGARcLsAAHAGiEvzYQ340.png

资料下载地址:

https://www.wch.cn/downloads/CH32V307EVT_ZIP.html

开发板的主要接口资源如下:

1.100M网口

2.MCU引出I/O

3.SWDIO调试口

4.CH32V307VCT6

5.USB全速接口

6.USB高速接口(内置PHY)

7.电源开关

8.复位按钮

9.下载按钮

个人觉得比较好的地方是P6把RMII接口引出来了,方便逻辑分析仪直接测量RMII接口,用于测试分析,甚至用于学习RMII接口都是不错的。

三、CH182H2介绍

开发板是用于评估的载体,本文的重点是CH182H2这颗PHY芯片,所以开发板大致了解,熟悉下原理图,知道有哪些接口,如何使用即可。重点来看CH182H2这颗芯片。该芯片IO口支持3.3/2.5/1.8V,适配多种电压的主控,还兼容RTL8102F。看手册描述,有一款CH182D内置唯一MAC地址,体积小巧,QFN封装才3*3mm。

可以从以下地址下载该芯片规格书

https://www.wch.cn/downloads/CH182DS1_PDF.html

这里顺带提一下,WCH的以太网产品还是挺全的。看他们官网介绍,除了以太网PHY,还提供控制器芯片CH390、协议栈芯片CH394/CH395和转接芯片CH9121等。CH390D尺寸3*3mm,算是目前市面上体积最小的百兆以太网MAC PHY芯片了,内置PHY,支持IPv4 TCP/UDP和IPv6 TCP/UDP校验和的生成和检查。带全球唯一MAC地址。

3.1原理图解析

根据开发板的原理图,重点看下CH182H2的应用部分。

MCU最小系统部分:

wKgZPGmNsTOAIKUJAAXjfKq6i-U850.png

PHY部分:

RMII接口部分,引出IO可使用逻辑分析抓信号:

wKgZPGmNsTWAPjDiAAFvnLvMQTw803.png

以太网接口部分:

wKgZO2mNsTWAboXVAAFi1-ndSi8958.png

PHY电源和复位部分:

wKgZPGmNsTaAZH1JAACwScfXTsQ621.png

从以上原理图可以看出PHY的外围电路是很简单的,可以降低BOM成本。

原理图分为以下部分来看:

1.电源

VDDIO: IO电源输入,对地接0.1uF电容。支持3.3V、2.5V或1.8V。

AVDD33: 3.3V主电源输入,对地接0.1uF并联10uF。

AVDDK:对地接1uF电容,供内置LDO用。实测应该为1.2V左右,最大1.5V。

DVDDK:对地接0.1uF电容,供内置LDO解耦用。实测应该为1.2V,最大1.5V。

2.MDIO

CH182系列MDIO、MDC均内置上拉电阻,可省外部上拉,简化电路。

3.复位

RSTB使用阻容复位即可,典型值4.7K,0.1uF。低电平有效。

4.LED

LED引脚的一个功能是配置PHY地址。

LED1 LED0组合决定PA1 PA0 PHY的地址,默认为01即LED0内部上拉,LED1内部下拉。

开发板中使用了默认配置,所以无需额外的4.7k的上下拉。

LED引脚本身还作为LED信号控制,用于表示10M还是100M速度,以及是否在通讯活动的状态,取决于寄存器配置LED_SEL不同,LED1和LED0的行为不一样,如下,默认LED_SEL为0b11

wKgZO2mNsTaAeZn8AAFYJPXS12s818.png

LED0还可以作为PMEB唤醒事件输出,低有效。

5.MDI

MDI_TX_P/N MDI_RX_P/N接网络变压器的TD+/- RD+/-即可,网络变压器中心抽头0.1uF对地即可,无需接电源。

6.中断

INTB引脚通过4.7k上拉到VDDIO。

需要在RMII模式下,作为中断输出,低有效。

7.晶振

XI,XO外接25M晶体,或者输入25M/50M时钟。PHY内部集成了负载电容为12pF的晶体所需的两个振荡电容,所以对于负载电容为12pF的晶体无需外接电容。

如果晶体负载电容大于12pF,则还需根据实际情况外接负载电容(在内部电容基础上再增加)。

8.RMII接口选择

RXDV引脚默认为内部下拉此时配置为MII接口,如果需要配置为RMII接口则RXDV需要外部接4.7k上拉到VDDIO。

9.TXC时钟模式

RMII模式下,RXD0引脚默认为下拉TXC输出50MHz时钟,

如果外部4.7KΩ上拉到VDDIO,则TXC输入50MHz时钟。

开发板中无外部上下拉,使用默认状态TXC输出时钟。

页7寄存器16也可配置RMII的TXC是输出还是输入时钟。

10.[R]MII接口

RXDV高有效表示有接收数据。同时用于配置RMII接口还是MII接口。

RXD0~3 MAC接收数据

RXC PHY输出时钟100M时25M,10M时2.5M

TXD0~3 MAC发送数据

TXCMII PHY输出时钟,RMII下PHY输出或者输入时钟(RXD0决定)

TXEN发送使能,高有效。

CRS_DV高有效,载波或者接收数据不为空闲时高。

COL 高有效,检测到碰撞为高

RXER 高有效,检测到错误为高

3.2寄存器

wKgZPGmNsTeAYPwEAAMqIIIid_0871.png

0号寄存器的速度和自动协商,双工模式是需要关注的,对于不能通过引脚配置这些参数的型号需要配置该寄存器,对于能通过引脚配置这些参数的型号则可以不配置该寄存器,CH182H2需要配置该寄存器。默认配置是100M,自动协商使能,全双工,所以默认配置即可满足一般使用。

wKgZO2mNsTiAR_9qAASeXgihFic305.png wKgZPGmNsTmAbQHRAAJejPn_tF4749.png

寄存器都是标准的。寄存器31用于页切换,基础寄存器是标准的,扩展寄存器由厂家自定义功能,详细内容需要咨询厂家。

3.3特点

详细参数,特点等可以参考数据手册,个人觉得以下特点值得特别提出

1.25M晶体(如果负载电容是12pF)无需外部电容,内置了负载电容为12pF的晶体对应的电容。

2.IO可配不同电压,支持3.3V、2.5V或1.8V。

3.P6引出了RMII接口,方便使用逻辑分析仪测试。

4.CH182D还内置唯一MAC地址。

5.内置以太网50Ω阻抗匹配电阻,外部不要再接49.9Ω或50Ω电阻,等效于电压驱动。

6.外围器件简单,BOM成本低。

3.4建议

开发板中建议CH182H2的VDDIO不要直连VCC182,而是通过跳线可外部供指定的电压或者使用板载默认的3.3V,方便评估VDDIO使用不同电压(最好是板载就可以选择不同电压,作为评估版要能通过配置就能评估所有功能)。

四、性能测试

这里来基于iperf进行TCP的收发性能测试,先来测试RAW发送可以验证PHY的速率,然后再测试TCP的收发性能。 实测结果先睹为快如下,详见后面的测试介绍。

1.Raw TX:93Mbps

2.TCP TX: 80Mbps

3. TCP RX: 70Mbps

4.1 Raw发送速度测试

基于CH32V307V-EVT-R3CH32V307EVTEVTEXAMETHMAC_RAW这个工程进行测试

注释掉接收处理与打印,只关注发送

void WCHNET_MainTask(void)
{    
  //RecDataPolling();    
  WCHNET_QueryPhySta();     /* Query external PHY status */    
  WCHNET_LinkProcessing();   /* process Link stage task */
}

发送代码

  static uint32_t sndlen = 0;
    static uint32_t tick1=0;
    static uint32_t tick2=0;
    extern uint32_t volatile LocalTime;
    while(1)
    {
        WCHNET_MainTask();
        if(LinkSta)
        {
            if(ETH_SUCCESS == MACRAW_Tx(ARPPackage, sizeof(ARPPackage))){
                ///if(++PktCnt % 100 == 0)
                ///    printf("PktCnt:%drn",PktCnt);
                ///Delay_Ms(100);
                sndlen += sizeof(ARPPackage);
                if(tick1 == 0){
                    tick1 = LocalTime;
                    tick2 = LocalTime;
                }else{
                    tick2 = LocalTime;
                }
                if (tick2 - tick1 >= 5000){
                    uint32_t speed;
                    speed=((uint64_t)sndlen/125)/(tick2-tick1); 
                    printf("%d Mbps!rn", speed);
                    tick1 = tick2;
                sndlen = 0;
                }
            }
        }
    }
}

可以看到几乎可以跑满100Mbps。

wKgZO2mNsTmAfP_5AAIjuO9UhWU154.png

4.2接收测试

作为servert接收

所以使用TCPServer的Demo

接收数据流如下:

WCHNET_HandleGlobalInt->WCHNET_HandleSockInt->WCHNET_DataLoopback

我们在WCHNET_DataLoopback记录接收指定长度数据后的时间,用于接收速度测试,

wKgZPGmNsTqAIn9ZAAF9IDKxEn4067.png

实测,接收速度最大可达70Mbps左右。

wKgZO2mNsTuAe2u_AAOxI3FtD1M976.png

关键代码如下

extern uint32_t volatile LocalTime;
void WCHNET_DataLoopback(u8 id)
{
    u32 len;
    u32 endAddr = SocketInf[id].RecvStartPoint + SocketInf[id].RecvBufLen;       //Receive buffer end address
    if ((SocketInf[id].RecvReadPoint + SocketInf[id].RecvRemLen) > endAddr) {    //Calculate the length of the received data
        len = endAddr - SocketInf[id].RecvReadPoint;
    }
    else {
        len = SocketInf[id].RecvRemLen;
    }
    static uint32_t recvlen = 0;
    static uint32_t tick1=0;
    static uint32_t tick2=0;
    recvlen += len;
    if(tick1 == 0){
        tick1 = LocalTime;
        tick2 = LocalTime;
    }else{
        tick2 = LocalTime;
    }
    
    if (tick2 - tick1 >= 5000){
        uint32_t speed;
        speed=((uint64_t)recvlen/125)/(tick2-tick1); 
        printf("%d Mbps!rn", speed);
        tick1 = tick2;
        recvlen = 0;
    }
    WCHNET_SocketRecv(id, NULL, &len);  
}

4.3发送测试

作为client发送

所以使用TCPClient的Demo

u8DESIP[4] = {192,168,1,100}; //destination IP address

改为电脑IP

u8DESIP[4] = {192,168,1,9};

端口对应

u16desport=1000; //destination portu16srcport=1000;                     //source port

增加变量,检测到链接或者断开时,设置对应标志,标志是链接状态时才发送

  //if (intstat & SINT_STAT_RECV)                               //receive data
    {
        WCHNET_DataLoopback(socketid);                          //Data loopback
    }
    volatileintconnect_flag=0;
 
    if (intstat&SINT_STAT_CONNECT)                            //connect successfully
    {
        connect_flag=1;
 
    if (intstat&SINT_STAT_DISCONNECT)                         //disconnect
    {
        connect_flag=0;
 
    if (intstat&SINT_STAT_TIM_OUT)                            //timeout disconnect
    {
        connect_flag=0;

接收处理这里不再发送避免干扰,单独添加发送测试函数


void WCHNET_DataLoopback(u8 id)
{
    u8 i;
    u32 len;
    u32 endAddr=SocketInf[id].RecvStartPoint+SocketInf[id].RecvBufLen;       //Receive buffer end address
 
    if ((SocketInf[id].RecvReadPoint+SocketInf[id].RecvRemLen) >endAddr) {    //Calculate the length of the received data
        len=endAddr-SocketInf[id].RecvReadPoint;
    }
    else {
        len=SocketInf[id].RecvRemLen;
    }
    //i = WCHNET_SocketSend(id, (u8 *) SocketInf[id].RecvReadPoint, &len);         //send data
    //if (i == WCHNET_ERR_SUCCESS) {
        WCHNET_SocketRecv(id, NULL, &len);                                       //Clear sent data
    //}

初始发送数据

  for (i=0; i< RECE_BUF_LEN; i++){
         SocketRecvBuf[0][i] =i&0xff;
    }

发送处理

extern uint32_t volatile LocalTime;
 
static voidsend_test(void){
    if(connect_flag){
        static uint32_t sndlen=0;
        static uint32_t tick1=0;
        static uint32_t tick2=0;
        u8 id=0;
        uint32_t len=RECE_BUF_LEN;
        u8 res=WCHNET_SocketSend(id, (u8*) SocketRecvBuf[id], &len); 
        if (res!=WCHNET_ERR_SUCCESS) {
            //printf("snd err:%drn",res);
            sndlen+=0;
        }else{
            sndlen+=len;
        }
        if(tick1==0){
            tick1=LocalTime;
            tick2=LocalTime;
        }else{
            tick2=LocalTime;
        }
        if (tick2-tick1>=5000){
            uint32_tspeed;
            speed=((uint64_t)sndlen/125)/(tick2-tick1); 
            printf("%d Mbps!rn", speed);
            tick1=tick2;
           sndlen=0;
        }
    }
}
 
    while(1)
    {
        /*Ethernet library main task function,
         * which needs to be called cyclically*/
        WCHNET_MainTask();
        /*Query the Ethernet global interrupt,
         * if there is an interrupt, call the global interrupt handler*/
        if(WCHNET_QueryGlobalInt())
        {
            WCHNET_HandleGlobalInt();
        }
 
        /* 发送测试 */
        send_test();
    }

实测如下

wKgZPGmNsTyAVPK3AAA6K6dYTEE322.png wKgZO2mNsTyAHb73AANu7dlDpJY303.png

发送速度为80Mbps左右,会有一些抖动,最大可达90Mbps,可以看到效率是非常不错的,支持硬件校验是一个很大的优势。

4.4速度优化建议

1.提高MCU主频

Usersystem_ch32v30x.c中改为144M

#defineSYSCLK_FREQ_144MHz_HSE 144000000

2.增加DMA描述符数/缓存区个数

根据应用场景看是大量收还是大量发,调大对应的方向的描述符数

比如发送多的场景可以加大ETH_TXBUFNB

Usernet_config.h中


#define ETH_TXBUFNB 16    /* The number of descriptors sent by the MAC  */
#define ETH_RXBUFNB 2    /* Number of MAC received descriptors  */

3.增加协议栈缓存区大小

Usernet_config.h中

根据应用场景看是大量收还是大量发,调大对应的方向的缓存大小。

比如发送多的场景可以加大WCHNET_NUM_TCP_SEG

#define RECE_BUF_LEN (WCHNET_TCP_MSS*2)   /* socket receive buffer size */
#define WCHNET_NUM_PBUF WCHNET_NUM_POOL_BUF   /* Number of PBUF structures */
#define WCHNET_NUM_TCP_SEG (WCHNET_NUM_TCP*8)   /* The number of TCP segments used to send */

4.打开硬件校验

这个是最能明显提升效率的,因为校验计算很占CPU带宽。

Usernet_config.h中

#defineHARDWARE_CHECKSUM_CONFIG   1  /* Hardware checksum checking and insertion configuration, 1: enable, 0: disable */

5.数据量尽量按最大包长填充,即应用上层协议的设计尽量不要使用短包。

五、总结建议

总的来说CH182H2的优点是很明显的,正如3.3的介绍,最主要的就是外围电路可以很简单,降低BOM成本,另外也有不同小封装可选,适应于尺寸限制等场景,同时也可以降低成本,所以选择100M以太网PHY芯片的话可以考虑下CH182系列。

选用CH32V30x等主控,基于MountRiverStudio开发,也是很方便的,测试跑RAW数据发送几乎能跑满硬件带宽,跑TCP效率也非常不错,发送可达80Mbps多。MountRiverStudio使用起来个人感觉还是非常丝滑方便的,界面也美观。

另外官方Demo提供了协议栈库可以直接使用减少开发工作量,而对于想自己移植第三方协议栈库或者直接面向底层编程的,可以参考下MAC Raw例程,可以基于此在上面移植以太网协议栈。RMII驱动层也是可以直接使用的。

注意ISP下载开发板BOOT0不要短接(默认是短接的)。

注意使用仿真器需要先切换到RV模式。

六、基于MounRiver_Studio开发(保姆级操作)

前面介绍了CH182H2这颗芯片和其对应的评估版,并进行了性能测试,对于只是想了解该芯片的可以参考,如果进一步想进行应用开发,则可参考本章内容。本章按照保姆级别操作记录,介绍基于官方的Demo开发实践。

6.1安装MounRiverStudio

从以下地址下载MounRiverStudio:

https://www.mounriver.com/download

wKgZPGmNsT2AIlOQAADEUll3BpE457.png

6.2导入工程

下载开发板资料包CH32V307EVT.ZIP,解压

https://www.wch.cn/downloads/CH32V307EVT_ZIP.html

双击CH32V307EVTEVTEXAMETHTCPServerTCPServer.wvproj打开tcpserver的例程。

6.2.1配置Netlib

我们这里要使用RMII,100M接口,所以要修改使用的驱动文件

右键eth_driver_RMII.c,Include/Exclude From Build添加到编译

wKgZO2mNsT6ANMkqAADx4w50zjk707.png

同样的方法将eth_driver_10M.c排除编译

即编译以下几个文件

wKgZPGmNsT-AfxqeAAD4X6X2BIk325.png

6.2.2配置浮点库

右键点击TCPServer->Properties

配置使能硬件单精度浮点

wKgZO2mNsT-AUjMKAAFU6evXB1k779.png

再配置链接对应的库文件(可省略)

wKgZPGmNsUCAKBNPAAEp5xiqi1Q634.png

配置完点击Apply

两个a文件只保留一个即可,这里使用float.a

也可以使用上述方法,将这个库排除编译。

wKgZO2mNsUGAZ0K1AAEHQpu9y3Y164.png

按delete按键选择remove

wKgZPGmNsUKAcp1iAAG_a8OfKD4628.png

6.2.3确认芯片型号

右键点击TCPServer->Properties,选择对应的MCU型号

wKgZO2mNsUKAF7N3AAGTR8pRsrA696.png

配置完点击Apply

6.3编译

菜单栏点击Project->build Project

编译完成

wKgZPGmNsUOAMj4sAAGSXt9Lh6g344.png

6.3.1编译注意事项

如果开启了微软电脑管家服务,MRS2检测到该服务可能导致编译变慢会弹窗提示如下。用户可以按弹窗提示,关闭该服务,编译速度就会恢复正常。

wKgZO2mNsUSAajqYAAXxD513D3U293.png

按照如下处理

右键点击左下角WIN图标->计算机管理->服务和应用程序->服务

找到Microsoft PC Manager Service,右键点击->属性

启动类型选择禁用,然后点击停止

wKgZO2mNsUWAapCPAARfQ_R6uZU331.png

6.4配置仿真

参考WCH-LinkUserManual

https://www.wch.cn/downloads/WCH-LinkUserManual_PDF.html

接入仿真器后设备管理器下外部接口目录下会看到对应的设备。

MounRiver Studio菜单栏Tools->WCH-LinkUtility

获取当前模式

wKgZPGmNsUWAMm0WAAe9thhqS-k807.png

设置为WCH-LinkRV

wKgZO2mNsUaAVXF2AAfHlEJpebQ445.png

右键点击TCPServer->Properties

设置仿真器和参数如下,一般默认即可

其中SVD下是指定寄存器描述文件,这样就可以查看各个外设寄存器

wKgZO2mNsUeAQKY1AAGjXJ2g-gU178.png wKgZPGmNsUiAZ7UuAAF3N8p7EKM590.png wKgZO2mNsUmAOgkRAAE5hbwI3y8113.png

然后点击甲壳虫图标进入仿真环境并下载程序

wKgZPGmNsUmAPu11AAIW3usM3n4442.png wKgZO2mNsUqAbu_mAARzZkenfr8843.png

可以查看外设寄存器。

wKgZPGmNsUuAGY-EAAJuxrTxEvI532.png

其他仿真操作,不同IDE都大同小异不再赘述。

新版本MounRiver基于VSCODE框架深度定制,明显比之前基于eclipse的更丝滑,轻量,美观。同时兼容了之前版本的操作习惯,方便熟悉MRS1的用户快速上手,另外对于熟悉VSCODE的用户也会觉得很熟悉可以直接上手。

6.5 ISP下载程序

手里没有WCH-LInk可以使用ISP下载

注意开发板上BOOT0默认跳线到了GND要断开。

BOOT0接VCC,BOOT1接GND是进下载模式,

BOOT0通过下载按键按下接VCC

wKgZO2mNsUyAb8yvAAEyR5PscpA342.png wKgZPGmNsUyABJHuAAOllK6L3gM024.png

以下地址下载WCHISPTool_Setup.exe

https://www.wch.cn/downloads/WCHISPTool_Setup_exe.html

双击WCHISPTool_Setup.exe安装

wKgZO2mNsU2AUCijAAbhs6OSBdg294.png wKgZPGmNsU6AMcG_AAKbh39IEUQ349.png wKgZO2mNsU-AHNeVAAIeLESELk4058.png wKgZPGmNsVCAH-PWAAJ5fMNZSqQ942.png wKgZO2mNsVCAZ3QtAAYusn7kbe4336.png wKgZPGmNsVGAFqxaAADwZevgAek975.png

选择MCU

wKgZO2mNsVKAe8KJAAPFnV7_teI191.png

为了方便可以先不使能读保护,否则使能了之后下次下载前需要先解除读保护

wKgZPGmNsVOAOuraAAIvjeTOZWc027.png

USB接P5,按下下载按键,按下复位按键

识别到USB设备

wKgZO2mNsVOAAV-JAAJi-9JsMuU447.png

选择HEX文件

CH32V307EVTEVTEXAMETHTCPServerobjTCPServer.hex

wKgZPGmNsVSAKXWyAAO7qwncdw8604.png

点击下载

wKgZO2mNsVWAIjXQAAR-br-jRlw721.png

6.6运行

接上串口线,参数为115200-8-n-1

wKgZPGmNsVaAWhN5AANt60n6l5A121.png

按键RST重启

串口打印如下

wKgZO2mNsVeAOOiJAAKsqS9SU1k211.png

Usermain.c中看到

开发板IP为

u8 IPAddr[4] = {192, 168, 1, 10}; //IP address

所以将电脑IP设置为192, 168, 1,9

打开网络调试助手

作为客户端,连接开发板的服务端192.168.1.10,端口1000

u16 srcport = 1000; //source port

wKgZPGmNsVeAAGiDAALCcskvX_Q865.png

客户端发送数据,开发板原样返回

开发板打印

wKgZO2mNsViALLVNAADBcS-jlWM535.png

Intstat这个打印在如下位置添加的

void WCHNET_HandleGlobalInt(void){    
  u8 intstat;    
  u16 i;    
  u8 socketint;
  intstat=WCHNET_GetGlobalInt();  //get global interrupt flag    
  printf("intstat:%xrn",intstat);

相关的处理逻辑位于

WCHNET_HandleSockInt

收到数据后原样返回


void WCHNET_HandleSockInt(u8 socketid, u8 intstat)
{
    u8i;
    if (intstat&SINT_STAT_RECV)      //receive data
    {
        WCHNET_DataLoopback(socketid);                            //Data loopback
    }

连接时打印信息

   if (intstat&SINT_STAT_CONNECT)                              //connect successfully
    {
#if KEEPALIVE_ENABLE
        WCHNET_SocketSetKeepLive(socketid, ENABLE);
#endif
        WCHNET_ModifyRecvBuf(socketid, (u32) SocketRecvBuf[socketid],
        RECE_BUF_LEN);
        for (i=0; i< WCHNET_MAX_SOCKET_NUM; i++) {
            if (socket[i] ==0xff) {                              //save connected socket id
                socket[i] =socketid;
                break;
            }
        }
        printf("TCP Connect Successrn");
        printf("socket id: %drn",socket[i]);
    }

其他逻辑,断开,超时等处理

    if (intstat&SINT_STAT_DISCONNECT)                           //disconnect
    {
        for (i=0; i< WCHNET_MAX_SOCKET_NUM; i++) {             //delete disconnected socket id
            if (socket[i] ==socketid) {
                socket[i] =0xff;
                break;
            }
        }
        printf("TCP Disconnectrn");
    }
    if (intstat&SINT_STAT_TIM_OUT)                              //timeout disconnect
    {
        for (i=0; i< WCHNET_MAX_SOCKET_NUM; i++) {             //delete disconnected socket id
            if (socket[i] ==socketid) {
                socket[i] =0xff;
                break;
            }
        }
        printf("TCP Timeoutrn");
    }