• 五、W5100S/W5500+RP2040树莓派Pico<UDP Client数据回环测试>


    1. 前言

      UDP是一种无连接的网络协议,它提供了一种简单的、不可靠的方式来进行数据传输。尽管它并不保证数据传输的完整性和顺序性,但UDP在某些场景下却具有独特的优势,例如在实时应用或网络游戏等领域中。

      本章将在UDP Client模式下进行数据回环测试。

      W5100S/W5500是一款集成全硬件 TCP/IP 协议栈的嵌入式以太网控制器,同时也是一颗工业级以太网控制芯片。在以太网应用中使用 W5100S/W5500 让用户可以更加方便地在设备之间实现远程连接和通信。

    2. 协议简介

    2.1 简述

      UDP是Open System Interconnection(开放式系统互联)参考模型中一种无连接的传输层协议,它提供面向事务的简单不可靠信息传送服务。UDP在IP报文的协议号是17。与传输控制协议(TCP)相对,UDP是一种无连接的、不可靠的协议,它提供了简单的数据传输服务。

      UDP协议不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用,包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。

      总的来说,虽然UDP不具备可靠性和流量控制等特性,但由于其低开销和高传输效率,使得UDP在音视频传输、实时通信等领域得到广泛应用。

    2.2 优点

    • 简单性:UDP的协议结构相对简单,这使得其在实现和使用上较为方便,对于某些简单数据传输任务来说,UDP可以更快地完成。
    • 高效性:UDP的数据报文头部开销较小,相对于TCP来说,其数据传输效率较高。在处理大数据量的情况下,UDP可以更好地利用网络带宽。
    • 实时性:UDP支持实时应用,例如视频会议和在线游戏等。这是因为UDP协议不提供数据包的分组、组装和排序功能,而是更注重速度和效率。
    • 应用广泛:由于UDP的简单和高效率,使其在许多网络管理任务、网络测试和实时多媒体应用中得到广泛应用。

    2.3 应用

    • 实时通信:如网络游戏、在线直播、VoIP(网络电话)等,需要实时传输音频、视频等数据流,通过UDP协议实现高效、实时的数据传输。
    • DNS查询:DNS(域名系统)使用UDP协议进行地址查询,因为UDP不需要建立连接,可以减少查询时间。
    • TFTP:文件传输协议TFTP(简单文件传输协议)使用UDP协议进行文件传输,因为它不需要建立连接,可以实现快速传输。
    • SNMP:网络管理协议SNMP(简单网络管理协议)使用UDP协议进行网络设备管理,因为UDP可以实现简单的请求和响应。
    • BOOTP:网络启动协议BOOTP(引导程序协议)使用UDP协议进行无盘工作站的引导,因为UDP可以实现简单的数据传输。

    3. WIZnet以太网芯片

    WIZnet 主流硬件协议栈以太网芯片参数对比

    ModelEmbedded CoreHost I/FTX/RX BufferHW SocketNetwork Performance
    W5100STCP/IPv4, MAC & PHY8bit BUS, SPI16KB4Max.25Mbps
    W6100TCP/IPv4/IPv6, MAC & PHY8bit BUS, Fast SPI32KB8Max.25Mbps
    W5500TCP/IPv4, MAC & PHYFast SPI32KB8Max 15Mbps
    1. W5100S/W6100 支持 8bit数据总线接口,网络传输速度会优于W5500。
    2. W6100 支持IPV6,与W5100S 硬件兼容,若已使用W5100S的用户需要支持IPv6,可以Pin to Pin兼容。
    3. W5500 拥有比 W5100S更多的 Socket数量以及发送与接收缓存

    4. UDP Client回环测试

    4.1 程序流程图

    在这里插入图片描述

    4.2 测试准备

    软件

    • Visual Studio Code
    • WIZnet UartTool
    • SocketTester

    硬件

    • W5100SIO模块 + RP2040 树莓派Pico开发板 或者 WIZnet W5100S-EVB-Pico开发板
    • Micro USB 接口的数据线
    • TTL 转 USB
    • 网线

    4.3 连接方式

    • 通过数据线连接PC的USB口(主要用于烧录程序,也可以虚拟出串口使用)
    • 通过TTL串口转USB,连接UART0 的默认引脚:
      • RP2040 GPIO 0(UART0 TX) <----> USB_TTL_RX
      • RP2040 GPIO 1(UART0 RX) <----> USB_TTL_TX
    • 使用模块连接RP2040进行连线时
      • RP2040 GPIO 16 <----> W5100S MISO
      • RP2040 GPIO 17 <----> W5100S CS
      • RP2040 GPIO 18 <----> W5100S SCK
      • RP2040 GPIO 19 <----> W5100S MOSI
      • RP2040 GPIO 20 <----> W5100S RST
    • 通过网线直接连接PC网口(或:PC和设备都通过网线连接交换机或路由器LAN口)

    4.4 相关代码

      我们直接打开udp_client.c文件(路径:examples/udp_client/udp_client.c)看下具体实现:

      可以看到这里是以DHCP模式配置网络信息的,因此在主控和W5100S初始化完成后,会进行DHCP初始化,然后增加一个定时器初始化,用来做DHCP过程中的计时以进行超时处理;接着进入DHCP配置网络信息,成功则直接进入循环调用回环测试函数,失败则用我们初始化的静态网络信息进行配置,然后再进入循环调用回环测试函数,如下所示:

    /* Network information to be configured. */
    wiz_NetInfo net_info = {
        .mac = {0x00, 0x08, 0xdc, 0x1e, 0xed, 0x2e}, // Configured MAC address
        .ip = {192, 168, 1, 10},                     // Configured IP address
        .sn = {255, 255, 255, 0},                    // Configured subnet mask
        .gw = {192, 168, 1, 1},                      // Configured gateway
        .dns = {8, 8, 8, 8},                         // Configured domain address
        .dhcp = NETINFO_DHCP};                       // Configured dhcp model,NETINFO_DHCP:use dhcp; NETINFO_STATIC: use static ip.
    
    wiz_NetInfo get_info;
    static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {
        0,
    };                                           // Send and receive cachestatic uint8_t destip[4]={192, 168, 1, 2};  // udp destination ip
    static uint8_t des_ip[4] = {192, 168, 1, 2}; // UDP IP address
    static uint16_t des_port = 8080;             // UDP port
    static uint8_t dhcp_get_ip_flag = 0;         // Define the DHCP acquisition flag
    
    int main()
    {
        struct repeating_timer timer; // Define the timer structure
    
        /* MCU init */
        stdio_init_all();     // Initialize the main control peripheral
        wizchip_initialize(); // Initialize the chip interface
    
        /*dhcp init*/
        DHCP_init(SOCKET_ID, ethernet_buf);                                   // DHCP initialization
        add_repeating_timer_ms(1000, repeating_timer_callback, NULL, &timer); // Add DHCP 1s Tick Timer handler
    
        printf("wiznet chip tcp server example.\r\n");
        network_init(&net_info);              // Configuring Network Information
        print_network_information(&get_info); // Read back the configuration information and print it
    
        while (true)
        {
            loopback_udpc(SOCKET_ID, ethernet_buf, des_ip, des_port); // udp loopback test
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

      跳进回环测试里面看下其具体实现: 该函数有这几个参数,socket端口号、数据收发缓存、目标IP地址、目标端口;可根据需要自行填入参数。其整体通过一个switch状态机轮询socket状态,根据不同进行相应的处理,依次完成了初始化、打开socket端口、连接服务端、收到数据后回传的操作 ;其中本地端口直接在函数内初始化了。如下所示:

    /**
     * @brief   udp client loopback test
     * @param   sn:         socket number
     * @param   buf:        Data sending and receiving cache
     * @param   destip:     Destination IP address
     * @param   destport:   Destination port
     * @return  value for SOCK_ERRORs,return 1:no error
    */
    int32_t loopback_udpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport)
    {
       int32_t ret;
       uint16_t size = 0, sentsize=0;
    
       static uint16_t any_port = 50000;
    
       switch(getSn_SR(sn))
       {
          case SOCK_UDP :
             // sendto(sn, "test", 4, destip, destport);
             if((size = getSn_RX_RSR(sn)) > 0)
             {
                if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
                ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
                buf[ret]=0x00;
                printf("recv form[%d.%d.%d.%d][%d]: %s\n", destip[0],destip[1],destip[2],destip[3],destport,buf);
                if(ret <= 0)
                {
    #ifdef _LOOPBACK_DEBUG_
                   printf("%d: recvfrom error. %ld\r\n",sn,ret);
    #endif
                   return ret;
                }
                size = (uint16_t) ret;
                sentsize = 0;
                while(sentsize != size)
                {
                   ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);
                   if(ret < 0)
                   {
    #ifdef _LOOPBACK_DEBUG_
                      printf("%d: sendto error. %ld\r\n",sn,ret);
    #endif
                      return ret;
                   }
                   sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
                }
             }
             break;
          case SOCK_CLOSED:
    #ifdef _LOOPBACK_DEBUG_
             //printf("%d:UDP loopback start\r\n",sn);
    #endif
             if((ret = socket(sn, Sn_MR_UDP, any_port, 0x00)) != sn)
                return ret;
    #ifdef _LOOPBACK_DEBUG_
             printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, any_port);
    #endif   
             break;
          default :
             break;
       }
       return 1;
       
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    4.5 测试现象

      硬件连接无误后,编译烧录程序(具体可参考第一章节),打开WIZ UartTool,选择对应的COM口,填入参数:波特率115200,8位数据位,1位停止位,无校验位,无流控,填完参数后点击open打开,观察串口打印的信息以获取设备运行状态;打开SocketTester,在左列填入相对应的参数,UDP 模式,本地IP填写电脑的IP,本地端口的填写可随机,但尽量不要使用特殊端口;然后根据设备通过DHCP获得的IP等信息,在下边远程IP地址栏填入设备IP和设备端口,因为UDP是无连接的,直接发送信息后可以看到回传现象,如下图所示:

    在这里插入图片描述

    5. 注意事项

    • UDP是无连接的,服务端发送消息后客户端收到才能看到现象
    • 如果想用WIZnet的W5500来实现本章的示例,我们只需修改两个地方即可:
    1. 在library/ioLibrary_Driver/Ethernet/下找到wizchip_conf.h这个头文件,将_WIZCHIP_ 宏定义修改为W5500;
    2. 在library下找到CMakeLists.txt文件,将COMPILE_SEL设置为ON即可,OFF为W5100S,ON为W5500。

    6. 相关链接

    WIZnet官网

    WIZnet官方库链接

    本章例程链接

    想了解更多,评论留言哦!

  • 相关阅读:
    电压基准源
    SpringBoot 配置CORS处理前后端分离跨域配置无效问题解析
    1031 Hello World for U
    linux使用docker实现redis主从复制和哨兵模式
    【Web系列二十五】前后端使用proto+grpc实现数据传输
    HR应用在线人才测评,给企业招聘带来的好处
    Linux中修改环境变量的几种方法比较分析
    【附源码】Python计算机毕业设计入学新生信息管理系统1
    Vue实现Hello World
    通过配置文件导入自己的jar包(Eclipse,包括打jar包)
  • 原文地址:https://blog.csdn.net/WIZnet2012/article/details/134044076