基於STM32 LWIP協議棧實現TCP以太網數據通信

在做以太網的數據傳輸,要把AD採到的數據通過網口發送給上位機(客戶端),我採用的是LWIP協議棧,實現了此功能。不管做項目時間多緊,也要先熟悉一下LWIP協議棧,TCP 及UDP傳輸協議。我採用的是TCP協議數據傳輸,好處是傳輸可靠。直接貼代碼,從main開始:

int main(void) { SystemInit(); System_Setup(); GpioLed_Init(); Init_Usart(); GPIO_Configuration(); GPIO_Configuration_SPI(); RCC_Configuration(); NVIC_Configuration(); Time_Configuration(); SPI_Configuration(); LwIP_Init(); HelloWorld_init(); while(1) { TI_ADC128S022_ADC_vout(); printf("Frequency1= %d HZ.\r\n",Frequency1); printf("Frequency2= %d HZ.\r\n",Frequency2); printf("V=%fmv\r\n",V); MCU_to_TCP(); /* Periodic tasks */ System_Periodic_Handle(); } }

說一下LwIP_Init();函數,主要是LWIP協議棧,IP和MAC初始化,

void LwIP_Init(void) { struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; uint8_t macaddress[6]={0,0,0,0,0,1}; /* Initializes the dynamic memory heap defined by MEM_SIZE.*/ mem_init(); /* Initializes the memory pools defined by MEMP_NUM_x.*/ memp_init(); IP4_ADDR(&ipaddr, 192, 168, 1, 198); IP4_ADDR(&netmask, 255, 255, 255, 0); IP4_ADDR(&gw, 192, 168, 1, 1); Set_MAC_Address(macaddress); netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input); /*Registers the default network interface.*/ netif_set_default(&netif); netif_set_up(&netif); }

HelloWorld_init();是建立TCP端口,

void HelloWorld_init(void) { /* Create a new TCP control block */ pcb = tcp_new(); /* Assign to the new pcb a local IP address and a port number */ /* Using IP_ADDR_ANY allow the pcb to be used by any local interface */ tcp_bind(pcb, IP_ADDR_ANY, 3007); /* Set the connection to the LISTEN state */ pcb = tcp_listen(pcb); /* Specify the function to be called when a connection is established */ tcp_accept(pcb, HelloWorld_accept); }

tcp_bind(pcb, IP_ADDR_ANY, 3007);是綁定你的端口號和IP地址, pcb = tcp_listen(pcb);進入監聽,檢查連接,申請TCP_PCB內存,tcp_accept(pcb, HelloWorld_accept);客戶端連接以後的回調函數,可以收發數據。

static err_t HelloWorld_accept(void *arg, struct tcp_pcb *pcb, err_t err) { tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));//回傳建立連接 tcp_err(pcb, HelloWorld_conn_err);//錯誤回調函數 tcp_recv(pcb, HelloWorld_recv);//指定收到數據的回調函數 return ERR_OK; }

void MCU_to_TCP(void)函數是給單片機(服務器)傳輸數據函數,每次傳輸數據完之後要調用tcp_output(cpcb);函數,用於TCP輸出。我之前調用tcp_write函數,每次只能收到一次數據,需要新創建一個新的pcb協議控制塊,tcp_write之後要調用tcp_output函數,才能不斷髮送數據。

void MCU_to_TCP(void) { struct tcp_pcb *cpcb; for(cpcb = tcp_active_pcbs;cpcb != NULL; cpcb = cpcb->next) { memset(GpcBufFileRead, 0x00, sizeof(GpcBufFileRead)); sprintf( (void *)readdata, "Frequency1 = %dHz\nFrequency2 = %dHz\nV = %fmv\n", Frequency1,Frequency2,V); //tcp_write(pcb, GpcBufFileRead, strlen((void *)readdata), 1); tcp_write(cpcb,GpcBufFileRead,strlen((void *)readdata),TCP_WRITE_FLAG_COPY); tcp_output(cpcb); } }

這樣就可以簡單實現LWIP TCP數據傳輸了,主要是這幾個地方注意一下,很快可以實現網口數據的發送與接收。

在調試以太網的時候應該注意的問題如下:

電腦IP地址一定要和開發板的IP地址在一個網絡內,例如開發板IP是:192.168.1.118,子網掩碼:255.255.255.0,默認網關:192.168.1.1。需要斷開電腦網絡,連接網線,設置電腦IP地址為192.168.1.X(2-254), 子網掩碼:255.255.255.0,默認網關:192.168.1.1,首選DNS服務器:192.168.1.1。即可實現路由器或者上位機與開發板建立連接。