CH32V307 UDP 网络库 WCHNET_SocketUdpSendTo 发送问题 库bug

之前应用CH561出现问题,现在找销售要来最新的CH32V307的开发板 也是还有如下的问题:WCHNET_SocketUdpSendTo发送到一个不在线的 目的地IP  之后 整个socket 卡死,不能再发送 也不能恢复 直到重启。 这个bug 有没有其他使用者遇到过,还是根本不支持 直接

6月2日的evt测试表示没有问题


    while(1)
    {
        WCHNET_MainTask();

        if(WCHNET_QueryGlobalInt())
        {
            WCHNET_HandleGlobalInt();
        }

        if(keypress==1)       //PA0作为按键输入 按一次 发送数据到以下两个IP地址
        {
            i = WCHNET_SocketUdpSendTo( SocketId,str,&len,roomaddr1,7888) ;
            printf("roomaddr1=%d\r\n", i);

             i=WCHNET_SocketUdpSendTo( SocketId,str,&len,roomaddr2,7888) ;
             printf("roomaddr2=%d\r\n",i);

             keypress=0;
        }
    }

这个是我的代码,是否是我使用上的问题  roomaddr1  roomaddr2 均为 与本机ip同网段的IP,这个是主动发送 。只要这两个IP设备都在线 发送没有问题,只有有其一不在线的 则不能再发送。   

如果你是按照官方例程在接收回调函数里面再发送给对方,肯定没问题的!


我也测试了主动发送,没问题,只是打印出来GINT_STAT_UNREACH,估计你问题出在socketid身上


socketid  设置有什么 要求吗 就是按照官方设置了一个目的地地址  请指教

void WCHNET_CreateUdpSocket(void)

{

    u8 i;

    SOCK_INF TmpSocketInf;


    memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF));

    TmpSocketInf.SourPort = srcport;

    TmpSocketInf.ProtoType = PROTO_TYPE_UDP;

    TmpSocketInf.RecvStartPoint = (u32) SocketRecvBuf;

    TmpSocketInf.RecvBufLen = RECE_BUF_LEN;

    TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv;

    i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);

    printf("WCHNET_SocketCreat %d\r\n", SocketId);

    mStopIfError(i);

}


创建socketid 都是用的官方的例程函数



#include "string.h"
#include "debug.h"
#include "WCHNET.h"
#include "eth_driver.h"

u8 str[] = "ch03";
u8 roomaddr1[4] = {192,168,100,241};
u8 roomaddr2[4] = {192,168,100,242};
int   keypress=0;

u8 MACAddr[6];                                   //MAC address
u8 IPAddr[4] = { 192, 168, 100, 174 };              //IP address
u8 GWIPAddr[4] = { 192, 168, 100, 1 };             //Gateway IP address
u8 IPMask[4] = { 255, 255, 255, 0 };             //subnet mask
u8 IP255[4] = { 255, 255, 255, 255};             //subnet mask
u16 srcport = 1002;                              //source port

u8 SocketId;
u8 SocketRecvBuf[RECE_BUF_LEN];                  //socket receive buffer

void mStopIfError(u8 iError)
{
    if (iError == WCHNET_ERR_SUCCESS)
        return;
    printf("Error: %02X\r\n", (u16) iError);
}

void EXTI0_INT_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    EXTI_InitTypeDef EXTI_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* GPIOA ----> EXTI_Line0 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void TIM2_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = { 0 };

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 1000000 - 1;
    TIM_TimeBaseStructure.TIM_Prescaler = WCHNETTIMERPERIOD * 1000 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    TIM_Cmd(TIM2, ENABLE);
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    NVIC_EnableIRQ(TIM2_IRQn);
}

void WCHNET_UdpServerRecv(struct _SCOK_INF *socinf, u32 ipaddr, u16 port,
        u8 *buf, u32 len)
{
    u8 ip_addr[4], i;

    printf("Remote IP:");
    for (i = 0; i < 4; i++) {
        ip_addr[i] = ipaddr & 0xff;
        printf("%d ", ip_addr[i]);
        ipaddr = ipaddr >> 8;
    }

    printf("srcport = %d len = %d socketid = %d\r\n", port, len,
            socinf->SockIndex);

    WCHNET_SocketUdpSendTo(socinf->SockIndex, buf, &len, ip_addr, port);
}

void WCHNET_CreateUdpSocket (void)
{
    u8 i;
    SOCK_INF TmpSocketInf;

    memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF));
    TmpSocketInf.DesPort = 1002;
    TmpSocketInf.SourPort = 1002;
    TmpSocketInf.ProtoType = PROTO_TYPE_UDP;
    TmpSocketInf.RecvStartPoint = (u32) SocketRecvBuf;
    TmpSocketInf.RecvBufLen = RECE_BUF_LEN;
    TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv;
    i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);
    printf("WCHNET_SocketCreat %d\r\n", SocketId);
    mStopIfError(i);
}

void WCHNET_HandleSockInt(u8 socketid, u8 intstat)
{
    if (intstat & SINT_STAT_RECV)                               //receive data
    {
    }
    if (intstat & SINT_STAT_CONNECT)                            //connect successfully
    {
        printf("TCP Connect Success\r\n");
    }
    if (intstat & SINT_STAT_DISCONNECT)                         //disconnect
    {
        printf("TCP Disconnect\r\n");
    }
    if (intstat & SINT_STAT_TIM_OUT)                            //timeout disconnect
    {
        printf("TCP Timeout\r\n");
    }
}

