第9章 STM32 TCP配置和测试
前言
硬件的配置由前面的工程递增,会根据目的修改部分控制代码
由于本人较懒,记录主要是过程,原理性的东西网上一大把,我就不赘述了,由于懒,主要由图片和代码加少量文字组成
源码地址https://gitcode.com/qq_36517072/stm32,第x章为cx文件夹
一、STM32CUBE配置修改
修改默认TASK的栈大小为512,否则由于资源过少,容易卡死在xQueueSemaphoreTake,这里壶中墨水网友给出方法有效

generatecode
二、代码和测试
新建C文件

源码来自参考文章做了一点修改
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip.h"
#include "lwip/api.h"
#include "tcp.h"
#include "main.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void tcp_client_init(void)
{
uint8_t Server_IP[4] = {192,168,0,11};
uint16_t Server_Port = 8087;
struct netconn *conn;
ip_addr_t ipaddr;
err_t err = ERR_OK;
struct netbuf *rx_buff;
void *rx_data;
uint16_t rx_data_len;
char connect_ok[64] = "Successfully connected to Server!\r\n";
// 将数组Server_IP中IP地址转换合并到ipaddr中
IP4_ADDR(&ipaddr, Server_IP[0], Server_IP[1], Server_IP[2], Server_IP[3]);
/* Infinite loop */
for(;;)
{
conn = netconn_new(NETCONN_TCP); // 创建新的连接结构conn
if(conn == NULL)
{
osDelay(1000);
continue;
}
netif_set_link_up(netif_default);
err = netconn_connect(conn, &ipaddr, Server_Port); // 连接服务器
if(err != ERR_OK)
{
osDelay(1000);
netconn_delete(conn); // 删除连接结构体conn
continue;
}
printf("State: %d\r\n", conn->state);
netconn_write(conn, connect_ok, strlen(connect_ok), NETCONN_COPY);
while(netconn_recv(conn, &rx_buff) == ERR_OK) // 从服务器接收数据,LWIP默认阻塞式接收
{
do
{
netbuf_data(rx_buff, &rx_data, &rx_data_len); // 从接收结构体rx_buff中拷贝数据到rx_data
netconn_write(conn, rx_data, rx_data_len, NETCONN_COPY); // 向服务器发送消息
printf("%.*s\r\n",(int)rx_data_len, (const char*)rx_data);
memset(rx_data, 0, rx_data_len);
}
while(netbuf_next(rx_buff) >= 0); // netbuf中还有数据时 调用netbuf_next函数移动ptr指针指向下一个pbuf
netbuf_delete(rx_buff); // 删除接收结构体rx_buff
}
netbuf_delete(rx_buff); // 删除接收结构体rx_buff 只有当服务器关闭或出现其他错误才会运行到这里
netconn_close(conn); // 关闭连接到的服务器
netconn_delete(conn); // 删除连接结构conn
printf("Close connection!\r\n");
osDelay(10);
}
}
在main.h里添加tcp_client_init函数的声明
/* USER CODE BEGIN EFP */
void udp_client_init(void);
void tcp_client_init(void);
/* USER CODE END EFP */
在freertos.c里添加TCP初始化的调用
/* USER CODE BEGIN StartDefaultTask */
shell_init();
//udp_client_init();
tcp_client_init();
/* Infinite loop */
连接好烧录器编译并烧录
打开网络助手软件,设置IP和端口后往板卡发送,能收到回复

总结
主要介绍了STM32 TCP的配置和测试
问题
一开始尝试使用raw来完成tcp客户端的代码,发现在连接服务器时tpcb->state总是等于2,卡在SYN阶段,无法连接上服务器,卡了几天没解决只能另辟蹊径,使用netconn可以,索性就不死磕raw了,如果有能行的欢迎告知我出问题的原因,源码如下
#include "stm32f4xx_hal.h"
#include "lwip.h"
#include "tcp.h"
#include "string.h"
#include "main.h"
/* 定义端口号 */
#define TCP_REMOTE_PORT 8087 /* 远端端口 */
#define TCP_LOCAL_PORT 8086 /* 本地端口 */
static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err)
{
uint32_t i;
/* 数据回传 */
//tcp_write(tpcb, p->payload, p->len, 1);
if (p != NULL)
{
struct pbuf *ptmp = p;
/* 打印接收到的数据 */
printf("get msg from %d:%d:%d:%d port:%d:\r\n",
*((uint8_t *)&tpcb->remote_ip.addr),
*((uint8_t *)&tpcb->remote_ip.addr + 1),
*((uint8_t *)&tpcb->remote_ip.addr + 2),
*((uint8_t *)&tpcb->remote_ip.addr + 3),
tpcb->remote_port);
while(ptmp != NULL)
{
for (i = 0; i < p->len; i++)
{
printf("%c", *((char *)p->payload + i));
}
ptmp = p->next;
}
printf("\r\n");
tcp_recved(tpcb, p->tot_len);
/* 释放缓冲区数据 */
pbuf_free(p);
}
else if (err == ERR_OK)
{
printf("tcp client closed\r\n");
tcp_recved(tpcb, p->tot_len);
return tcp_close(tpcb);
}
return ERR_OK;
}
static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
printf("tcp client connected\r\n");
tcp_write(tpcb, "tcp client connected", strlen("tcp client connected"), 0);
/* 注册接收回调函数 */
tcp_recv(tpcb, tcp_client_recv);
return ERR_OK;
}
void tcp_client_init(void)
{
struct tcp_pcb *tpcb;
ip_addr_t serverIp;
int i,ret;
printf("tcp_client_init: flags=0x%x\r\n", netif_default->flags);
/* 服务器IP */
IP4_ADDR(&serverIp, 192, 168, 0, 11);
/* 创建tcp控制块 */
tpcb = tcp_new();
if (tpcb != NULL)
{
err_t err;
/* 绑定本地端号和IP地址 */
err = tcp_bind(tpcb, IP_ADDR_ANY, TCP_LOCAL_PORT);
tpcb->remote_ip = serverIp;
printf("\r\nremote_ip:%x\r\n",tpcb->remote_ip.addr);
if (err == ERR_OK)
{
/* 连接服务器 */
for(i=0;i<5;i++)
{
printf("tcp_connect: flags=0x%x\r\n", netif_default->flags);
HAL_Delay(1000);
ret = tcp_connect(tpcb, &serverIp, TCP_REMOTE_PORT, tcp_client_connected);
printf("Callback: %p, Expected: %p\r\n", tpcb->connected, (void*)tcp_client_connected);
printf("State: %d\r\n", tpcb->state);
if(ret == ERR_OK)break;
}
}
else
{
memp_free(MEMP_TCP_PCB, tpcb);
printf("can not bind pcb\r\n");
}
}
}

浙公网安备 33010602011771号