1. 程式人生 > 其它 >【STM32F429】第11章 ThreadX NetXDUO之UDP客戶端/伺服器

【STM32F429】第11章 ThreadX NetXDUO之UDP客戶端/伺服器

最新教程下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=104619

第11章 ThreadX NetXDUO之UDP客戶端/伺服器

本章節為大家講解NetXDUO的UDP客戶端實現,學習本章節前,務必要優先學習第10章UDP傳輸控制協議基礎知識。有了這些基礎知識之後,再搞本章節會有事半功倍的效果。

11.1 初學者重要提示

11.2 UDP的API函式

11.3 UDP的實現方法

11.4 網路除錯助手和板子的除錯操作步驟

11.5 實驗例程說明

11.6 總結

11.1 初學者重要提示

1、 學習本章節前,務必保證已經學習了第10章的基礎知識。

2、 本章要掌握的函式稍多,可以先學會基本的使用,然後再深入瞭解這些函式使用時的注意事項,爭取達到熟練使用。

3、 ThreadX NetXDUO的UDP Socket資料包申請和釋放問題

  • 函式nx_udp_socket_receive 會申請一個NX_PACKET資料包用於接收,如果使用者不使用了必須使用函式nx_packet_release釋放。
  • 使用函式nx_udp_socket_send必須有申請好的NX_PACKET資料包,可以使用函式nx_packet_allocate申請,也可以使用nx_udp_socket_receive申請的。

特別要注意的地方來了,函式nx_udp_socket_send呼叫後會釋放nx_packet_allocate或者nx_udp_socket_receive申請的資料包。無需使用者再去呼叫函式nx_packet_release釋放。

11.2 UDP的API函式

11.2.1 函式nx_system_initialize

函式原型:

VOID nx_system_initialize(VOID);

函式描述:

NetXDUO初始化,所有其它功能呼叫之前必須優先呼叫此函式。

11.2.2 函式nx_packet_pool_create

函式原型:

UINT nx_packet_pool_create(
                          NX_PACKET_POOL *pool_ptr,
                          CHAR *name,
                          ULONG payload_size,
                          VOID 
*memory_ptr, ULONG memory_size);

函式描述:

此函式用於資料包記憶體池建立

函式引數:

  1. 第1個引數是記憶體池控制塊的地址。
  2. 第2個引數是記憶體池名字。
  3. 第3個引數是記憶體池中每個資料包的位元組數。 此值必須至少為 40 個位元組,並且還必須可以被 4 整除。
  4. 第4個引數是記憶體池中資料地址,此地址必須ULONG對齊。
  5. 第5個引數是記憶體池大小。
  6. 返回值:
  • NX_SUCCESS:(0x00) 建立記憶體池成功。
  • NX_PTR_ERROR:(0x07) 第1個引數地址無效。
  • NX_SIZE_ERROR:(0x09) 第5個引數記憶體池大小無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。

使用舉例:

  /* 建立記憶體池 */
    status =  nx_packet_pool_create(&pool_0,                 /* 記憶體池控制塊 */
                                    "NetX Main Packet Pool",/* 記憶體池名 */
               1536, /* 記憶體池每個資料包大小,單位位元組此值必須至少為 40 個位元組,並且還必須可以被 4 整除 */
             (ULONG*)(((int)packet_pool_area + 15) & ~15) ,/* 記憶體池地址,此地址必須ULONG對齊 */
               NX_PACKET_POOL_SIZE);                        /* 記憶體池大小 */       

11.2.3 函式nx_ip_create

函式原型:

UINT nx_ip_create(
    NX_IP *ip_ptr, 
    CHAR *name, ULONG ip_address,
    ULONG network_mask, 
    NX_PACKET_POOL *default_pool,
    VOID (*ip_network_driver)(NX_IP_DRIVER *),
    VOID *memory_ptr, 
    ULONG memory_size,
    UINT priority);                    

函式描述:

此函式使用使用者提供的 IP 地址,資料包記憶體記憶體池和網路驅動程式建立 IP 例項。注意,直到 IP任務執行之後,才會呼叫網路驅動。

