我是卓波,很高興你來看我的博客。
系列文章:
stm32+lwip(一):使用STM32CubeMX生成項目
ST官方有lwip的例程,下載地址如下:
本文例子參考ST官方給出的例程。
一、准備
ST例程文檔關於lwip的介紹如下:
由此可以看到LWIP有三種API,在本文中,使用Raw API。
本文用到的TCP Raw API如下:
二、tcp client
1 /** 2 ***************************************************************************** 3 * @file tcp_client.c 4 * @author Zorb 5 * @version V1.0.0 6 * @date 2018-09-04 7 * @brief tcp客戶端的實現 8 ***************************************************************************** 9 * @history 10 * 11 * 1. Date:2018-09-04 12 * Author:Zorb 13 * Modification:建立文件 14 * 15 ***************************************************************************** 16 */ 17 18 #include "stm32f4xx_hal.h" 19 #include "lwip.h" 20 #include "tcp.h" 21 #include "string.h" 22 23 /* 定義端口號 */ 24 #define TCP_REMOTE_PORT 8881 /* 遠端端口 */ 25 #define TCP_LOCAL_PORT 8880 /* 本地端口 */ 26 27 /****************************************************************************** 28 * 描述 : 數據接收回調函數 29 * 參數 : - 30 * 返回 : - 31 ******************************************************************************/ 32 static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, 33 struct pbuf *p, err_t err) 34 { 35 uint32_t i; 36 37 /* 數據回傳 */ 38 //tcp_write(tpcb, p->payload, p->len, 1); 39 40 if (p != NULL) 41 { 42 struct pbuf *ptmp = p; 43 44 /* 打印接收到的數據 */ 45 printf("get msg from %d:%d:%d:%d port:%d:\r\n", 46 *((uint8_t *)&tpcb->remote_ip.addr), 47 *((uint8_t *)&tpcb->remote_ip.addr + 1), 48 *((uint8_t *)&tpcb->remote_ip.addr + 2), 49 *((uint8_t *)&tpcb->remote_ip.addr + 3), 50 tpcb->remote_port); 51 52 while(ptmp != NULL) 53 { 54 for (i = 0; i < p->len; i++) 55 { 56 printf("%c", *((char *)p->payload + i)); 57 } 58 59 ptmp = p->next; 60 } 61 62 printf("\r\n"); 63 64 tcp_recved(tpcb, p->tot_len); 65 66 /* 釋放緩沖區數據 */ 67 pbuf_free(p); 68 } 69 else if (err == ERR_OK) 70 { 71 printf("tcp client closed\r\n"); 72 73 tcp_recved(tpcb, p->tot_len); 74 75 return tcp_close(tpcb); 76 } 77 78 return ERR_OK; 79 } 80 81 /****************************************************************************** 82 * 描述 : 連接服務器回調函數 83 * 參數 : - 84 * 返回 : - 85 ******************************************************************************/ 86 static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) 87 { 88 printf("tcp client connected\r\n"); 89 90 tcp_write(tpcb, "tcp client connected", strlen("tcp client connected"), 0); 91 92 /* 注冊接收回調函數 */ 93 tcp_recv(tpcb, tcp_client_recv); 94 95 return ERR_OK; 96 } 97 98 /****************************************************************************** 99 * 描述 : 創建tcp客戶端 100 * 參數 : 無 101 * 返回 : 無 102 ******************************************************************************/ 103 void tcp_client_init(void) 104 { 105 struct tcp_pcb *tpcb; 106 ip_addr_t serverIp; 107 108 /* 服務器IP */ 109 IP4_ADDR(&serverIp, 192, 168, 2, 194); 110 111 /* 創建tcp控制塊 */ 112 tpcb = tcp_new(); 113 114 if (tpcb != NULL) 115 { 116 err_t err; 117 118 /* 綁定本地端號和IP地址 */ 119 err = tcp_bind(tpcb, IP_ADDR_ANY, TCP_LOCAL_PORT); 120 121 if (err == ERR_OK) 122 { 123 /* 連接服務器 */ 124 tcp_connect(tpcb, &serverIp, TCP_REMOTE_PORT, tcp_client_connected); 125 } 126 else 127 { 128 memp_free(MEMP_TCP_PCB, tpcb); 129 130 printf("can not bind pcb\r\n"); 131 } 132 } 133 } 134 135 /******************************** END OF FILE ********************************/
本例用到的上位機IP為192.168.2.194,開放端口為8881
STM32的IP為192.168.2.8,開放端口為8880
先將網絡調試助手的TCP Server打開,然后給STM32上電。
網絡調試助手將會收到如下信息:
然后點擊網絡調試助手的發送,STM32調試串口輸出以下信息:
get msg from 192:168:2:194 port:8881: hello zorb
三、tcp server
1 /** 2 ***************************************************************************** 3 * @file tcp_server.c 4 * @author Zorb 5 * @version V1.0.0 6 * @date 2018-09-04 7 * @brief tcp服務端的實現 8 ***************************************************************************** 9 * @history 10 * 11 * 1. Date:2018-09-04 12 * Author:Zorb 13 * Modification:建立文件 14 * 15 ***************************************************************************** 16 */ 17 18 #include "stm32f4xx_hal.h" 19 #include "lwip.h" 20 #include "tcp.h" 21 #include "string.h" 22 23 /* 定義端口號 */ 24 #define TCP_REMOTE_PORT 8881 /* 遠端端口 */ 25 #define TCP_LOCAL_PORT 8880 /* 本地端口 */ 26 27 /****************************************************************************** 28 * 描述 : 接收回調函數 29 * 參數 : - 30 * 返回 : - 31 ******************************************************************************/ 32 static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, 33 struct pbuf *p, err_t err) 34 { 35 uint32_t i; 36 37 /* 數據回傳 */ 38 //tcp_write(tpcb, p->payload, p->len, 1); 39 40 if (p != NULL) 41 { 42 struct pbuf *ptmp = p; 43 44 /* 打印接收到的數據 */ 45 printf("get msg from %d:%d:%d:%d port:%d:\r\n", 46 *((uint8_t *)&tpcb->remote_ip.addr), 47 *((uint8_t *)&tpcb->remote_ip.addr + 1), 48 *((uint8_t *)&tpcb->remote_ip.addr + 2), 49 *((uint8_t *)&tpcb->remote_ip.addr + 3), 50 tpcb->remote_port); 51 52 while(ptmp != NULL) 53 { 54 for (i = 0; i < p->len; i++) 55 { 56 printf("%c", *((char *)p->payload + i)); 57 } 58 59 ptmp = p->next; 60 } 61 62 printf("\r\n"); 63 64 tcp_recved(tpcb, p->tot_len); 65 66 /* 釋放緩沖區數據 */ 67 pbuf_free(p); 68 } 69 else if (err == ERR_OK) 70 { 71 printf("tcp client closed\r\n"); 72 73 tcp_recved(tpcb, p->tot_len); 74 75 return tcp_close(tpcb); 76 } 77 78 return ERR_OK; 79 } 80 81 /****************************************************************************** 82 * 描述 : 客戶端接入回調函數 83 * 參數 : - 84 * 返回 : - 85 ******************************************************************************/ 86 static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err) 87 { 88 printf("tcp client connected\r\n"); 89 90 printf("ip %d:%d:%d:%d port:%d\r\n", 91 *((uint8_t *)&newpcb->remote_ip.addr), 92 *((uint8_t *)&newpcb->remote_ip.addr + 1), 93 *((uint8_t *)&newpcb->remote_ip.addr + 2), 94 *((uint8_t *)&newpcb->remote_ip.addr + 3), 95 newpcb->remote_port); 96 97 tcp_write(newpcb, "tcp client connected", strlen("tcp client connected"), 0); 98 99 /* 注冊接收回調函數 */ 100 tcp_recv(newpcb, tcp_server_recv); 101 102 return ERR_OK; 103 } 104 105 /****************************************************************************** 106 * 描述 : 創建tcp服務器 107 * 參數 : 無 108 * 返回 : 無 109 ******************************************************************************/ 110 void tcp_server_init(void) 111 { 112 struct tcp_pcb *tpcb; 113 114 /* 創建tcp控制塊 */ 115 tpcb = tcp_new(); 116 117 if (tpcb != NULL) 118 { 119 err_t err; 120 121 /* 綁定端口接收,接收對象為所有ip地址 */ 122 err = tcp_bind(tpcb, IP_ADDR_ANY, TCP_LOCAL_PORT); 123 124 if (err == ERR_OK) 125 { 126 /* 監聽 */ 127 tpcb = tcp_listen(tpcb); 128 129 /* 注冊接入回調函數 */ 130 tcp_accept(tpcb, tcp_server_accept); 131 132 printf("tcp server listening\r\n"); 133 printf("tcp server ip:%d:%d:%d:%d prot:%d\r\n", 134 *((uint8_t *)&ipaddr.addr), 135 *((uint8_t *)&ipaddr.addr + 1), 136 *((uint8_t *)&ipaddr.addr + 2), 137 *((uint8_t *)&ipaddr.addr + 3), 138 tpcb->local_port); 139 } 140 else 141 { 142 memp_free(MEMP_TCP_PCB, tpcb); 143 144 printf("can not bind pcb\r\n"); 145 } 146 147 } 148 } 149 150 /******************************** END OF FILE ********************************/
本例用到的上位機IP為192.168.2.194,開放端口為8881
STM32的IP為192.168.2.8,開放端口為8880
先將STM32上電,STM32調試串口輸出以下信息:
tcp server listening tcp server ip:192:168:2:8 prot:8880
然后通過網絡調試助手連接到STM32的tcp服務器:
STM32調試串口輸出以下信息:
tcp client connected ip 192:168:2:194 port:53538
在網絡調試助手發送信息”hello zorb”,STM32調試串口輸出以下信息:
get msg from 192:168:2:194 port:53538: hello zorb
四、最后
本文測試了lwip的tcp功能,能正常連接並收發數據,撒花。
github:https://github.com/54zorb/stm32-lwip
版權所有,轉載請打賞喲
如果你喜歡我的文章,可以通過微信掃一掃給我打賞喲