void WCHNET_HandleGlobalInt(void)
{
    u8 intstat;
    u16 i;
    u8 socketint;

    intstat = WCHNET_GetGlobalInt();                              //get global interrupt flag
    if (intstat & GINT_STAT_UNREACH)                              //Unreachable interrupt
    {
        printf("GINT_STAT_UNREACH\r\n");
    }
    if (intstat & GINT_STAT_IP_CONFLI)                            //IP conflict
    {
        printf("GINT_STAT_IP_CONFLI\r\n");
    }
    if (intstat & GINT_STAT_PHY_CHANGE)                           //PHY status change
    {
        i = WCHNET_GetPHYStatus();
        if (i & PHY_Linked_Status)
            printf("PHY Link Success\r\n");
    }
    if (intstat & GINT_STAT_SOCKET) {                             //socket related interrupt
        for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) {
            socketint = WCHNET_GetSocketInt(i);
            if (socketint)
                WCHNET_HandleSockInt(i, socketint);
        }
    }
}

int main(void)
{
    u8 i;
    u32 len;
    len=4;
    Delay_Init();
    USART_Printf_Init(115200);                                    //USART initialize
    EXTI0_INT_INIT();
    printf("UdpServer Test\r\n");
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf("net version:%x\n", WCHNET_GetVer());
    if ( WCHNET_LIB_VER != WCHNET_GetVer()) {
        printf("version error.\n");
    }
    WCHNET_GetMacAddr(MACAddr);                                   //get the chip MAC address
    printf("mac addr:");
    for (int i = 0; i < 6; i++)
        printf("%x ", MACAddr[i]);
    printf("\n");
    TIM2_Init();
    i = ETH_LibInit(IPAddr, GWIPAddr, IPMask, MACAddr);           //Ethernet library initialize
    mStopIfError(i);
    if (i == WCHNET_ERR_SUCCESS)
        printf("WCHNET_LibInit Success\r\n");
    WCHNET_CreateUdpSocket();                                     //Create  UDP Socket

    while(1)
    {
        WCHNET_MainTask();

        if(WCHNET_QueryGlobalInt())
        {
            WCHNET_HandleGlobalInt();
        }

        if(keypress==1)       //PA0作为按键输入 按一次 发送数据到以下两个IP地址
        {
            i = WCHNET_SocketUdpSendTo( SocketId,str,&len,roomaddr1,1002) ;

           //  i=WCHNET_SocketUdpSendTo( SocketId,str,&len,roomaddr2,7888) ;
           //  printf("roomaddr2=%d\r\n",i);

             keypress=0;
        }
    }
}


/*以上是我整个main.c的全部代码,使用pa0中断 按下之后 发送一次数据,你可以修改IP地址 测试即可,对方使用电脑网络调试助手,现在即使不发给其他IP,第一次也发送不出去。一定要先收到电脑发来第一次数据之后,才可以 主动发送数据。现在测试到的就是 上电之后 一定要电脑先发数据过来,再按键 才可以发送数据到电脑。否则上电之后先按键发送了, 即使之后电脑再发数据, 按键的主动发送也不会成功,而且 如果上电之后 主动发送 会提示  TCP Timeout。


*/


以上是我整个main.c的全部代码,使用pa0中断 按下之后 发送一次数据,你可以修改IP地址 测试即可,对方使用电脑网络调试助手,现在即使不发给其他IP,第一次也发送不出去。一定要先收到电脑发来第一次数据之后,才可以 主动发送数据。现在测试到的就是 上电之后 一定要电脑先发数据过来,再按键 才可以发送数据到电脑。否则上电之后先按键发送了, 即使之后电脑再发数据, 按键的主动发送也不会成功,而且 如果上电之后 主动发送 会提示  TCP Timeout。


大概看了一下,其余都基本一样,除了这个函数 void WCHNET_CreatSocket(void)

这个是我使用的函数,全部功能正常,不会有第一次发送不了,也不会有超时发生,你说的问题,我这里一个也没有

void WCHNET_CreatSocket(void)

{

SOCK_INF TmpSocketInf;

memset((void *)&TmpSocketInf, 0, sizeof(SOCK_INF));

TmpSocketInf.SourPort = LocalPort;

TmpSocketInf.ProtoType = PROTO_TYPE_UDP;

TmpSocketInf.RecvBufLen = RECE_BUF_LEN;

TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv;

WCHNET_SocketCreat(&SocketId, &TmpSocketInf);

WCHNET_ModifyRecvBuf(SocketId, (u32)SocketRecvBuf[SocketId], RECE_BUF_LEN);

}



改成你这样还是不行,可能是板子硬件不行,板子是刚刚拿到的沁恒的开发板,调这个东西真是心累


出现相似的问题了,要先收到一组数据后才能发出去,请教一下怎么解决,方便的话可以看看代码吗


您好,我这边测试没有发现这种情况,不知您是采用怎样的方式测试的,我是通过按键,按一下发送数据,因为您一开始主动发的时候不知道接收端的端口,所以会出现数据不可达的情况,如图1,若您想接收到数据,可以先通过调试助手发一次数据,获取已连通的接收端端口,修改代码中的端口号,重新编译烧录之后(网络调试助手别断开),通过按键发送即可接收到数据,若您是直接建立的固定端口,则不需要上述操作,直接通过按键发送即可接收到数据。测试结果如图2所示,测试例程已附上,您可以测试一下,后续有问题可以通过邮箱联系:kx@wch.cn

图1:

image.png

图2

image.png

icon_rar.gifETH-UDP.zip



只有登录才能回复,可以选择微信账号登录