STM32F407以太网服务器配置及热拔插详解
MCU芯片:STM32F407ZGT6
软件:keil5+cubemx6.11(需要6.11及以上版本)+freertos
PHY芯片:LAN8742
协议:tcp/ip
连接方式:soket
功能:单片机板子做服务器实现以太网数据回显+热拔插
一,硬件电路:
二,软件:
CUBMX配置:
1.先配置好freertos系统,栈大小选择为1024字,优先级为osPriorityNormal
2.配置ETH:
3.配置lwip协议:选择phy芯片
设置为静态ip地址,关闭UDP(我是直连电脑的所以网关地址就随便设置了)
4.keil5程序:在freertos.c中void StartDefaultTask(void *argument)中添加:
void StartDefaultTask(void *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
int sock = -1, connected;
struct sockaddr_in server_addr, client_addr;
socklen_t sin_size;
printf("/--------------------ETHInit Begin--------------------/\r\n");
printf("LOCAL_PORT:%d\r\n", LOCAL_PORT);
printf("IP_ADDRESS:%d.%d.%d.%d\r\n", IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
printf("NETMASK_ADDRESS:%d.%d.%d.%d\r\n", NETMASK_ADDRESS[0], NETMASK_ADDRESS[1], NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
printf("GATEWAY_ADDRESS:%d.%d.%d.%d\r\n", GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);
printf("ETH Linkl Success\r\n");
printf("/--------------------ETHInit END--------------------/\r\n");
if ((char *)pvPortMalloc(1536) == NULL)
{
printf("No memory\n");
goto __exit;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
printf("Socket error\n");
goto __exit;
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(LOCAL_PORT);
memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
printf("Unable to bind\n");
goto __exit;
}
if (listen(sock, 5) == -1)
{
printf("Listen error\n");
goto __exit;
}
while (1)
{
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
printf("new client connected from (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
{
int flag = 1;
setsockopt(connected,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *)&flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
}
while (1)
{
if (recv(connected, eth_resbuff, 1024, 0) <= 0)break;
if (write(connected, eth_resbuff, strlen((char *)eth_resbuff)) < 0)break;
}
if (connected >= 0)
closesocket(connected);
connected = -1;
}
__exit:
if (sock >= 0)
closesocket(sock);
free(eth_resbuff);
}
/* USER CODE END StartDefaultTask */
}
电脑以太网设置为静态ip要和单片机在同一个网段,我设置为(192.168.2.8)
ping一下(如图所示为成功):
查看串口是否正常打印和连接以太网(如图所示为成功):
添加热拔插功能:在cubemx中打开链路检测回调函数
在keil程序中找到lwip.c中的void MX_LWIP_Init(void)
将创建的任务优先级改为osPriorityNormal,再在static void ethernet_link_status_updated(struct netif *netif)添加相应的拔开与插入提示
查看串口是否有拔插提示且拔插后是否仍可以保持以太网连接(如图所示为成功)
作者:大能人499