使用STM32F407ZGT6驱动DP83848,使用STM32CubeMX 6.11.0版本创建工程,MDK版本5.27,STM32F407的固件库是STM32Cube FW_F4 V1.28.0。
创建的工程中使用了中间件FreeRTOS、LWIP;ETH接口是MII,DP83848外部有独立的25M晶振。
在LWIP中选择了DP83848_PHY,没启用DHCP,给板子设定了固定的IP。其他基本都是默认。
创建了1个默认的任务、1个TCP任务;TCP任务开启2048的堆栈空间,如下所示。
打算使用TCP工具软件作为客户端,板子作为服务器端。由TCP工具软件连接板子。
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 256);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of tcpserverTask */
osThreadDef(tcpserverTask, tcpserverTaskFunc, osPriorityHigh, 0, 2048);
tcpserverTaskHandle = osThreadCreate(osThread(tcpserverTask), NULL);
void tcpserverTaskFunc(void const * argument)
{
/* USER CODE BEGIN tcpserverTaskFunc */
MX_LWIP_Init();
/* Infinite loop */
for(;;)
{
if (TCP_STATUS_UPDATE == 0)
{
TCP_STATUS_UPDATE = 1;
sys_thread_new("tcp_echoserver_init", tcp_echoserver_init, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO+10);
}
osDelay(30);
}
/* USER CODE END tcpserverTaskFunc */
}
下面是tcp_echoserver_init的代码:
void tcp_echoserver_init(void *p_arg)
{
struct sockaddr_in server_addr; //服务器地址
struct sockaddr_in conn_addr; //连接地址
int sock_fd ; //服务器的 socked
int sock_conn; // 请求的 socked
socklen_t addr_len; // 地址长度
int err;
int length;
int num;
sock_fd = socket(AF_INET, SOCK_STREAM, 0); //建立一个新的socket连接
if (sock_fd < 0)
{
printf("tcp socket error\r\n") ;
TCP_STATUS_UPDATE = 0;
return;
}
else printf("tcp socket ok\r\n") ;
memset(&server_addr, 0, sizeof(server_addr)); //将服务器地址清空
server_addr.sin_family = AF_INET; //地址家族
server_addr.sin_addr.s_addr =inet_addr("192.168.1.252"); //注意转化为网络字节序
server_addr.sin_port = htons(SERVER_PORT); //使用SERVER_PORT指定为程序头设定的端口号
memset(server_addr.sin_zero,0,sizeof(server_addr.sin_zero));
err = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); //建立绑定
if (err < 0) //如果绑定失败则关闭套接字
{
closesocket(sock_fd); //关闭套接字
printf("bind error\r\n");
TCP_STATUS_UPDATE = 0;
return;
}
else printf("tcp socket bind ok\r\n") ;
err = listen(sock_fd, 1); //监听连接请求
if (err < 0) //如果监听失败则关闭套接字
{
closesocket(sock_fd); //关闭套接字
printf("listen error\r\n");
TCP_STATUS_UPDATE = 0;
return;
}
else printf("tcp socket listen ok\r\n") ;
addr_len = sizeof(struct sockaddr_in); //将链接地址赋值给addr_len
sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len); //对监听到的请求进行连接,状态赋值给sock_conn
if(sock_conn<0) //状态小于0代表连接故障,此时关闭套接字
{
closesocket(sock_fd);
printf("sock_conn error\r\n");
TCP_STATUS_UPDATE = 0;
return;
}
else send(sock_conn, "connect success!\n\r", 20, 0); //连接成功则发送“connect success!”给客户端
while (1)
{
memset(data_buffer, 0, sizeof(data_buffer)); //清空接收Buff
length = recv(sock_conn, (unsigned int *)data_buffer, 100, 0); //将收到的数据放到接收Buff
for(num=0;num<100;num++) //接收Buff的数据转移到数据处理Buff,防止之后数据混乱
{
tcp_server_recvbuf[num]=data_buffer[num];
}
if (length > 0)
{
send(sock_conn, "\ntcp response: ",strlen("\ntcp response: "), 1); //回复
send(sock_conn, tcp_server_recvbuf,length, 1); //回复
send(sock_conn, "\r\n", strlen("\r\n"), 1); //回复
}
else
{
if (errno != EINTR) //(length<=0)&&(errno!=EINTR) means socket broke
{
printf("tcp link broke\r\n");
err = listen(sock_fd, 1); //监听连接请求
if (err < 0) //如果监听失败则关闭套接字
{
closesocket(sock_fd); //关闭套接字
printf("listen error\r\n");
TCP_STATUS_UPDATE = 0;
return;
}
else printf("tcp socket listen ok\r\n") ;
addr_len = sizeof(struct sockaddr_in); //将链接地址赋值给addr_len
sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len); //对监听到的请求进行连接,状态赋值给sock_conn
if(sock_conn<0) //状态小于0代表连接故障,此时关闭套接字
{
closesocket(sock_fd);
printf("sock_conn error\r\n");
TCP_STATUS_UPDATE = 0;
return;
}
else send(sock_conn, "connect success!\n\r", 20, 0); //连接成功则发送“connect success!”给客户端
}
}
osDelay(1);
}
}
现在测试中的问题是:
(1)MX_LWIP_Init()初始化放在main入口函数中,初始化过不去。放在TCP的tcpserverTaskFunc任务中,能初始化过去。这是为什么。我把其他点灯的初始化放在main入口函数,或者放在点灯任务中是可以的。
(2)连接不上板子。提示SOCKET连接失败,错误代码10061。sys_thread_new("tcp_echoserver_init", tcp_echoserver_init, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO+10);,创建的TCP进程,不进去执行。
有用过的朋友请指点下。
12-31上午,添加了下打印信息,确定是sys_thread_new("tcp_echoserver_init", tcp_echoserver_init, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO+10)创建线程失败。
DEFAULT_THREAD_STACKSIZE默认大小是1024,DEFAULT_THREAD_PRIO优先级是3。不知道为什么会创建失败。