由於LAN8720使用的是外部25MHz的晶振,因此不須要單片機輸出時鐘服務器
LAN8720A在初始化的時候須要復位,所以在ethernetif.c的 static void low_level_init(struct netif *netif) 函數中添加LAN8720A 的復位程序tcp
再mian函數主循環中添加一下代碼,而後編譯運行,正常的話,再路由器中能看到程序中設置的MAC地址,以及分配的IP,此時可以ping通函數
MX_LWIP_Process();
成功了?NoNoNO,若是你啓動的時候沒有接網線,等啓動以後,再插上網線,你會發現,板子死活都不會找dhcp服務器要IP, 結果就是失聯。。重大缺陷,不能忍!幸好LWIP協議棧早就想到了這種狀況,LWIP_NETIF_LINK_CALLBACK是幹嗎的?就是在鏈接狀態改變的時候,調用一個回調函數,來作相應的處理ui
在main函數的住循環中加入spa
extern struct netif *netif_default; ethernetif_set_link(netif_default);
這個函數會查詢當前的鏈接狀態,當狀態改變的時候,調用回調函數,在ethernetif.c裏咱們能夠找到這個回調函數,.net
void ethernetif_update_config(struct netif *netif)
果真有不少處理,那爲何仍是不能打開dhcp呢?來看看這個函數的末尾,調用了這個函數3d
ethernetif_notify_conn_changed()
這個函數,而這個函數看看註釋就知道,是須要咱本身來實現的,因此咱們加入如下的代碼code
1 /** 2 * @brief This function notify user about link status changement. 3 * @param netif: the network interface 4 * @retval None 5 */ 6 __weak void ethernetif_notify_conn_changed(struct netif *netif) 7 { 8 /* NOTE : This is function could be implemented in user file 9 when the callback is needed, 10 */ 11 if(netif_is_link_up(netif) && !netif_is_up(netif)) 12 { 13 netif_set_up(netif); 14 extern err_t dhcp_start(struct netif *netif); 15 dhcp_start(netif); 16 } 17 }
重編譯下載,拔掉網線,開機,再插上網線,得到了IP, 大功告成!blog
從庫中示例代碼中把LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c 和 tcp_echoclient.h 拷貝到工程中,而後添加發送函數內存
1 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size) 2 { 3 err_t ret_err; 4 struct echoclient *es; 5 es=tpcb->callback_arg; 6 if(es!=NULL) //鏈接處於空閒時能夠發送數據 7 { 8 es->p_tx=pbuf_alloc(PBUF_TRANSPORT, size,PBUF_POOL); //申請內存 9 pbuf_take(es->p_tx,(char*)buff,size); //將tcp_client_sentbuf[]中的數據拷貝到es->p_tx中 10 tcp_echoclient_send(tpcb,es); //將tcp_client_sentbu[]裏面複製給pbuf的數據發送出去 11 if(es->p_tx)pbuf_free(es->p_tx); //釋放內存 12 ret_err=ERR_OK; 13 }else 14 { 15 tcp_abort(tpcb); //終止鏈接,刪除pcb控制塊 16 ret_err=ERR_ABRT; 17 } 18 return ret_err; 19 }
在 tcp_echoclient.h中須要添加鏈接到的服務器的IP地址和端口
1 #include "err.h" 2 #include "tcp.h" 3 /* Includes ------------------------------------------------------------------*/ 4 /* Exported types ------------------------------------------------------------*/ 5 /* Exported constants --------------------------------------------------------*/ 6 /* Exported macro ------------------------------------------------------------*/ 7 /* Exported functions ------------------------------------------------------- */ 8 void tcp_echoclient_connect(void); 9 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size); 10 11 #define DEST_IP_ADDR0 192 12 #define DEST_IP_ADDR1 168 13 #define DEST_IP_ADDR2 000 14 #define DEST_IP_ADDR3 108 15 16 17 #define DEST_PORT 9001
經過以上更改,就可使用 tcp_client_usersent()函數進行發送數據了
1 /** 2 * @brief 發送數據包 3 * @retval None 4 */ 5 void UCP_DataAnswer(void) 6 { 7 tcp_client_usersent(echoclient_pcb, ToSendBuf, 23); 8 tcp_client_usersent(echoclient_pcb, DeSendBuf, 23); 9 }
上面已經能正常發送數據了,若是我把網線拔下來,在插上去又怎麼樣呢,試試?全部在main函數的主循環中增長斷線重連的代碼
1 /* USER CODE BEGIN WHILE */ 2 while (1) 3 { 4 HAL_GPIO_TogglePin(ALARM_GPIO_Port, ALARM_Pin); 5 MX_LWIP_Process(); // LwIP Initialization 6 ethernetif_set_link(netif_default); // This function sets the netif link status. 7 8 // 拔掉網線後,因爲服務端單向斷開鏈接,客戶端會進入FIN_WAIT_2等待狀態 9 if(echoclient_pcb->state == CLOSED || echoclient_pcb->state == FIN_WAIT_2) 10 { 11 tcp_abort(echoclient_pcb); 12 tcp_echoclient_connect(); // 斷線重連 13 } 14