函式引數:

  1. 第1個引數是建立IP例項的控制塊指標。
  2. 第2個引數是IP例項的名字。
  3. 第3個引數是IP地址。
  4. 第4個引數是子網掩碼
  5. 第5個引數是記憶體池地址。
  6. 第6個引數是網絡卡驅動地址。
  7. 第7個引數是IP任務棧地址
  8. 第8個引數是IP任務棧大小,單位位元組。
  9. 第9個引數是IP任務優先順序。
  10. 返回值
  • NX_SUCCESS:(0x00) 建立 IP 例項成功。
  • NX_NOT_IMPLEMENTED:(0x4A) 未正確配置 NetX Duo 庫。
  • NX_PTR_ERROR:(0x07) IP控制塊地址、網路驅動函式指標、記憶體池地址或任務棧地址無效。
  • NX_SIZE_ERROR:(0x09) 提供的任務棧大小太小。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_IP_ADDRESS_ERROR:(0x21) 提供的 IP 地址無效。
  • NX_OPTION_ERROR:(0x21) 提供的 IP 任務優先順序無效。

使用舉例:

/* 例化IP */
    status = nx_ip_create(&ip_0,                                                   /* IP例項控制塊 */                                    
                            "NetX IP Instance 0",                                  /* IP例項名 */     
                            IP_ADDRESS(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3),    /* IP地址 */
                            0xFFFFFF00UL,                                          /* 子網掩碼 */
                            &pool_0,                                               /* 記憶體池 */
                        nx_driver_stm32h7xx,                                   /* 網絡卡驅動 */
                            (UCHAR*)AppTaskNetXStk,                                /* IP任務棧地址 */
                            sizeof(AppTaskNetXStk),                             /* IP任務棧大小,單位位元組 */
                            APP_CFG_TASK_NETX_PRIO);                            /* IP任務優先順序 */

11.2.4 函式nx_arp_enable

函式原型:

UINT nx_arp_enable(
    NX_IP *ip_ptr, 
    VOID *arp_cache_memory,
    ULONG arp_cache_size);                

函式描述:

此函式用於使能ARP地址解析。

函式引數:

  1. ip_ptr:IP例項地址。
  2. arp_cache_memory:ARP快取地址。
  3. arp_cache_size:每個 ARP 條目均為 52 個位元組,因此,ARP 條目總數是52位元組整數倍。
  4. 返回值
  • NX_SUCCESS:(0x00) 啟用 ARP 成功。
  • NX_PTR_ERROR:(0x07) IP例項地址或ARP快取地址無效。
  • NX_SIZE_ERROR:(0x09) 使用者提供的 ARP 快取記憶體太小。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_ALREADY_ENABLED:(0x15) 此元件已啟用。

使用舉例:

int32_t tcp_sock;

tcp_sock = netTCP_GetSocket (tcp_cb_server);
    
if (tcp_sock > 0) 
{
res = netTCP_Listen (tcp_sock, PORT_NUM);
}

if(netTCP_SendReady(tcp_sock) == true )
{

}

11.2.5 函式nx_ip_fragment_enable

函式原型:

UINT nx_ip_fragment_enable(NX_IP *ip_ptr);

函式描述:

此函式用於啟用 IPv4 和 IPv6 資料包分段和重組功能。建立 IP 任務時,此服務會自動禁用。

函式引數:

  1. 第1個引數是IP例項地址。
  2. 返回值
  • NX_SUCCESS:(0x00) 啟用 IP 分段成功。
  • NX_PTR_ERROR:(0x07) IP 例項地址無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_NOT_ENABLED:(0x14) IP 分段功能未編譯到 NetX Duo 中。

使用舉例:

    /* 使能fragment */    
status = nx_ip_fragment_enable(&ip_0);

11.2.6 函式nx_udp_enable

函式原型:

UINT nx_udp_enable(NX_IP *ip_ptr);

函式描述:

此函式用於使能UDP元件。

函式引數:

  1. 第1個引數是IP例項地址。
  2. 返回值
  • NX_SUCCESS:(0x00) 啟用 UDP 成功。
  • NX_PTR_ERROR:(0x07) IP 指標無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_ALREADY_ENABLED:(0x15) 此元件已啟用。

