阅读量:0
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)添加相应的拔开与插入提示
查看串口是否有拔插提示且拔插后是否仍可以保持以太网连接(如图所示为成功)