【项目目标】
MCXN947创建lwip,实现动态获取IP,并连接http服务器,实现定时向服务器发送数据。
【硬件】
1、FRDM-MCXN947开发板
2、网线
【软件】
1、MCUXpressoIDE
2、网络数据调器
【实现步骤】
1、使用MCUXpressoIDE导入freertos_dhcp工程示例:
2、导入示例后,编译下载到开发板,接上网线,打开串口终端,确定可以动态获取到IP
3、使用网络调试助手创建一个TCPServer 端口为777
【程序编写】
编写远程服务器的IP地址为电192.168.3.231,远程端口为777,当连上服务器后每5秒发送一次数据:
#include "lwip/opt.h" #include "lwip/arch.h" #include "lwip/api.h" #include "lwip/netif.h" #include "lwip/inet.h" #include "lwip/sockets.h" #include <string.h> #include <stdio.h> // Server configuration #define SERVER_IP "192.168.3.231" #define SERVER_PORT 777 #define SEND_INTERVAL_MS 5000 // Send interval: 5 seconds #define SOCKET_TIMEOUT_MS 3000 // Socket operation timeout: 3 seconds // POST data (modify as needed) static const char *post_data = "temperature=25.5&humidity=60.2&device=mcxn947"; /** * Set socket timeout for connect/send/recv operations */ static void set_socket_timeout(int sockfd) { struct timeval timeout; timeout.tv_sec = SOCKET_TIMEOUT_MS / 1000; timeout.tv_usec = (SOCKET_TIMEOUT_MS % 1000) * 1000; // Set send timeout if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { PRINTF("Failed to set send timeout\n"); } // Set receive timeout if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { PRINTF("Failed to set receive timeout\n"); } } /** * Send HTTP POST request with error handling */ static int http_post_request(void) { int sockfd = -1; int ret = -1; struct sockaddr_in server_addr; char http_request[512]; int request_len; // 1. Create TCP socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { PRINTF("[POST] Failed to create socket (err: %d)\n", errno); return -1; } // 2. Set socket timeout to prevent permanent blocking set_socket_timeout(sockfd); // 3. Configure server address memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) { PRINTF("[POST] Invalid server IP: %s (err: %d)\n", SERVER_IP, errno); close(sockfd); return -1; } // 4. Connect to server PRINTF("[POST] Connecting to %s:%d...\n", SERVER_IP, SERVER_PORT); ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); if (ret < 0) { PRINTF("[POST] Connect failed (err: %d)\n", errno); close(sockfd); return -1; } PRINTF("[POST] Connected successfully\n"); // 5. Build HTTP POST request request_len = snprintf(http_request, sizeof(http_request), "POST / HTTP/1.1\r\n" "Host: %s:%d\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %d\r\n" "Connection: close\r\n" "\r\n" "%s", SERVER_IP, SERVER_PORT, strlen(post_data), post_data); if (request_len >= sizeof(http_request)) { PRINTF("[POST] Request too long (need %d bytes, buffer: %d)\n", request_len, sizeof(http_request)); close(sockfd); return -1; } // 6. Send request ret = send(sockfd, http_request, request_len, 0); if (ret < 0) { PRINTF("[POST] Send failed (err: %d)\n", errno); close(sockfd); return -1; } PRINTF("[POST] Sent %d bytes of data\n", ret); // 7. Receive response (optional, but helpful for debugging) char recv_buf[1024] = {0}; ret = recv(sockfd, recv_buf, sizeof(recv_buf)-1, 0); if (ret > 0) { PRINTF("[POST] Received %d bytes response:\n%s\n", ret, recv_buf); } else if (ret == 0) { PRINTF("[POST] Server closed connection after send\n"); } else { PRINTF("[POST] No response received (err: %d)\n", errno); } // 8. Cleanup close(sockfd); return 0; } /** * Test task: Cyclically send POST requests with error recovery */ static void http_post_test_task(void *arg) { (void)arg; // Wait for network initialization (DHCP ready) while (1) { if (netif_default != NULL && (netif_default->flags & NETIF_FLAG_UP)) { PRINTF("[TASK] Network ready. IP: %s\n", inet_ntoa(netif_default->ip_addr)); break; } vTaskDelay(pdMS_TO_TICKS(1000)); PRINTF("[TASK] Waiting for network...\n"); } // Cyclic send loop with error tolerance while (1) { PRINTF("\n[TASK] --- Sending POST request --- \n"); int result = http_post_request(); if (result != 0) { PRINTF("[TASK] Request failed. Will retry after interval.\n"); } else { PRINTF("[TASK] Request completed successfully.\n"); } // Wait for next interval vTaskDelay(pdMS_TO_TICKS(SEND_INTERVAL_MS)); } } /** * Initialize test task */ void http_post_test_init(void) { // Create task with sufficient stack size sys_thread_new("http_post_task", http_post_test_task, NULL, 2048, 3); PRINTF("[INIT] HTTP POST test task started\n"); }
【测试】
在main中添加http链接任任务创建程序
【效果】
打开串口助手,可以看到服务器成功的接收到了MCXN947周期发送的数据:
【总结】
通过官方的示例,再添加一个freertos任务,可以快速的实现http的数据交互。