使用舉例:

    /* 使能UDP */
    status =  nx_udp_enable(&ip_0);

11.2.7 函式nx_udp_socket_create

函式原型:

UINT nx_udp_socket_create(
    NX_IP *ip_ptr,
    NX_UDP_SOCKET *socket_ptr, 
    CHAR *name,
    ULONG type_of_service, 
    ULONG fragment,
    UINT time_to_live, 
    ULONG queue_maximum);

函式描述:

此函式用於建立UDP Socket。

函式引數:

1、 第1個引數是IP例項指標。

2、 第2個引數是UDP Socket指標。

3、 第3個引數是UDP Socket名字。

4、 第4個引數是傳輸服務型別,支援的引數如下:

  • NX_IP_NORMAL (0x00000000)
  • NX_IP_MIN_DELAY (0x00100000)
  • NX_IP_MAX_DATA (0x00080000)
  • NX_IP_MAX_RELIABLE (0x00040000)
  • NX_IP_MIN_COST (0x00020000)

5、 第5個引數是指定是否允許進行 IP 分段。 如果指定 NX_FRAGMENT_OKAY (0x0),則允許進行 IP 分段。如果指定 NX_DONT_FRAGMENT (0x4000),則會禁止進行 IP 分段。

6、 第6個引數是指定一個 8 位的值,用於定義此資料包在被丟棄之前可通過的路由器數目。 預設值由 NX_IP_TIME_TO_LIVE 指定。

7、 第7個引數是支援的UDP Socket報文最大數目。達到最大值後,接收到每個新資料包時,都會釋放最早的 UDP 資料包。

8、 返回值

  • NX_SUCCESS:(0x00) 建立 UDP Socket成功。
  • NX_OPTION_ERROR:(0x0A) 服務型別、分段或生存時間選項無效。
  • NX_PTR_ERROR:(0x07) IP 或Socket指標無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_NOT_ENABLED (0x14) 尚未啟用此元件。

使用舉例:

    /* 建立UDP socket */
    ret = nx_udp_socket_create(&ip_0,                 /* IP例項控制塊 */    
                                &UDPSocket,           /* UDP控制塊 */ 
                                "UDP Server Socket",  /* UDP名 */ 
                                NX_IP_NORMAL,         /* IP服務型別 */ 
                                NX_FRAGMENT_OKAY,     /* 使能IP分段 */ 
                                NX_IP_TIME_TO_LIVE,   /*用於定義此資料包在被丟棄之前可通過的路由器數目 */ 
                                512);                 /* 支援的報文數 */

11.2.8 函式nx_udp_socket_bind

函式原型:

UINT nx_udp_socket_bind(
    NX_UDP_SOCKET *socket_ptr, 
    UINT port,
    ULONG wait_option);

函式描述:

此函式用於為建立的UDP Socket繫結埠。如果設定的埠號還不可用,可以設定等待時間。

函式引數:

1、 第1個引數是UDP Socket指標。

2、 第2個引數是繫結的埠,範圍1 -65535。如果設定為NX_ANY_PORT(0x0000),則會搜尋一個可用埠號。

3、 第3個引數是埠號不可用時,等待時間定義:

  • NX_NO_WAIT (0x00000000)
  • NX_WAIT_FOREVER (0xFFFFFFFF)
  • 等待時間:(0x00000001 到 0xFFFFFFFE),單位是ThreadX系統時鐘節拍。

4、 返回值

  • NX_SUCCESS:(0x00) 繫結UDP Socket成功。
  • NX_ALREADY_BOUND:(0x22) 此UDP Socket已與另一 UDP 埠繫結。
  • NX_PORT_UNAVAILABLE:(0x23) 埠已與其他Socket繫結。
  • NX_NO_FREE_PORTS:(0x45) 沒有可用的埠。
  • NX_WAIT_ABORTED:(0x1A) 已通過呼叫 tx_thread_wait_abort 中止請求。
  • NX_INVALID_PORT:(0x46) 埠無效。
  • NX_PTR_ERROR:(0x07) Socket指標無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_NOT_ENABLED:(0x14) 此元件尚未啟用。

