单片机IWIP NETCONN实验
单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
一、UDP实验
主函数
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) { err_t err; static struct netconn *udpconn; static struct netbuf *recvbuf; static struct netbuf *sentbuf; ip_addr_t destipaddr; uint32_t data_len = 0; struct pbuf *q; BaseType_t lwip_err; /* 第一步:创建udp控制块 */ udpconn = netconn_new(NETCONN_UDP); /* 定义接收超时时间 */ udpconn->recv_timeout = 10; if (udpconn != NULL) /* 判断创建控制块释放成功 */ { /* 第二步:绑定控制块、本地IP和端口 */ err = netconn_bind(udpconn, IP_ADDR_ANY, LWIP_DEMO_PORT); /*构造目的IP地址 */ IP4_ADDR(&destipaddr, DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3); /* 第三步:连接或者建立对话框 */ netconn_connect(udpconn, &destipaddr, LWIP_DEMO_PORT); /* 连接到远端主机 */ if (err == ERR_OK) /* 绑定完成 */ { while (1) { /* 第四步:如果指定的按键按下时,会发送信息 */ if ((g_lwip_send_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) { sentbuf = netbuf_new(); netbuf_alloc(sentbuf, strlen((char *)g_lwip_demo_sendbuf)); memcpy(sentbuf->p->payload, (void *)g_lwip_demo_sendbuf, strlen((char *)g_lwip_demo_sendbuf)); err = netconn_send(udpconn, sentbuf); /* 将netbuf中的数据发送出去 */ if (err != ERR_OK) { printf("发送失败\r\n"); netbuf_delete(sentbuf); /* 删除buf */ } g_lwip_send_flag &= ~LWIP_SEND_DATA; /* 清除数据发送标志 */ netbuf_delete(sentbuf); /* 删除buf */ } /* 第五步:接收数据 */ netconn_recv(udpconn, &recvbuf); if (recvbuf != NULL) /* 接收到数据 */ { memset(g_lwip_demo_recvbuf, 0, LWIP_DEMO_RX_BUFSIZE); /* 数据接收缓冲区清零 */ for (q = recvbuf->p; q != NULL; q = q->next) /* 遍历完整个pbuf链表 */ { /* 判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于 */ /* 的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 */ if (q->len > (LWIP_DEMO_RX_BUFSIZE - data_len)) memcpy(g_lwip_demo_recvbuf + data_len, q->payload, (LWIP_DEMO_RX_BUFSIZE - data_len)); /* 拷贝数据 */ else memcpy(g_lwip_demo_recvbuf + data_len, q->payload, q->len); data_len += q->len; if (data_len > LWIP_DEMO_RX_BUFSIZE) break; /* 超出TCP客户端接收数组,跳出 */ } data_len = 0; /* 复制完成后data_len要清零 */ lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0); if (lwip_err == errQUEUE_FULL) { printf("队列Key_Queue已满,数据发送失败!\r\n"); } netbuf_delete(recvbuf); /* 删除buf */ } else vTaskDelay(5); /* 延时5ms */ vTaskDelay(10); } } else printf("UDP绑定失败\r\n"); } else printf("UDP连接创建失败\r\n"); }测试结果:
二、NETCONN TCP客户端实验
主函数
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) { static struct netconn *tcp_clientconn = NULL; /* TCP CLIENT网络连接结构体 */ uint32_t data_len = 0; struct pbuf *q; err_t err,recv_err; ip4_addr_t server_ipaddr,loca_ipaddr; static uint16_t server_port,loca_port; BaseType_t lwip_err; char *tbuf; server_port = LWIP_DEMO_PORT; IP4_ADDR(&server_ipaddr,DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3); /* 构造目的IP地址 */ tbuf = mymalloc(SRAMIN, 200); /* 申请内存 */ sprintf((char *)tbuf, "Port:%d", LWIP_DEMO_PORT); /* 客户端端口号 */ lcd_show_string(5, 150, 200, 16, 16, tbuf, BLUE); while (1) { tcp_clientconn = netconn_new(NETCONN_TCP); /* 创建一个TCP链接 */ err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port); /* 连接服务器 */ if (err != ERR_OK) { printf("接连失败\r\n"); netconn_delete(tcp_clientconn); /* 返回值不等于ERR_OK,删除tcp_clientconn连接 */ } else if (err == ERR_OK) /* 处理新连接的数据 */ { struct netbuf *recvbuf; tcp_clientconn->recv_timeout = 10; netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); /* 获取本地IP主机IP地址和端口号 */ printf("连接上服务器%d.%d.%d.%d,本机端口号为:%d\r\n",DEST_IP_ADDR0,DEST_IP_ADDR1, DEST_IP_ADDR2,DEST_IP_ADDR3,loca_port); lcd_show_string(5, 90, 200, 16, 16, "State:Connection Successful", BLUE); while (1) { if ((g_lwip_send_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) /* 有数据要发送 */ { err = netconn_write(tcp_clientconn ,g_lwip_demo_sendbuf,strlen((char*)g_lwip_demo_sendbuf),NETCONN_COPY); /* 发送tcp_server_sentbuf中的数据 */ if (err != ERR_OK) { printf("发送失败\r\n"); } g_lwip_send_flag &= ~LWIP_SEND_DATA; } if ((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) /* 接收到数据 */ { taskENTER_CRITICAL(); /* 进入临界区 */ memset(g_lwip_demo_recvbuf,0,LWIP_DEMO_RX_BUFSIZE); /* 数据接收缓冲区清零 */ for (q = recvbuf->p;q != NULL;q = q->next) /* 遍历完整个pbuf链表 */ { /* 判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于 */ /* 的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 */ if (q->len > (LWIP_DEMO_RX_BUFSIZE - data_len)) { memcpy(g_lwip_demo_recvbuf + data_len,q->payload,(LWIP_DEMO_RX_BUFSIZE - data_len));/* 拷贝数据 */ } else { memcpy(g_lwip_demo_recvbuf + data_len,q->payload,q->len); } data_len += q->len; if (data_len > LWIP_DEMO_RX_BUFSIZE) { break; /* 超出TCP客户端接收数组,跳出 */ } } taskEXIT_CRITICAL(); /* 退出临界区 */ data_len = 0; /* 复制完成后data_len要清零 */ lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0); if (lwip_err == errQUEUE_FULL) { printf("队列Key_Queue已满,数据发送失败!\r\n"); } netbuf_delete(recvbuf); } else if (recv_err == ERR_CLSD) /* 关闭连接 */ { netconn_close(tcp_clientconn); netconn_delete(tcp_clientconn); printf("服务器%d.%d.%d.%d断开连接\r\n",DEST_IP_ADDR0,DEST_IP_ADDR1, DEST_IP_ADDR2,DEST_IP_ADDR3); lcd_fill(5, 89, lcddev.width,110, WHITE); lcd_show_string(5, 90, 200, 16, 16, "State:Disconnect", BLUE); myfree(SRAMIN, tbuf); break; } } } } }测试结果:
三、NETCONN TCP服务器实验
主函数
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(); /* 进入临界区 */ 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) { static struct netconn *tcp_serverconn = NULL; /* TCP SERVER网络连接结构体 */ uint32_t data_len = 0; struct pbuf *q; err_t err,recv_err; uint8_t remot_addr[4]; struct netconn *newconn; static ip_addr_t ipaddr; static u16_t port; BaseType_t lwip_err; char *tbuf; tbuf = mymalloc(SRAMIN, 200); /* 申请内存 */ sprintf((char *)tbuf, "Port:%d", LWIP_DEMO_PORT); /* 客户端端口号 */ lcd_show_string(5, 150, 200, 16, 16, tbuf, BLUE); /* 第一步:创建一个TCP控制块 */ tcp_serverconn = netconn_new(NETCONN_TCP); /* 创建一个TCP链接 */ /* 第二步:绑定TCP控制块、本地IP地址和端口号 */ netconn_bind(tcp_serverconn,IP_ADDR_ANY,LWIP_DEMO_PORT); /* 绑定端口 8080号端口 */ /* 第三步:监听 */ netconn_listen(tcp_serverconn); /* 进入监听模式 */ tcp_serverconn->recv_timeout = 10; /* 禁止阻塞线程 等待10ms */ while (1) { /* 第四步:接收连接请求 */ err = netconn_accept(tcp_serverconn,&newconn); /* 接收连接请求 */ if (err == ERR_OK) newconn->recv_timeout = 10; if (err == ERR_OK) /* 处理新连接的数据 */ { struct netbuf *recvbuf; netconn_getaddr(newconn,&ipaddr,&port,0); /* 获取远端IP地址和端口号 */ remot_addr[3] = (uint8_t)(ipaddr.addr >> 24); remot_addr[2] = (uint8_t)(ipaddr.addr>> 16); remot_addr[1] = (uint8_t)(ipaddr.addr >> 8); remot_addr[0] = (uint8_t)(ipaddr.addr); printf("主机%d.%d.%d.%d连接上服务器,主机端口号为:%d\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3],port); lcd_show_string(5, 90, 200, 16, 16, "State:Connection Successful", BLUE); while (1) { if ((g_lwip_send_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) /* 有数据要发送 */ { err = netconn_write(newconn ,g_lwip_demo_sendbuf,strlen((char*)g_lwip_demo_sendbuf),NETCONN_COPY); /* 发送g_lwip_demo_sendbuf中的数据 */ if (err != ERR_OK) { printf("发送失败\r\n"); } g_lwip_send_flag &= ~LWIP_SEND_DATA; } if ((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK) /* 接收到数据 */ { taskENTER_CRITICAL(); /* 进入临界区 */ memset(g_lwip_demo_recvbuf,0,LWIP_DEMO_RX_BUFSIZE); /* 数据接收缓冲区清零 */ for (q = recvbuf->p;q != NULL;q = q->next) /* 遍历完整个pbuf链表 */ { /* 判断要拷贝到LWIP_DEMO_RX_BUFSIZE中的数据是否大于LWIP_DEMO_RX_BUFSIZE的剩余空间,如果大于 */ /* 的话就只拷贝LWIP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 */ if (q->len > (LWIP_DEMO_RX_BUFSIZE - data_len)) { memcpy(g_lwip_demo_recvbuf + data_len,q->payload,(LWIP_DEMO_RX_BUFSIZE - data_len));/* 拷贝数据 */ } else { memcpy(g_lwip_demo_recvbuf + data_len,q->payload,q->len); } data_len += q->len; if (data_len > LWIP_DEMO_RX_BUFSIZE) { break; /*超出TCP客户端接收数组,跳出*/ } } taskEXIT_CRITICAL(); /* 退出临界区 */ data_len = 0; /* 复制完成后data_len要清零 */ lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0); if (lwip_err == errQUEUE_FULL) { printf("队列Key_Queue已满,数据发送失败!\r\n"); } netbuf_delete(recvbuf); } else if (recv_err == ERR_CLSD) /* 关闭连接 */ { netconn_close(newconn); netconn_delete(newconn); printf("主机:%d.%d.%d.%d断开与服务器的连接\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3]); lcd_fill(5, 89, lcddev.width,110, WHITE); lcd_show_string(5, 90, 200, 16, 16, "State:Disconnect", BLUE); myfree(SRAMIN, tbuf); break; } } } } }测试结果:
