单片机IWIP SOCKET UDP实验

单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31

HSE 为8MHZ
HSI为16MHZ

主函数

int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ usmart_dev.init(84); /* 初始化USMART */ led_init(); /* 初始化LED */ lcd_init(); /* 初始化LCD */ key_init(); /* 初始化按键 */ my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */ my_mem_init(SRAMCCM); /* 初始化内部SRAMCCM内存池 */ freertos_demo(); /* 创建lwIP的任务函数 */ }
void freertos_demo(void) { /* start_task任务 */ xTaskCreate((TaskFunction_t )start_task, (const char * )"start_task", (uint16_t )START_STK_SIZE, (void * )NULL, (UBaseType_t )START_TASK_PRIO, (TaskHandle_t * )&StartTask_Handler); vTaskStartScheduler(); /* 开启任务调度 */ }
void start_task(void *pvParameters) { pvParameters = pvParameters; g_lwipdev.lwip_display_fn = lwip_test_ui; lwip_test_ui(1); /* 加载后前部分UI */ while (lwip_comm_init() != 0) { lcd_show_string(30, 110, 200, 16, 16, "lwIP Init failed!!", RED); delay_ms(500); lcd_fill(30, 50, 200 + 30, 50 + 16, WHITE); lcd_show_string(30, 110, 200, 16, 16, "Retrying... ", RED); delay_ms(500); LED1_TOGGLE(); } while (!ethernet_read_phy(PHY_SR)) /* 检查MCU与PHY芯片是否通信成功 */ { printf("MCU与PHY芯片通信失败,请检查电路或者源码!!!!\r\n"); } while ((g_lwipdev.dhcpstatus != 2)&&(g_lwipdev.dhcpstatus != 0XFF)) /* 等待DHCP获取成功/超时溢出 */ { vTaskDelay(5); } taskENTER_CRITICAL(); /* 进入临界区 */ g_display_queue = xQueueCreate(DISPLAYMSG_Q_NUM,200); /* 创建消息Message_Queue,队列项长度是200长度 */ /* 创建lwIP任务 */ xTaskCreate((TaskFunction_t )lwip_demo_task, (const char* )"lwip_demo_task", (uint16_t )LWIP_DMEO_STK_SIZE, (void* )NULL, (UBaseType_t )LWIP_DMEO_TASK_PRIO, (TaskHandle_t* )&LWIP_Task_Handler); /* key任务 */ xTaskCreate((TaskFunction_t )key_task, (const char * )"key_task", (uint16_t )KEY_STK_SIZE, (void * )NULL, (UBaseType_t )KEY_TASK_PRIO, (TaskHandle_t * )&KEYTask_Handler); /* LED测试任务 */ xTaskCreate((TaskFunction_t )led_task, (const char* )"led_task", (uint16_t )LED_STK_SIZE, (void* )NULL, (UBaseType_t )LED_TASK_PRIO, (TaskHandle_t* )&LEDTask_Handler); /* 显示任务 */ xTaskCreate((TaskFunction_t )display_task, (const char* )"display_task", (uint16_t )DISPLAY_STK_SIZE, (void* )NULL, (UBaseType_t )DISPLAY_TASK_PRIO, (TaskHandle_t* )&DISPLAYTask_Handler); vTaskDelete(StartTask_Handler); /* 删除开始任务 */ taskEXIT_CRITICAL(); /* 退出临界区 */ }
void lwip_demo_task(void *pvParameters) { pvParameters = pvParameters; lwip_demo(); /* lwip测试代码 */ while (1) { vTaskDelay(5); } }
void lwip_demo(void) { BaseType_t lwip_err; char *tbuf; lwip_data_send(); /* 创建发送数据线程 */ memset(&g_local_info, 0, sizeof(struct sockaddr_in)); /* 将服务器地址清空 */ g_local_info.sin_len = sizeof(g_local_info); g_local_info.sin_family = AF_INET; /* IPv4地址 */ g_local_info.sin_port = htons(LWIP_DEMO_PORT); /* 设置端口号 */ g_local_info.sin_addr.s_addr = htons(INADDR_ANY); /* 设置本地IP地址 */ g_sock_fd = socket(AF_INET, SOCK_DGRAM, 0); /* 建立一个新的socket连接 */ tbuf = mymalloc(SRAMIN, 200); /* 申请内存 */ sprintf((char *)tbuf, "Port:%d", LWIP_DEMO_PORT); /* 客户端端口号 */ lcd_show_string(5, 150, 200, 16, 16, tbuf, BLUE); /* 建立绑定 */ bind(g_sock_fd, (struct sockaddr *)&g_local_info, sizeof(struct sockaddr_in)); while (1) { memset(g_lwip_demo_recvbuf, 0, sizeof(g_lwip_demo_recvbuf)); recv(g_sock_fd, (void *)g_lwip_demo_recvbuf, sizeof(g_lwip_demo_recvbuf), 0); lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0); if (lwip_err == errQUEUE_FULL) { printf("队列Key_Queue已满,数据发送失败!\r\n"); } } }

测试结果:

二、广播实验

主函数

int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ usmart_dev.init(84); /* 初始化USMART */ led_init(); /* 初始化LED */ lcd_init(); /* 初始化LCD */ key_init(); /* 初始化按键 */ my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */ my_mem_init(SRAMCCM); /* 初始化内部SRAMCCM内存池 */ freertos_demo(); /* 创建lwIP的任务函数 */ }

demo

void freertos_demo(void) { /* start_task任务 */ xTaskCreate((TaskFunction_t )start_task, (const char * )"start_task", (uint16_t )START_STK_SIZE, (void * )NULL, (UBaseType_t )START_TASK_PRIO, (TaskHandle_t * )&StartTask_Handler); vTaskStartScheduler(); /* 开启任务调度 */ }
void start_task(void *pvParameters) { pvParameters = pvParameters; g_lwipdev.lwip_display_fn = lwip_test_ui; lwip_test_ui(1); /* 加载后前部分UI */ while (lwip_comm_init() != 0) { lcd_show_string(30, 110, 200, 16, 16, "lwIP Init failed!!", RED); delay_ms(500); lcd_fill(30, 50, 200 + 30, 50 + 16, WHITE); lcd_show_string(30, 110, 200, 16, 16, "Retrying... ", RED); delay_ms(500); LED1_TOGGLE(); } while (!ethernet_read_phy(PHY_SR)) /* 检查MCU与PHY芯片是否通信成功 */ { printf("MCU与PHY芯片通信失败,请检查电路或者源码!!!!\r\n"); } while ((g_lwipdev.dhcpstatus != 2) && (g_lwipdev.dhcpstatus != 0XFF)) /* 等待DHCP获取成功/超时溢出 */ { vTaskDelay(5); } taskENTER_CRITICAL(); /* 进入临界区 */ /* 创建lwIP任务 */ xTaskCreate((TaskFunction_t )lwip_demo_task, (const char* )"lwip_demo_task", (uint16_t )LWIP_DMEO_STK_SIZE, (void* )NULL, (UBaseType_t )LWIP_DMEO_TASK_PRIO, (TaskHandle_t* )&LWIP_Task_Handler); /* LED测试任务 */ xTaskCreate((TaskFunction_t )led_task, (const char* )"led_task", (uint16_t )LED_STK_SIZE, (void* )NULL, (UBaseType_t )LED_TASK_PRIO, (TaskHandle_t* )&LEDTask_Handler); vTaskDelete(StartTask_Handler); /* 删除开始任务 */ taskEXIT_CRITICAL(); /* 退出临界区 */ }
void lwip_demo_task(void *pvParameters) { pvParameters = pvParameters; lwip_demo(); /* lwip测试代码 */ while (1) { vTaskDelay(5); } }
/* UDP广播测试 */ void lwip_demo(void) { struct link_socjet_info *socket_info; socket_info = mem_malloc(sizeof(struct link_socjet_info)); socket_info->optval = 1; /* 创建socket UDP通信 */ socket_info->sfd = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(socket_info->sfd, SOL_SOCKET, SO_BROADCAST, &socket_info->optval, sizeof(socket_info->optval)); socket_info->client_addr.sin_family = AF_INET; socket_info->client_addr.sin_port = htons(9090); socket_info->client_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); socket_info->client_addr_len = sizeof(struct sockaddr_in); /* 设置接收和发送缓冲区 */ socket_info->recv.buf = g_lwip_demo_recvbuf; socket_info->recv.size = sizeof(g_lwip_demo_recvbuf); socket_info->send.buf = g_lwip_demo_sendbuf; socket_info->send.size = sizeof(g_lwip_demo_sendbuf); sys_thread_new("lwip_send_thread", lwip_recv_thread, (void *)socket_info, 512, LWIP_SEND_THREAD_PRIO ); while (1) { /* 发送广播数据 */ sendto(socket_info->sfd, socket_info->send.buf, socket_info->send.size, 0, (struct sockaddr *)&socket_info->client_addr, socket_info->client_addr_len); vTaskDelay(1000); } }

测试结果:

void freertos_demo(void) { /* start_task任务 */ xTaskCreate((TaskFunction_t )start_task, (const char * )"start_task", (uint16_t )START_STK_SIZE, (void * )NULL, (UBaseType_t )START_TASK_PRIO, (TaskHandle_t * )&StartTask_Handler); vTaskStartScheduler(); /* 开启任务调度 */ }

三、组播实验