使用舉例:

    /* UDP Socket繫結埠 */
    ret = nx_udp_socket_bind(&UDPSocket, DEFAULT_PORT, TX_WAIT_FOREVER);

    if (ret != NX_SUCCESS)
    {
        Error_Handler(__FILE__, __LINE__);   
    }

11.2.9 函式nx_packet_data_retrieve

函式原型:

UINT nx_packet_data_retrieve(
    NX_PACKET *packet_ptr,
    VOID *buffer_start,
    ULONG *bytes_copied);

函式描述:

此函式用於將提供的資料包中的資料複製到提供的緩衝區。複製的實際位元組數由形參bytes_copied 所指向的儲存單元返回。

注意,此函式不會更改該資料包的內部狀態。檢索的資料仍存在於該資料包中。

函式引數:

  1. 第1個引數是指向源資料包的指標
  2. 第2個引數是目的資料包的地址。
  3. 第3個引數是最終複製的位元組數儲存地址。
  4. 返回值,返回以下幾種狀態值:
  • NX_SUCCESS:(0x00)複製資料包資料成功。
  • NX_INVALID_PACKET:(0x12) 資料包無效。
  • NX_PTR_ERROR:(0x07) 形參地址無效。

注意事項:

目標緩衝區的大小必須足以容納該資料包的內容。否則記憶體會損壞,導致不可預知的結果。

使用舉例:

/* 獲取客戶端發來的資料 */
 nx_packet_data_retrieve(data_packet,    /* 接收到的資料包 */
                      data_buffer,    /* 解析出資料 */
                      &bytes_read);   /* 資料大小 */

11.2.10 函式nx_packet_data_extract_offset

函式原型:

UINT nx_packet_data_extract_offset(
    NX_PACKET *packet_ptr,
    ULONG offset,
    VOID *buffer_start,
    ULONG buffer_length,
    ULONG *bytes_copied);

函式描述:

此函式將NetX Duo 資料包中的資料複製到指定緩衝區中,可以指定要複製的資料偏移位置。實際複製的位元組數在 bytes_copied 中返回。此函式不會從資料包中刪除資料,也不會調整前置指標或其他內部狀態資訊。

函式引數:

  1. 第1個引數是資料包指標。
  2. 第2個引數是資料包的偏移地址。
  3. 第3個引數是複製後要儲存的緩衝地址。
  4. 第4個引數是要複製的位元組數。
  5. 第5個引數是實際複製的位元組數
  6. 返回值,返回以下幾種狀態值:
  • NX_SUCCESS:(0x00)複製資料包資料成功。
  • NX_PACKET_OFFSET_ERROR (0x53)提供了無效的偏移值。
  • NX_PTR_ERROR:(0x07) 形參地址無效。

注意事項:

目標緩衝區的大小必須足以容納該資料包的內容。否則記憶體會損壞,導致不可預知的結果。

使用舉例:

/* 將UDP資料包中的資料複製到緩衝data_buffer */
  nx_packet_data_extract_offset(RecPacket,            /* 資料包 */
                                0,                    /* 資料包地址偏移 */
                                data_buffer,          /* 目標緩衝 */
                                sizeof(data_buffer),  /* 目標緩衝大小 */
                                &bytes_read);         /* 資料複製的位元組數 */

11.2.11 函式nx_udp_socket_receive

函式原型:

UINT nx_udp_socket_receive(
    NX_UDP_SOCKET *socket_ptr,
    NX_PACKET **packet_ptr,
    ULONG wait_option);

函式描述:

此函式用於從指定的Socket接收UDP資料,如果指定的Socket上沒有已經排隊的資料,則呼叫方會根據提供的等待選項引數掛起。

函式引數:

1、 第1個引數是UDP Socket指標

2、 第2個引數是UDP資料包指標。

3、 第3個引數是Socket佇列上沒有資料時的處理:

  • NX_NO_WAIT (0x00000000)。
  • NX_WAIT_FOREVER (0xFFFFFFFF)。
  • 以時鐘週期為單位的超時值(0x00000001 到 0xFFFFFFFE)。

4、 返回值:

  • NX_SUCCESS:(0x00) 接收Socket資料成功。
  • NX_NOT_BOUND:(0x24) Socket未繫結。
  • NX_NO_PACKET:(0x01) 未收到任何資料。
  • NX_WAIT_ABORTED:(0x1A) 通過呼叫 tx_thread_wait_abort 中止掛起。
  • NX_PTR_ERROR:(0x07) Socket指標或返回資料包指標無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_NOT_ENABLED:(0x14) 此元件尚未啟用。

注意事項:

  1. 如果返回了 NX_SUCCESS,則應用程式負責:不再需要收到資料包時將其釋放。

使用舉例:

/* 接收資料 */
ret = nx_udp_socket_receive(&UDPSocket, &RecPacket, TX_WAIT_FOREVER);

11.2.12 函式nx_udp_socket_send

函式原型:

UINT nx_udp_socket_send(
    NX_UDP_SOCKET *socket_ptr,
    NX_PACKET *packet_ptr,
    ULONG ip_address, 
    UINT port);

函式描述:

此函式用於UDP Socket資料傳送。注意,無論 UDP 資料報是否已成功傳送,此服務都會立即返回。。

函式引數:

  1. 第1個引數是UDP Socket控制代碼。
  2. 第2個引數是UDP資料包指標。
  3. 第3個引數是目標地址。
  4. 第4個引數是目標埠號,範圍1到65535。
  5. 返回值,返回以下幾種狀態值:
  • NX_SUCCESS:(0x00) Socket傳送成功。
  • NX_NOT_BOUND:(0x24) Socket未與任何埠繫結。
  • NX_NO_INTERFACE_ADDRESS:(0x50) 找不到合適的傳出介面。
  • NX_TX_QUEUE_DEPTH:(0x49) 已達到最大傳輸佇列深度。
  • NX_OVERFLOW:(0x03) 資料包追加指標無效。
  • NX_UNDERFLOW:(0x02) 資料包前置指標無效。
  • NX_PTR_ERROR:(0x07) 套接字指標無效。
  • NX_CALLER_ERROR:(0x11) 此服務的呼叫方無效。
  • NX_NOT_ENABLED:(0x14) 此元件尚未啟用。

使用舉例:

/* 傳送資料包到UDP傳送端 */
ret =  nx_udp_socket_send(&UDPSocket, TraPacket, source_ip_address, source_port);

11.2.13 函式nx_packet_release

函式原型:

UINT nx_packet_release(NX_PACKET *packet_ptr);

函式描述:

此函式用於釋放資料包,包括連結到指定資料包的任何其他資料包。如果有其他任務在等待這個資料包,則該任務會獲得該資料包並繼續執行。

函式引數:

  1. 第1個引數是資料包地址。
  2. 返回值,返回以下幾種狀態值:
  • NX_SUCCESS:(0x00) 釋放資料包成功。
  • NX_PTR_ERROR:(0x07) 資料包指標無效。
  • NX_UNDERFLOW:(0x02) 預置指標小於有效負載開始位置。
  • NX_OVERFLOW:(0x03) 追加指標大於有效負載結束位置。

注意事項:

應用程式必須防止多次釋放同一資料包,否則會導致不可預知的結果。

11.3 UDP的實現方法

11.3.1 NetXDUO初始化

建立UDP前,要初始化NetX,建立記憶體池,例化IP:

/*
*********************************************************************************************************
*    函 數 名: NetXTest
*    功能說明: TCPnet應用
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/    
void NetXTest(void)
{
    UINT status;
    UINT ret;
    ULONG socket_state;
    UINT old_priority;

    NX_PACKET *data_packet;
    ULONG bytes_read;
    
    ULONG peer_ip_address;
    ULONG peer_port;
    
    
    /* 初始化NetX */
    nx_system_initialize();

    /* 建立記憶體池 */
    status =  nx_packet_pool_create(&pool_0,                 /* 記憶體池控制塊 */
                                     "NetX Main Packet Pool",/* 記憶體池名 */
               1536, /* 記憶體池每個資料包大小,單位位元組此值必須至少為 40 個位元組,並且還必須可以被 4 整除 */
             (ULONG*)(((int)packet_pool_area + 15) & ~15) ,/* 記憶體池地址,此地址必須ULONG對齊 */
               NX_PACKET_POOL_SIZE);                        /* 記憶體池大小 */                  
          
    /* 檢測建立是否失敗 */
    if (status) error_counter++;

    /* 例化IP */
    status = nx_ip_create(&ip_0,                                                   /* IP例項控制塊 */                                    
                            "NetX IP Instance 0",                                  /* IP例項名 */     
                            IP_ADDRESS(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3),    /* IP地址 */
                            0xFFFFFF00UL,                                          /* 子網掩碼 */
                            &pool_0,                                               /* 記憶體池 */
                        nx_driver_stm32h7xx,                                   /* 網絡卡驅動 */
                            (UCHAR*)AppTaskNetXStk,                                /* IP任務棧地址 */
                            sizeof(AppTaskNetXStk),                             /* IP任務棧大小,單位位元組 */
                            APP_CFG_TASK_NETX_PRIO);                            /* IP任務優先順序 */
                            
            
    /* 檢測建立是否失敗 */
    if (status) error_counter++;

    /* 使能ARP,並提供ARP快取 */
    status =  nx_arp_enable(&ip_0,               /* IP例項控制塊 */
                     (void *)arp_space_area,  /* ARP快取地址 */
         sizeof(arp_space_area));   /* 每個 ARP 條目均為 52 個位元組,因此,ARP 條目總數是52位元組整數倍 */

    /* 使能fragment */    
    status = nx_ip_fragment_enable(&ip_0);

    /* 檢測使能成功 */
    if (status) error_counter++;

    /* 使能TCP */
    status =  nx_tcp_enable(&ip_0);

    /* 檢測使能成功 */
    if (status) error_counter++;

    /* 使能UDP  */
    status =  nx_udp_enable(&ip_0);

    /* 檢測使能成功 */
    if (status) error_counter++;

    /* 使能ICMP */
    status =  nx_icmp_enable(&ip_0);

    /* 檢測使能成功 */
    if (status) error_counter++;   
    
    /* NETX初始化完畢後,重新設定優先順序 */
    tx_thread_priority_change(netx_thread_ptr, APP_CFG_TASK_NETX_PRIO1, &old_priority);
tx_thread_priority_change(&AppTaskNetXProTCB, APP_CFG_TASK_NetXPro_PRIO1, &old_priority);

    /* 省略 */
}

程式末尾務優先順序做了特別處理,建立的時候先設定為低優先順序,檢測到網線正常連線並初始了網路後將優先順序設定到正常水平。

11.3.2 UDP實現

下面是建立UDP:

/*
*********************************************************************************************************
*    函 數 名: NetXTest
*    功能說明: TCPnet應用
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/    
void NetXTest(void)
{
  
     /* 省略 */


    /* 建立UDP socket */
    ret = nx_udp_socket_create(&ip_0,                 /* IP例項控制塊 */    
                                &UDPSocket,           /* UDP控制塊 */ 
                                "UDP Server Socket",  /* UDP名 */ 
                                NX_IP_NORMAL,         /* IP服務型別 */ 
                                NX_FRAGMENT_OKAY,     /* 使能IP分段 */ 
                                NX_IP_TIME_TO_LIVE,   /* 用於定義此資料包在被丟棄之前可通過的路由器數目 */ 
                                512);                 /* 支援的報文數 */

    if (ret != NX_SUCCESS)
    {
        Error_Handler(__FILE__, __LINE__);   
    }
    
    /* UDP Socket繫結埠 */
    ret = nx_udp_socket_bind(&UDPSocket, DEFAULT_PORT, TX_WAIT_FOREVER);

    if (ret != NX_SUCCESS)
    {
        Error_Handler(__FILE__, __LINE__);   
    }

     /* 省略 */
}

11.3.3 UDP迴環通訊實現

迴環的意思就是電腦端網路助手傳送資料給板子後,板子再將資料返回。為了方便大家使用,本例子將接收資料包和傳送資料包分別做了定義:

/*
*********************************************************************************************************
*    函 數 名: NetXTest
*    功能說明: TCPnet應用
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/    
void NetXTest(void)
{
  
     /* 省略 */

       /* 接收資料 */
        ret = nx_udp_socket_receive(&UDPSocket, &RecPacket, TX_WAIT_FOREVER);

        if (ret == NX_SUCCESS)
        {
            /* 將UDP資料包中的資料複製到緩衝data_buffer */
            nx_packet_data_extract_offset(RecPacket,            /* 資料包 */
                                          0,                    /* 資料包地址偏移 */
                                          data_buffer,          /* 目標緩衝 */
                                          sizeof(data_buffer),  /* 目標緩衝大小 */
                                          &bytes_read);         /* 資料複製的位元組數 */

            /* 獲取遠端埠和IP  */
            nx_udp_source_extract(RecPacket, &source_ip_address, &source_port);

            /* 列印接收到資料 */
            PRINT_DATA(source_ip_address, source_port, data_buffer);

            /* 釋放資料包 */
            nx_packet_release(RecPacket);

            /* 申請傳送資料包 */
            ret = nx_packet_allocate(&pool_0, &TraPacket, NX_UDP_PACKET, TX_WAIT_FOREVER);

            if (ret)
            {
                Error_Handler(__FILE__, __LINE__);  
            }

            sprintf((char *)sendbuf, "sendbuf = %d\r\n", count++);

            /*將要傳送的資料附加到TraPacket */
            ret = nx_packet_data_append(TraPacket, (VOID *)sendbuf, strlen((char *)sendbuf), 
&pool_0, TX_WAIT_FOREVER);

            if (ret)
            {
                Error_Handler(__FILE__, __LINE__);
            }

            /* 傳送資料包到UDP傳送端 */
            ret =  nx_udp_socket_send(&UDPSocket, TraPacket, source_ip_address, source_port);

        }
    }      

     /* 省略 */
}

11.4 網路除錯助手和板子的除錯操作步驟

我們這裡使用下面這款除錯助手,當然,任何其它網路除錯助手均可,不限制:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=1568

11.4.1 測試使用的DM916X網口並注意跳線帽

測試時,網線要插到DM916X網口上:

特別注意此處跳線帽的位置,要短接PG11:

11.4.2 RJ45網路變壓器插座上綠燈和黃燈現象

各種網絡卡、交換機等網路裝置都不一樣,一般來講:綠燈分為亮或不亮(代表網路速度),黃燈分為閃爍或不閃爍(代表是否有資料收發)。

綠燈:長亮代表100M; 不亮代表10M。

黃燈:長亮代表無資料收發; 閃爍代表有資料收發。

也有些千兆網絡卡的燈以顏色區分,不亮代表10M / 綠色代表100M / 黃色代表1000M。現在10M的網路基本看不到了,如果一個燈長亮,基本可以說明100M網路或更高,而另一個燈時而閃爍,那代表有資料收發,具體要看網路裝置了。甚至有些低等網絡卡如TP-LINK,只有一個燈,亮代表連通,閃爍代表資料收發。

對於開發板上面的RJ45網路變壓器插座上面的燈而言,綠燈代表資料收發,長亮的話表示無資料收發,閃爍代表有資料收發。黃燈代表網路速度,長亮代表100M,不亮代表10M。

11.4.3 第1步,設定板子IP地址

我們這裡使用使用固定IP(或者說靜態IP一個意思),設定也比較省事。我們這裡以開發板和電腦直連的方式進行說明,即通過一根網線直接將開發板的網口和電腦端的網口連線起來即可。如果大家使用的是筆記本,強烈推薦測試期間將筆記本的WIFI網路禁止,各種代理軟體和虛擬網絡卡也暫時關閉。等測試完畢了再逐一開啟,檢視是否有問題。

對於固定IP方式,也可以接到路由器或者交換機上面測試,特別注意板子設定的IP地址不要跟路由器或者交換機上其它裝置的IP衝突了,測試階段還是建議採用電腦直連方式,跑通了再跑其它方式。

在檔案demo_dm9162_netx.h中設定IP地址,具體配置如下(大家更新自己的情況修改):

/*
*********************************************************************************************************
*                                        IP相關
*********************************************************************************************************
*/
#define DEFAULT_PORT                    1000    /* TCP伺服器監聽埠號 */

#define IP_ADDR0                        192
#define IP_ADDR1                        168
#define IP_ADDR2                        28
#define IP_ADDR3                        245  

11.4.4 第2步,設定電腦IP地址

一定要將電腦端的IP地址設定到跟開發板在一個IP段,即都是192.168.28.X。第2步中已經將開發板的IP設定為192.168.28.245,我們這裡就將電腦的IP設定為192.168.28.221。我這裡是WIN7 64bit系統。

(1)右擊桌面上的“網路”圖示,選擇屬性。

(2)彈出的介面中選項“本地連線”

(3)選擇“屬性(P)”

(4)雙擊“Internet協議版本4(TCP/Ipv4)”選項。

(5)配置IP地址、子網掩碼和預設閘道器,DNS無需配置,記得點選確定

(6)點選了“確定”按鈕後,退回到之前的介面,這裡的“確定”按鈕不要忘了點選:

11.4.5 第3步,測試ping是否成功

下載例程到開發板,然後ping 192.168.28.245,檢視是否連線上。

(1)WIN+R組合鍵開啟“執行”視窗,輸入cmd。

(2)輸入ping 192.168.28.245後,回車,也是可以的。

收發相同,沒有資料丟失,說明ping命令也是成功的。

11.4.6 第5步,網路除錯助手建立UDP伺服器

  • 開啟除錯助手,點選左上角建立伺服器:

  • 彈出如下介面,指定IP設定為192.168.28.245,一定要跟第2步設定的板子端IP地址一致,埠號1000,最後點選確定:

  • 建立後的介面效果如下:

11.4.7 第6步,連線板子端的UDP Socket

點選連線UDP Socket:

正常連線後效果:

11.4.8 第5步,UDP迴環測試

板子和網路除錯助手建立連線後就可以相互收發資料了。

板子端接收到字元做了個簡單的展示(波特率115200,資料位8,奇偶校驗位無,停止位1):

11.5 實驗例程

配套例子:

V6-2404_ThreadX NetXDUO UDP

實驗目的:

  1. 學習ThreadX NetXDUO UDP實現

實驗內容:

  1. 共建立瞭如下幾個任務,通過按下按鍵K1可以通過串列埠列印任務堆疊使用情況

======================================================

OS CPU Usage = 1.31%

=======================================================

任務優先順序 任務棧大小 當前使用棧 最大棧使用 任務名

Prio StackSize CurStack MaxStack Taskname

2 4092 303 459 App Task Start

30 1020 303 303 App Task STAT

31 1020 87 71 App Task IDLE

5 4092 311 551 App Msp Pro

7 4092 303 719 App Task UserIF

6 4092 255 359 App NETX Pro

3 4092 415 535 NetX IP Instance 0

0 1020 191 235 System Timer Thread

串列埠軟體可以使用SecureCRT或者H7-TOOL RTT檢視列印資訊。

App Task Start任務 :啟動任務,這裡用作BSP驅動包處理。

App Task MspPro任務 :訊息處理。

App Task UserIF任務 :按鍵訊息處理。

App Task COM任務 :這裡用作LED閃爍。

System Timer Thread任務:系統定時器任務

操作說明:

  1. 由於程式使用了DWT時鐘週期計數器,程式下載後,請將板子重新上電使用,防止DWT時鐘週期計數器沒有正常復位。
  2. NetX網路協議棧操作:

(1) 預設IP地址192.168.28.245,在demo_dm9162_netx.c開頭定義,使用者可根據需要修改。

(2) 可以在電腦端用網路除錯軟體建立TCP伺服器,埠號1001。

(3) 實現了一個簡單的迴環通訊,使用者使用上位機發送的資料,然後板子返回另外的資料。

串列埠列印資訊方式(AC5,AC6和IAR):

波特率 115200,資料位 8,奇偶校驗位無,停止位 1

11.6 總結

本章節就為大家講解這麼多,希望大家多做測試,爭取可以熟練掌握這些API函式的使用。

微信公眾號:armfly_com 安富萊論壇:www.armbbs.cn 安富萊淘寶:https://armfly.taobao.com