在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

利用LWIP 2.2實現(xiàn)以太網(wǎng)的DHCP功能

Geehy極海半導(dǎo)體 ? 來源:21ic論壇極海半導(dǎo)體專區(qū) ? 2024-11-26 14:37 ? 次閱讀

最近學(xué)習(xí)了LWIP,了解到目前LWIP的版本已經(jīng)更新到了2.2版本。LWIP 2.2相較于之前的版本,在協(xié)議支持、性能、安全性等方面都有了顯著的改進(jìn),我將在本帖中探討如何利用LWIP 2.2來實現(xiàn)以太網(wǎng)的DHCP功能,并分享一些我所獲得的經(jīng)驗。

1.LWIP簡介

LWIP代表"輕量級IP"(Lightweight IP),是一個嵌入式系統(tǒng)中常用的開源TCP/IP協(xié)議棧。它被設(shè)計成小巧、高效,適用于資源受限的系統(tǒng),如嵌入式設(shè)備、物聯(lián)網(wǎng)設(shè)備等。LWIP提供了包括IPv4/IPv6協(xié)議、TCP、UDP、ICMP等在內(nèi)的各種網(wǎng)絡(luò)協(xié)議的實現(xiàn),同時支持各種設(shè)備接口操作系統(tǒng)。通過使用LWIP,開發(fā)者可以方便地將網(wǎng)絡(luò)連接功能集成到他們的嵌入式系統(tǒng)中,而無需從頭開始實現(xiàn)網(wǎng)絡(luò)協(xié)議棧。

LWIP1.4.1與LWIP2.2的對比

特性/方面 LWIP1.4.1 LWIP2.2
協(xié)議支持 TCP、UDP、IP、ICMP、DHCP、DNS、PPP等 TCP、UDP、IP、ICMP、DHCP、DNS、PPP等,還包括TLS(實驗性)
性能 基本性能優(yōu)化 改進(jìn)的性能優(yōu)化
安全性 有限的安全性功能 增強的安全性功能
API變更 穩(wěn)定的API 一些API變更和新增
Bug修復(fù) 針對已知問題的Bug修復(fù) 為穩(wěn)定性進(jìn)行的Bug修復(fù)和補丁
兼容性 與現(xiàn)有LWIP1.x代碼兼容 與現(xiàn)有LWIP1.x代碼兼容,但可能需要適應(yīng)性修改
文檔 提供了LWIP1.4.1文檔 更新的LWIP2.2文檔
內(nèi)存使用 適度的內(nèi)存使用 優(yōu)化的內(nèi)存使用
多線程支持 有限或無多線程支持 改進(jìn)的多線程支持
TLS支持
(安全增強)
不可用 實驗性的TLS支持

這里列舉了從LWIP1.4.1到目前最新的LWIP2.2版本主要的一些修改點。具體詳細(xì)的組件支持可去LWIP官網(wǎng)了解。

2.DHCP介紹

DynamicHost Configuration Protocol(DHCP)是一種網(wǎng)絡(luò)協(xié)議,用于在計算機網(wǎng)絡(luò)上自動分配IP地址和其他網(wǎng)絡(luò)配置信息。DHCP的主要目的是簡化網(wǎng)絡(luò)管理,避免手動配置每臺計算機的網(wǎng)絡(luò)參數(shù)。

以下是DHCP的一些關(guān)鍵特性和工作原理

1. 自動IP地址分配:DHCP允許網(wǎng)絡(luò)中的設(shè)備自動獲取IP地址,而無需管理員手動配置。這對于大型網(wǎng)絡(luò)特別有用,因為手動分配IP地址可能會變得繁瑣和容易出錯。

2. 動態(tài)分配:DHCP支持動態(tài)分配IP地址,這意味著設(shè)備在每次連接到網(wǎng)絡(luò)時可以獲得不同的IP地址。這有助于更有效地利用可用的IP地址池。

3. 配置其他網(wǎng)絡(luò)參數(shù):除了IP地址之外,DHCP還可以分配其他網(wǎng)絡(luò)配置信息,如子網(wǎng)掩碼、默認(rèn)網(wǎng)關(guān)、DNS服務(wù)器地址等。這些信息是設(shè)備與網(wǎng)絡(luò)通信所需的關(guān)鍵參數(shù)。

4. 租約機制:DHCP通過租約機制來管理分配的IP地址。設(shè)備獲得一個IP地址并與DHCP服務(wù)器建立租約,這個租約在一定時間內(nèi)有效。設(shè)備可以選擇在租約到期前續(xù)租或請求新的租約。

5. DHCP服務(wù)器:網(wǎng)絡(luò)中通常有一個或多個DHCP服務(wù)器,它們負(fù)責(zé)分配IP地址和配置信息。當(dāng)設(shè)備連接到網(wǎng)絡(luò)時,它們發(fā)送DHCP請求,DHCP服務(wù)器收到請求后分配一個可用的IP地址和相關(guān)配置信息。