int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ usmart_dev.init(84); /* 初始化USMART */ led_init(); /* 初始化LED */ lcd_init(); /* 初始化LCD */ key_init(); /* 初始化按键 */ my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */ my_mem_init(SRAMCCM); /* 初始化内部SRAMCCM内存池 */ freertos_demo(); /* 创建lwIP的任务函数 */ }
void start_task(void *pvParameters) { pvParameters = pvParameters; g_lwipdev.lwip_display_fn = lwip_test_ui; lwip_test_ui(1); /* 加载后前部分UI */ while (lwip_comm_init() != 0) { lcd_show_string(30, 110, 200, 16, 16, "lwIP Init failed!!", RED); delay_ms(500); lcd_fill(30, 50, 200 + 30, 50 + 16, WHITE); lcd_show_string(30, 110, 200, 16, 16, "Retrying... ", RED); delay_ms(500); LED1_TOGGLE(); } while (!ethernet_read_phy(PHY_SR)) /* 检查MCU与PHY芯片是否通信成功 */ { printf("MCU与PHY芯片通信失败,请检查电路或者源码!!!!\r\n"); } while ((g_lwipdev.dhcpstatus != 2) && (g_lwipdev.dhcpstatus != 0XFF)) /* 等待DHCP获取成功/超时溢出 */ { vTaskDelay(5); } taskENTER_CRITICAL(); /* 进入临界区 */ /* 创建lwIP任务 */ xTaskCreate((TaskFunction_t )lwip_demo_task, (const char* )"lwip_demo_task", (uint16_t )LWIP_DMEO_STK_SIZE, (void* )NULL, (UBaseType_t )LWIP_DMEO_TASK_PRIO, (TaskHandle_t* )&LWIP_Task_Handler); /* LED测试任务 */ xTaskCreate((TaskFunction_t )led_task, (const char* )"led_task", (uint16_t )LED_STK_SIZE, (void* )NULL, (UBaseType_t )LED_TASK_PRIO, (TaskHandle_t* )&LEDTask_Handler); vTaskDelete(StartTask_Handler); /* 删除开始任务 */ taskEXIT_CRITICAL(); /* 退出临界区 */ }
void lwip_demo_task(void *pvParameters) { pvParameters = pvParameters; lwip_demo(); /* lwip测试代码 */ while (1) { vTaskDelay(5); } }
void lwip_demo(void) { struct link_socjet_info *socket_info; struct ip_mreq_t *mreq_info; socket_info = mem_malloc(sizeof(struct link_socjet_info)); mreq_info = mem_malloc(sizeof(struct ip_mreq_t)); socket_info->sfd = socket(AF_INET, SOCK_DGRAM, 0); if (socket_info->sfd < 0) { printf("socket failed!\n"); } socket_info->client_addr.sin_family = AF_INET; socket_info->client_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 待与 socket 绑定的本地网络接口 IP */ socket_info->client_addr.sin_port = htons(9999); /* 待与 socket 绑定的本地端口号 */ socket_info->client_addr_len = sizeof(socket_info->client_addr); /* 设置接收和发送缓冲区 */ socket_info->recv.buf = g_lwip_demo_recvbuf; socket_info->recv.size = sizeof(g_lwip_demo_recvbuf); socket_info->send.buf = g_lwip_demo_sendbuf; socket_info->send.size = sizeof(g_lwip_demo_sendbuf); /* 将 Socket 与本地某网络接口绑定 */ int ret = bind(socket_info->sfd, (struct sockaddr*)&socket_info->client_addr, socket_info->client_addr_len); if (ret < 0) { printf(" bind error!\n "); } mreq_info->mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP); /* 多播组 IP 地址设置 */ mreq_info->mreq.imr_interface.s_addr = htonl(INADDR_ANY); /* 待加入多播组的 IP 地址 */ mreq_info->mreq_len = sizeof(struct ip_mreq); /* 添加多播组成员(该语句之前,socket 只与 某单播IP地址相关联 执行该语句后 将与多播地址相关联) */ ret = setsockopt(socket_info->sfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq_info->mreq,mreq_info->mreq_len); if (ret < 0) { printf("setsockopt failed !"); } else { printf("setsockopt success\n"); } int length = 0; struct sockaddr_in sender; int sender_len = sizeof(sender); sys_thread_new("lwip_send_thread", lwip_send_thread, (void *)socket_info, 512, LWIP_SEND_THREAD_PRIO ); while(1) { length = recvfrom(socket_info->sfd,socket_info->recv.buf,socket_info->recv.size,0,(struct sockaddr*)&sender,(socklen_t *)&sender_len); socket_info->recv.buf[length]='\0'; printf("%s %d : %s\n", inet_ntoa(sender.sin_addr), ntohs(sender.sin_port), socket_info->recv.buf); vTaskDelay(10); } }

测试结果: