我是卓波,很高兴你来看我的博客。
系列文章:
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功能,能正常连接并收发数据,撒花。