6. DHCP客戶端:設(shè)備上運行的DHCP客戶端負(fù)責(zé)向網(wǎng)絡(luò)中的DHCP服務(wù)器發(fā)送請求以獲取IP地址和配置信息。DHCP客戶端通常在設(shè)備啟動時觸發(fā)DHCP過程。

7. 廣播通信:DHCP通信通常使用廣播方式進(jìn)行。DHCP客戶端在網(wǎng)絡(luò)上廣播一個請求,DHCP服務(wù)器接收到請求后回應(yīng),然后客戶端使用分配的IP地址和配置信息進(jìn)行通信。

總體而言,DHCP簡化了網(wǎng)絡(luò)管理過程,使得設(shè)備可以更輕松地連接到網(wǎng)絡(luò)而無需手動配置網(wǎng)絡(luò)參數(shù)。 DHCP在家庭網(wǎng)絡(luò)、企業(yè)網(wǎng)絡(luò)和大型互聯(lián)網(wǎng)服務(wù)提供商(ISP)網(wǎng)絡(luò)中廣泛應(yīng)用。

3.使用LWIP2.2搭建ETH DHCP例程

首先,介紹一下該例程主要實現(xiàn)的功能。

1.可以實時檢測以太網(wǎng)是否斷開,并將信息打印在串口上。

2.開發(fā)板復(fù)位后首先獲取DHCP服務(wù)器分配的IP地址。若無法查找到DHCP(設(shè)置的時間是60s),開發(fā)板會使用默認(rèn)的靜態(tài)IP地址。

3.1 訪問官網(wǎng),下載LWIP2.2源碼

官網(wǎng):https://savannah.nongnu.org/projects/lwip

5fc03846-a656-11ef-93f3-92fbcf53809c.jpg

3.2 解壓,復(fù)制到工程目錄下,并在工程中添加相關(guān)文件。

5fde1f1e-a656-11ef-93f3-92fbcf53809c.jpg

我這里是按文件分類添加的,可以自定義添加。

3.3 編寫main函數(shù)

int main(void)

{

char LCDDisplayBuf[100] = {0};

struct ip4_addr DestIPaddr;

uint8_t flag = 0;

USART_Config_T usartConfig;

/* User config the different system Clock */

UserRCMClockConfig();

/* Configure SysTick */

ConfigSysTick();

/* Configure USART */

usartConfig.baudRate = 115200;

usartConfig.wordLength = USART_WORD_LEN_8B;

usartConfig.stopBits = USART_STOP_BIT_1;

usartConfig.parity = USART_PARITY_NONE ;

usartConfig.mode = USART_MODE_TX_RX;

usartConfig.hardwareFlow = USART_HARDWARE_FLOW_NONE;

APM_BOARD_COMInit(COM1,&usartConfig);

/* Configures LED2 and LED3 */

APM_BOARD_LEDInit(LED2);

APM_BOARD_LEDInit(LED3);

/* KEY init*/

APM_BOARD_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);

APM_BOARD_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);

printf("This is a ETH TCP Client Demo! ");

/* Configure ethernet (GPIOs, clocks, MAC, DMA) */

ConfigEthernet();

/* Initilaize the LwIP stack */

LwIP_Init();

#ifndef USE_DHCP

/* Use Com printf static IP address*/

sprintf(LCDDisplayBuf,"TINY board Static IP address ");

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"IP: %d.%d.%d.%d ",

IP_ADDR0,

IP_ADDR1,

IP_ADDR2,

IP_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"NETMASK: %d.%d.%d.%d ",

NETMASK_ADDR0,

NETMASK_ADDR1,

NETMASK_ADDR2,

NETMASK_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"Gateway: %d.%d.%d.%d ",

GW_ADDR0,

GW_ADDR1,

GW_ADDR2,

GW_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"TCP Server IP: %d.%d.%d.%d:%d ",

COMP_IP_ADDR0,

COMP_IP_ADDR1,

COMP_IP_ADDR2,

COMP_IP_ADDR3,

COMP_PORT);

printf("%s",LCDDisplayBuf);

#endif

// printf(" KEY1: Connect TCP server ");

// printf("KEY2: Disconnect TCP server ");

while(1)

{

if ((APM_TINY_PBGetState(BUTTON_KEY1)==0)&&(flag==0))

{

APM_TINY_LEDOn(LED2);

if (EthLinkStatus == 0)

{

/* connect to tcp server */

printf(" Connect TCP server ");

IP4_ADDR( &DestIPaddr, COMP_IP_ADDR0, COMP_IP_ADDR1, COMP_IP_ADDR2, COMP_IP_ADDR3 );

tcpc_echo_init(&DestIPaddr,COMP_PORT);

flag=1;

}

}

if ((APM_TINY_PBGetState(BUTTON_KEY2)==0)&&(flag==1))

{

APM_TINY_LEDOff(LED2);

printf(" Disconnect TCP server ");

tcpc_echo_disable();

flag=0;

}

/* check if any packet received */

if (ETH_CheckReceivedFrame())

{

/* process received ethernet packet */

LwIP_Pkt_Handle();

}

/* handle periodic timers for LwIP */

LwIP_Periodic_Handle(ETHTimer);

}

}

main函數(shù)主要是對一些串口、GPIO的初始化操作。我在main.h中定義了一個USE_DHCP的宏,我們可以打開或注釋掉這個宏,選擇是否開啟DHCP功能。

3.4 LWIP_Init()函數(shù)

void LwIP_Init(void)

{

struct ip4_addr ipaddr;

struct ip4_addr netmask;

struct ip4_addr gw;

/* Initializes the dynamic memory heap */

mem_init();

/* Initializes the memory pools */

memp_init();

#ifdef USE_DHCP

ipaddr.addr = 0;

netmask.addr = 0;

gw.addr = 0;

#else

IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);

IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);

IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);

#endif

/* Config MAC Address */

ETH_ConfigMACAddress(ETH_MAC_ADDRESS0, SetMACaddr);

/* Add a network interface to the list of lwIP netifs */

netif_add(&UserNetif, &ipaddr, &netmask, &gw, NULL, eernetif_init, eernet_input);

/* Registers the default network interface */

netif_set_default(&UserNetif);

if (ETH_ReadPHYRegister(ETH_PHY_ADDRESS, PHY_BSR) & 1)

{

UserNetif.flags |= NETIF_FLAG_LINK_UP;

/* When the netif is fully configured this function must be called */

netif_set_up(&UserNetif);

#ifdef USE_DHCP

DHCP_state = DHCP_START;

#endif

}

else

{

netif_set_down(&UserNetif);

#ifdef USE_DHCP

DHCP_state = DHCP_LINK_DOWN;

#endif /* USE_DHCP */

printf("network cable is not connected! ");

}

netif_set_link_callback(&UserNetif, ETH_link_callback);

}

這段代碼是用于初始化LwIP網(wǎng)絡(luò)堆棧的函數(shù) LwIP_Init。讓我們逐步分析其功能:

1. 初始化IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址的結(jié)構(gòu)體變量 ipaddr、netmask 和 gw。

2. 初始化動態(tài)內(nèi)存堆。

3. 初始化內(nèi)存池。

4. 根據(jù)是否啟用了DHCP,設(shè)置IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址。

5. 配置MAC地址。

6. 將一個網(wǎng)絡(luò)接口添加到lwIP網(wǎng)絡(luò)接口列表中。

7. 注冊默認(rèn)的網(wǎng)絡(luò)接口。

8. 通過讀取PHY寄存器的狀態(tài)來判斷網(wǎng)絡(luò)連接狀態(tài):

- 如果連接狀態(tài)為鏈接狀態(tài),設(shè)置網(wǎng)絡(luò)接口的標(biāo)志為鏈接已建立,將網(wǎng)絡(luò)接口設(shè)置為已啟用,并根據(jù)是否啟用了DHCP,設(shè)置DHCP狀態(tài)為啟動。

- 如果連接狀態(tài)為斷開狀態(tài),將網(wǎng)絡(luò)接口設(shè)置為已關(guān)閉,并根據(jù)是否啟用了DHCP,設(shè)置DHCP狀態(tài)為鏈接斷開,并打印消息表示網(wǎng)絡(luò)電纜未連接。

9. 設(shè)置網(wǎng)絡(luò)接口的鏈接狀態(tài)回調(diào)函數(shù)為 ETH_link_callback。

綜上所述,該函數(shù)主要用于初始化LwIP網(wǎng)絡(luò)堆棧。它包括初始化內(nèi)存堆和內(nèi)存池、配置網(wǎng)絡(luò)接口的IP地址信息、MAC地址、添加網(wǎng)絡(luò)接口到lwIP列表中、判斷網(wǎng)絡(luò)連接狀態(tài)并相應(yīng)地設(shè)置網(wǎng)絡(luò)接口狀態(tài)和DHCP狀態(tài),最后設(shè)置網(wǎng)絡(luò)接口的鏈接狀態(tài)回調(diào)函數(shù)。

3.5 ETH_link_callback函數(shù)

void ETH_link_callback(struct netif *netif)

{

__IO uint32_t timeout = 0;

uint16_t RegValue;

struct ip4_addr ipaddr;

struct ip4_addr netmask;

struct ip4_addr gw;

if(netif_is_link_up(netif))

{

/* Restart the auto-negotiation */

if(ETH_InitStructure.autoNegotiation == ETH_AUTONEGOTIATION_ENABLE)

{

/* Reset Timeout counter */

timeout = 0;

/* Enable auto-negotiation */

ETH_WritePHYRegister(ETH_PHY_ADDRESS, PHY_BCR, PHY_AUTONEGOTIATION);

/* Wait until the auto-negotiation will be completed */

do

{

timeout++;

} while (!(ETH_ReadPHYRegister(ETH_PHY_ADDRESS, PHY_BSR) & PHY_AUTONEGO_COMPLETE) && (timeout < (uint32_t)PHY_READ_TIMEOUT));??

/* Reset Timeout counter */

timeout = 0;

/* Read the result of the auto-negotiation */

RegValue = ETH_ReadPHYRegister(ETH_PHY_ADDRESS, PHY_SR);

/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */

if((RegValue & PHY_DUPLEX_STATUS) != (uint16_t)RESET)

{

/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */

ETH_InitStructure.mode = ETH_MODE_FULLDUPLEX;

}

else

{

/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */

ETH_InitStructure.mode = ETH_MODE_HALFDUPLEX;

}

/* Configure the MAC with the speed fixed by the auto-negotiation process */

if(RegValue & PHY_SPEED_STATUS)

{

/* Set Ethernet speed to 10M following the auto-negotiation */

ETH_InitStructure.speed = ETH_SPEED_10M;

}

else

{

/* Set Ethernet speed to 100M following the auto-negotiation */

ETH_InitStructure.speed = ETH_SPEED_100M;

}

/*------------------------ ETHERNET MACCR Re-Configuration --------------------*/

/* Set the FES bit according to ETH_Speed value */

/* Set the DM bit according to ETH_Mode value */

ETH->CFG_B.SSEL = ETH_InitStructure.speed;

ETH->CFG_B.DM = ETH_InitStructure.mode;

Delay(0x00000001);

}

/* Restart MAC interface */

ETH_Start();

#ifdef USE_DHCP

ipaddr.addr = 0;

netmask.addr = 0;

gw.addr = 0;

DHCP_state = DHCP_START;

#else

IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);+

IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);

IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);

#endif /* USE_DHCP */

netif_set_addr(&UserNetif, &ipaddr , &netmask, &gw);

/* When the netif is fully configured this function must be called.*/

netif_set_up(&UserNetif);

/* Display message on the LCD */

printf("network cable is connected now ! ");

EthLinkStatus = 0;

}

else

{

ETH_Stop();

#ifdef USE_DHCP

DHCP_state = DHCP_LINK_DOWN;

dhcp_stop(netif);

#endif /* USE_DHCP */

/* When the netif link is down this function must be called.*/

netif_set_down(&UserNetif);

printf("network cable is unplugged! ");

}

}

這段代碼是一個用于處理以太網(wǎng)鏈接狀態(tài)變化的回調(diào)函數(shù) ETH_link_callback。讓我們逐步分析它的功能:

1. 首先,聲明了一些變量,包括超時計數(shù)器 timeout、存儲從PHY讀取的寄存器值的變量 RegValue,以及用于存儲IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址的變量。

2. 如果網(wǎng)絡(luò)接口的鏈接狀態(tài)為鏈接狀態(tài)(通過 netif_is_link_up(netif) 判斷):

- 如果啟用了以太網(wǎng)自動協(xié)商(ETH_InitStructure.autoNegotiation== ETH_AUTONEGOTIATION_ENABLE),則重新啟動自動協(xié)商過程:

- 向PHY寄存器寫入自動協(xié)商命令 PHY_AUTONEGOTIATION。

- 等待自動協(xié)商完成,超時時間由 PHY_READ_TIMEOUT 定義。

- 讀取自動協(xié)商結(jié)果,根據(jù)結(jié)果配置以太網(wǎng)MAC的速度和雙工模式。

- 根據(jù)速度和雙工模式重新配置以太網(wǎng)MAC控制器的寄存器。

- 重新啟動MAC接口。

- 根據(jù)是否啟用了DHCP,設(shè)置IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址,并將網(wǎng)絡(luò)接口標(biāo)記為已啟用。

- 打印消息,表示網(wǎng)絡(luò)電纜已連接。

- 將 EthLinkStatus 標(biāo)記為鏈接狀態(tài)。

3. 如果網(wǎng)絡(luò)接口的鏈接狀態(tài)為斷開狀態(tài),執(zhí)行以下操作:

- 停止MAC接口。

- 如果啟用了DHCP,將DHCP狀態(tài)設(shè)置為鏈接斷開,并停止DHCP客戶端。

- 將網(wǎng)絡(luò)接口標(biāo)記為已關(guān)閉。

- 打印消息,表示網(wǎng)絡(luò)電纜已拔出。

綜上所述,該函數(shù)主要用于處理以太網(wǎng)鏈接狀態(tài)的變化。根據(jù)鏈接狀態(tài)的變化,重新啟動自動協(xié)商過程(如果啟用了自動協(xié)商),配置以太網(wǎng)MAC的參數(shù),并設(shè)置IP地址信息。同時,根據(jù)鏈接狀態(tài)的變化執(zhí)行相應(yīng)的動作,例如重新啟動或停止MAC接口,并更新相應(yīng)的狀態(tài)標(biāo)志。

3.6 LwIP_Periodic_Handle

void LwIP_Periodic_Handle(__IO uint32_t ETHTimer)

{

static uint8_t flagToggle = 0;

#if LWIP_TCP

/* TCP periodic process every 250 ms */

if (ETHTimer - TCPTimer >= TCP_TMR_INTERVAL)

{

TCPTimer = ETHTimer;

tcp_tmr();

}

#endif

/* ARP periodic process every 5s */

if ((ETHTimer - ARPTimer) >= ARP_TMR_INTERVAL)

{

ARPTimer = ETHTimer;

etharp_tmr();

}

/* Check link status */

if ((ETHTimer - LinkTimer) >= 1000)

{

if ((ETH_GET_LINK_STATUS != 0) && (flagToggle == 0))

{

/* link goes up */

netif_set_link_up(&UserNetif);

flagToggle = 1;

}

if ((ETH_GET_LINK_STATUS == 0) && (flagToggle == 1))

{

EthLinkStatus = 1;

/* link goes down */

netif_set_link_down(&UserNetif);

flagToggle = 0;

}

}

#ifdef USE_DHCP

/* Fine DHCP periodic process every 500ms */

if (ETHTimer - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)

{

DHCPfineTimer = ETHTimer;

dhcp_fine_tmr();

if ((DHCP_state != DHCP_ADDRESS_ASSIGNED) &&

(DHCP_state != DHCP_TIMEOUT) &&

(DHCP_state != DHCP_LINK_DOWN))

{

/* toggle LED1 to indicate DHCP on-going process */

APM_TINY_LEDOn(LED2);

/* process DHCP state machine */

LwIP_DHCP_Process_Handle();

}

}

/* DHCP Coarse periodic process every 60s */

if (ETHTimer - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS)

{

DHCPcoarseTimer = ETHTimer;

dhcp_coarse_tmr();

}

#endif

}

以上函數(shù)是一個用于處理LwIP(Lightweight IP)網(wǎng)絡(luò)堆棧的周期性任務(wù)的函數(shù)。讓我們逐段分析它:

1.staticuint8_t flagToggle = 0;:定義了一個靜態(tài)變量 flagToggle,用于跟蹤網(wǎng)絡(luò)連接狀態(tài)的變化。

2. if(ETHTimer - TCPTimer >= TCP_TMR_INTERVAL):檢查TCP定時器是否超過了TCP_TMR_INTERVAL(TCP定時器間隔),如果超過,則調(diào)用 tcp_tmr() 函數(shù)進(jìn)行TCP定時器處理。

3. if((ETHTimer - ARPTimer) >= ARP_TMR_INTERVAL):檢查ARP定時器是否超過了ARP_TMR_INTERVAL(ARP定時器間隔),如果超過,則調(diào)用 etharp_tmr() 函數(shù)進(jìn)行ARP定時器處理。

4. if((ETHTimer - LinkTimer) >= 1000):檢查鏈接狀態(tài)是否需要更新,如果超過了一定時間(這里設(shè)置為1000ms),則進(jìn)行鏈接狀態(tài)檢查。

5. if((ETH_GET_LINK_STATUS != 0) && (flagToggle == 0)):檢查網(wǎng)絡(luò)鏈接狀態(tài)是否正常,并且之前的狀態(tài)是斷開的,如果是,則設(shè)置網(wǎng)絡(luò)接口為鏈接狀態(tài)。

6. if((ETH_GET_LINK_STATUS == 0) && (flagToggle == 1)):檢查網(wǎng)絡(luò)鏈接狀態(tài)是否異常,并且之前的狀態(tài)是連接的,如果是,則設(shè)置網(wǎng)絡(luò)接口為斷開狀態(tài)。

7. if(ETHTimer - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS):檢查是否需要進(jìn)行DHCP的Fine定時處理,如果超過了DHCP_FINE_TIMER_MSECS(Fine定時器間隔),則調(diào)用 dhcp_fine_tmr() 函數(shù)。

8. if(ETHTimer - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS):檢查是否需要進(jìn)行DHCP的Coarse定時處理,如果超過了DHCP_COARSE_TIMER_MSECS(Coarse定時器間隔),則調(diào)用 dhcp_coarse_tmr() 函數(shù)。

在整個函數(shù)中,主要處理了TCP、ARP、網(wǎng)絡(luò)鏈接狀態(tài)和DHCP的周期性任務(wù)。這些任務(wù)包括定時器的處理以及相應(yīng)的動作,例如發(fā)送ARP請求、更新網(wǎng)絡(luò)鏈接狀態(tài)和處理DHCP狀態(tài)機等。

3.7 LwIP_DHCP_Process_Handle

void LwIP_DHCP_Process_Handle(void)

{

struct ip4_addr ipaddr;

struct ip4_addr netmask;

struct ip4_addr gw;

uint8_t iptab[4] = {0};

char LCDDisplayBuf[100] = {0};

switch (DHCP_state)

{

case DHCP_START:

{

DHCP_state = DHCP_WAIT_ADDRESS;

dhcp_start(&UserNetif);

/* IP address should be set to 0

every time we want to assign a new DHCP address */

IPaddress = 0;

printf(" Looking for DHCP server, please wait..... ");

}

break;

case DHCP_WAIT_ADDRESS:

{

/* Read the new IP address */

struct dhcp *dhcp = netif_dhcp_data(&UserNetif);

if (dhcp->offered_ip_addr.addr != 0 && dhcp->offered_sn_mask.addr != 0 && dhcp->offered_gw_addr.addr != 0)

{

DHCP_state = DHCP_ADDRESS_ASSIGNED;

printf("IP address assigned by a DHCP server! ");

IPaddress = dhcp->offered_ip_addr.addr;

iptab[0] = (uint8_t)(IPaddress >> 24);

iptab[1] = (uint8_t)(IPaddress >> 16);

iptab[2] = (uint8_t)(IPaddress >> 8);

iptab[3] = (uint8_t)(IPaddress);

IP4_ADDR(&ipaddr, iptab[3] ,iptab[2] , iptab[1] , iptab[0] );

sprintf(LCDDisplayBuf,"IP: %d.%d.%d.%d ",

iptab[3],

iptab[2],

iptab[1],

iptab[0]);

printf("%s",LCDDisplayBuf);

IPaddress = dhcp->offered_sn_mask.addr;

iptab[0] = (uint8_t)(IPaddress >> 24);

iptab[1] = (uint8_t)(IPaddress >> 16);

iptab[2] = (uint8_t)(IPaddress >> 8);

iptab[3] = (uint8_t)(IPaddress);

IP4_ADDR(&netmask, iptab[3] ,iptab[2] , iptab[1] , iptab[0] );

sprintf(LCDDisplayBuf,"NETMASK: %d.%d.%d.%d ",

iptab[3],

iptab[2],

iptab[1],

iptab[0]);

printf("%s",LCDDisplayBuf);

IPaddress = dhcp->offered_gw_addr.addr;

iptab[0] = (uint8_t)(IPaddress >> 24);

iptab[1] = (uint8_t)(IPaddress >> 16);

iptab[2] = (uint8_t)(IPaddress >> 8);

iptab[3] = (uint8_t)(IPaddress);

IP4_ADDR(&gw, iptab[3] ,iptab[2] , iptab[1] , iptab[0]);

sprintf(LCDDisplayBuf,"Gateway: %d.%d.%d.%d ",

iptab[3],

iptab[2],

iptab[1],

iptab[0]);

printf("%s",LCDDisplayBuf);

IPaddress = dhcp->server_ip_addr.addr;

iptab[0] = (uint8_t)(IPaddress >> 24);

iptab[1] = (uint8_t)(IPaddress >> 16);

iptab[2] = (uint8_t)(IPaddress >> 8);

iptab[3] = (uint8_t)(IPaddress);

sprintf(LCDDisplayBuf,"TCP Server IP: %d.%d.%d.%d ",

iptab[3],

iptab[2],

iptab[1],

iptab[0]);

printf("%s",LCDDisplayBuf);

// IP4_ADDR( &s_ipaddr, iptab[3] ,iptab[2] , iptab[1] , iptab[0] );

// udp_connect();

/* Stop DHCP */

dhcp_stop(&UserNetif);

// UserNetif.ip_addr.addr = ipaddr.addr;

// UserNetif.netmask.addr = netmask.addr;

// UserNetif.gw.addr = gw.addr;

netif_set_addr(&UserNetif, &ipaddr , &netmask, &gw);

APM_TINY_LEDOn(LED2);

}

else

{

/* DHCP timeout */

if (dhcp->tries > 4)

{

DHCP_state = DHCP_TIMEOUT;

/* Stop DHCP */

dhcp_stop(&UserNetif);

/* Static address used */

/* Use Com printf static IP address*/

printf("DHCP timeout! ");

/* Static address used */

IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );

IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);

IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);

netif_set_addr(&UserNetif, &ipaddr , &netmask, &gw);

sprintf(LCDDisplayBuf,"TINY board Static IP address ");

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"IP: %d.%d.%d.%d ",

IP_ADDR0,

IP_ADDR1,

IP_ADDR2,

IP_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"NETMASK: %d.%d.%d.%d ",

NETMASK_ADDR0,

NETMASK_ADDR1,

NETMASK_ADDR2,

NETMASK_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"Gateway: %d.%d.%d.%d ",

GW_ADDR0,

GW_ADDR1,

GW_ADDR2,

GW_ADDR3);

printf("%s",LCDDisplayBuf);

sprintf(LCDDisplayBuf,"TCP Server IP: %d.%d.%d.%d:%d ",

COMP_IP_ADDR0,

COMP_IP_ADDR1,

COMP_IP_ADDR2,

COMP_IP_ADDR3,

COMP_PORT);

printf("%s",LCDDisplayBuf);

APM_TINY_LEDOn(LED2);

}

}

}

break;

default: break;

}

}

這段代碼是用于處理LwIP網(wǎng)絡(luò)堆棧中DHCP過程的函數(shù) LwIP_DHCP_Process_Handle。它通過狀態(tài)機來處理DHCP過程的不同階段。讓我們逐步分析其功能:

1. 在 DHCP_START 狀態(tài)下,將狀態(tài)切換到 DHCP_WAIT_ADDRESS,并啟動DHCP客戶端。

2. 在 DHCP_WAIT_ADDRESS 狀態(tài)下,如果DHCP客戶端獲得了IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址,將狀態(tài)切換到 DHCP_ADDRESS_ASSIGNED,打印獲得的IP地址、子網(wǎng)掩碼和網(wǎng)關(guān)地址,并停止DHCP客戶端。

3. 如果DHCP超時(嘗試次數(shù)超過4次),將狀態(tài)切換到 DHCP_TIMEOUT,停止DHCP客戶端,并使用靜態(tài)IP地址(如果配置了靜態(tài)IP地址)。

綜上所述,該函數(shù)主要用于處理LwIP網(wǎng)絡(luò)堆棧中DHCP過程的不同階段。根據(jù)DHCP狀態(tài)的不同,執(zhí)行不同的操作,例如啟動DHCP客戶端、處理獲取到的IP地址信息、處理超時情況等。

4. 實驗現(xiàn)象

1.串口打印相關(guān)信息

5fe3b852-a656-11ef-93f3-92fbcf53809c.jpg

2.正常獲取IP后,cmd執(zhí)行ping命令,正常通信

5ff26280-a656-11ef-93f3-92fbcf53809c.jpg

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    40

    文章

    5424

    瀏覽量

    171702
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    41

    文章

    3593

    瀏覽量

    129466
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1353

    瀏覽量

    79070
  • DHCP
    +關(guān)注

    關(guān)注

    0

    文章

    105

    瀏覽量

    19716
  • LwIP
    +關(guān)注

    關(guān)注

    2

    文章

    86

    瀏覽量

    27168

原文標(biāo)題:APM32芯得 EP.46 | 增強以太網(wǎng)連接:使用LWIP 2.2實現(xiàn)動態(tài)主機配置協(xié)議(DHCP)

文章出處:【微信號:geehysemi,微信公眾號:Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    如何實現(xiàn)以太網(wǎng)功能的,是用F107或F407芯片自己移植Lwip還是采用SPI轉(zhuǎn)以太網(wǎng)模塊?

    一般大家是如何實現(xiàn)以太網(wǎng)功能的,是用F107或F407芯片自己移植Lwip還是采用SPI轉(zhuǎn)以太網(wǎng)模塊?
    發(fā)表于 05-17 06:49

    基于FPGA的萬兆以太網(wǎng)接口的設(shè)計與實現(xiàn)

    基于FPGA的萬兆以太網(wǎng)接口的設(shè)計與實現(xiàn)標(biāo)準(zhǔn)中萬兆以太網(wǎng)物理層及媒質(zhì)接入控制子層的相關(guān)協(xié)議以 應(yīng)用物理環(huán)境為例,闡述了萬兆以太網(wǎng)接口各個單元模塊的
    發(fā)表于 08-11 15:48

    NIOS實現(xiàn)以太網(wǎng)

    基于NIOS2的嵌入式實現(xiàn)以太網(wǎng)通信
    發(fā)表于 09-08 12:39

    請問ATK-RM04_WIFI模塊能實現(xiàn)以太網(wǎng)轉(zhuǎn)WIFI功能嗎?

    ATK-RM04_WIFI模塊能不能實現(xiàn)以太網(wǎng)轉(zhuǎn)WIFI功能???
    發(fā)表于 11-06 01:15

    請問嵌入式系統(tǒng)實現(xiàn)以太網(wǎng),TCP/IP協(xié)議棧是都是移植的嗎?

    想請教各位大神們。嵌入式系統(tǒng)實現(xiàn)以太網(wǎng)(比如stm32),TCP/IP協(xié)議棧是不是都是移植的。比如都移植LWIP。UIP等。而不是自己寫啊…………感謝……
    發(fā)表于 03-13 02:22

    沒有發(fā)現(xiàn)以太網(wǎng)

    PIC32以太網(wǎng)啟動器套件II,編號:DM320004-2。我編譯并下載了TCPIP演示應(yīng)用程序,但是微芯片以太網(wǎng)發(fā)現(xiàn)器應(yīng)用程序沒有發(fā)現(xiàn)以太網(wǎng),而不管在另一臺計算機上重復(fù)這個過程。有人遇到過這個問題并找到解決辦法嗎?謝謝
    發(fā)表于 04-10 06:43

    請教大神怎樣去實現(xiàn)以太網(wǎng)MAC子層協(xié)議?

    什么是以太網(wǎng)MAC子層協(xié)議?怎樣去實現(xiàn)以太網(wǎng)MAC子層協(xié)議?
    發(fā)表于 05-06 10:33

    怎么實現(xiàn)以太網(wǎng)的光無線通信系統(tǒng)的設(shè)計?

    怎么實現(xiàn)以太網(wǎng)的光無線通信系統(tǒng)的設(shè)計?
    發(fā)表于 05-28 07:08

    如何利用STM32CubeMX實現(xiàn)FreeRTOS+LAN8720A+LWIP以太網(wǎng)ping通?

    如何利用STM32CubeMX實現(xiàn)FreeRTOS+LAN8720A+LWIP以太網(wǎng)ping通?
    發(fā)表于 02-22 07:49

    單片機實現(xiàn)以太網(wǎng)通訊硬件設(shè)計

    介紹以太網(wǎng)的幀協(xié)議和以太網(wǎng)控制芯片RTL8019AS的結(jié)構(gòu)特性;介紹單片機控制RTL8019AS實現(xiàn)以太網(wǎng)通訊的硬件設(shè)計方案;采用c51語言實現(xiàn)RPP協(xié)議(地址解析協(xié)議),并進(jìn)行了系統(tǒng)
    發(fā)表于 08-29 16:32 ?126次下載
    單片機<b class='flag-5'>實現(xiàn)以太網(wǎng)</b>通訊硬件設(shè)計

    ST有關(guān)以太網(wǎng)講座課件

    ST公司培訓(xùn)有關(guān)以太網(wǎng)講座課件,包括tcp/ip協(xié)議、以太網(wǎng)基礎(chǔ)、Lwip、網(wǎng)卡設(shè)計與實現(xiàn)等等介紹
    發(fā)表于 03-07 11:50 ?20次下載

    以太網(wǎng)Lwip例程

    以太網(wǎng)Lwip例程
    發(fā)表于 12-06 16:53 ?28次下載
    <b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>Lwip</b>例程

    AT89C52單片機實現(xiàn)以太網(wǎng)接口的控制設(shè)計

    隨著互聯(lián)網(wǎng)的迅速發(fā)展,網(wǎng)絡(luò)用戶飛速增長,在使用計算機進(jìn)行網(wǎng)絡(luò)互聯(lián)的同時,各種家電設(shè)備、儀表設(shè)備及工業(yè)中數(shù)據(jù)采集與控制設(shè)備也在逐步走向網(wǎng)絡(luò)化,基于此結(jié)合專用的以太網(wǎng)控制芯片RTL8019學(xué)習(xí)了利用單片機實現(xiàn)以太網(wǎng)接口的設(shè)計。
    發(fā)表于 03-03 11:17 ?2819次閱讀
    AT89C52單片機<b class='flag-5'>實現(xiàn)以太網(wǎng)</b>接口的控制設(shè)計

    PLC如何實現(xiàn)以太網(wǎng)口無線通訊

    PLC若想實現(xiàn)以太網(wǎng)口無線通訊,首先我們需要確定好PLC型號,然后選擇一個合適的通訊設(shè)備。比如如果是西門子S7-200PLC,就需要使用歐美PLC無線通訊終端,并且這個設(shè)備需要支持以太網(wǎng)口通訊。
    發(fā)表于 03-08 09:17 ?5072次閱讀

    Android 9以太網(wǎng)功能移植以及設(shè)置IP地址

    基于Android 9實現(xiàn)以太網(wǎng)的IP地址設(shè)置和功能實現(xiàn)
    發(fā)表于 06-20 14:42 ?2次下載
    主站蜘蛛池模板: 天天添| 久久九九国产| 欧美色欧| freesexvideo性欧美医生护士| 免费jlzzjlzz在线播放视频| 国产毛片哪里有| 精品一区二区三区在线视频| 作爱在线观看| 女人张开腿让男人捅爽| 天天在线天天看成人免费视频 | 视频在线免费| 成年男人午夜片免费观看| 免费人成网ww777kkk手机| 亚洲欧美色鬼久久综合| 国产色窝| avt天堂网| 午夜爱爱免费视频| 国产精品yy9299在线观看| 国产未成女年一区二区| 亚洲色图欧美在线| 国产高清视频免费最新在线 | 丁香六月综合激情| 色天网站| 手机看片1024精品日韩| 美欧毛片| 日本小视频免费| 天天亚洲| 91久久澡人人爽人人添| 国产一级做a爰片久久毛片| 99国产福利| 四虎国产精品永久免费网址| 黄色三级录像| 1024人成网色www| 色老头永久免费网站| 天天干天天草天天射| 99热最新在线| 成人在线亚洲| 加勒比黑人喝羽月希奶水| 亚洲人成影网站~色| 99久久综合狠狠综合久久男同| 亚洲一区区|