色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

利用LWIP 2.2實現以太網的DHCP功能

Geehy極海半導體 ? 來源:21ic論壇極海半導體專區 ? 2024-11-26 14:37 ? 次閱讀

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

1.LWIP簡介

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

LWIP1.4.1與LWIP2.2的對比

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

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

2.DHCP介紹

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

以下是DHCP的一些關鍵特性和工作原理

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

2. 動態分配:DHCP支持動態分配IP地址,這意味著設備在每次連接到網絡時可以獲得不同的IP地址。這有助于更有效地利用可用的IP地址池。

3. 配置其他網絡參數:除了IP地址之外,DHCP還可以分配其他網絡配置信息,如子網掩碼、默認網關、DNS服務器地址等。這些信息是設備與網絡通信所需的關鍵參數。

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

5. DHCP服務器:網絡中通常有一個或多個DHCP服務器,它們負責分配IP地址和配置信息。當設備連接到網絡時,它們發送DHCP請求,DHCP服務器收到請求后分配一個可用的IP地址和相關配置信息。

6. DHCP客戶端:設備上運行的DHCP客戶端負責向網絡中的DHCP服務器發送請求以獲取IP地址和配置信息。DHCP客戶端通常在設備啟動時觸發DHCP過程。

7. 廣播通信:DHCP通信通常使用廣播方式進行。DHCP客戶端在網絡上廣播一個請求,DHCP服務器接收到請求后回應,然后客戶端使用分配的IP地址和配置信息進行通信。

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

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

首先,介紹一下該例程主要實現的功能。

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

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

3.1 訪問官網,下載LWIP2.2源碼

官網:https://savannah.nongnu.org/projects/lwip

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

3.2 解壓,復制到工程目錄下,并在工程中添加相關文件。

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

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

3.3 編寫main函數

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

3.4 LWIP_Init()函數

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網絡堆棧的函數 LwIP_Init。讓我們逐步分析其功能:

1. 初始化IP地址、子網掩碼和網關地址的結構體變量 ipaddr、netmask 和 gw。

2. 初始化動態內存堆。

3. 初始化內存池。

4. 根據是否啟用了DHCP,設置IP地址、子網掩碼和網關地址。

5. 配置MAC地址。

6. 將一個網絡接口添加到lwIP網絡接口列表中。

7. 注冊默認的網絡接口。

8. 通過讀取PHY寄存器的狀態來判斷網絡連接狀態:

- 如果連接狀態為鏈接狀態,設置網絡接口的標志為鏈接已建立,將網絡接口設置為已啟用,并根據是否啟用了DHCP,設置DHCP狀態為啟動。

- 如果連接狀態為斷開狀態,將網絡接口設置為已關閉,并根據是否啟用了DHCP,設置DHCP狀態為鏈接斷開,并打印消息表示網絡電纜未連接。

9. 設置網絡接口的鏈接狀態回調函數為 ETH_link_callback。

綜上所述,該函數主要用于初始化LwIP網絡堆棧。它包括初始化內存堆和內存池、配置網絡接口的IP地址信息、MAC地址、添加網絡接口到lwIP列表中、判斷網絡連接狀態并相應地設置網絡接口狀態和DHCP狀態,最后設置網絡接口的鏈接狀態回調函數。

3.5 ETH_link_callback函數

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! ");

}

}

這段代碼是一個用于處理以太網鏈接狀態變化的回調函數 ETH_link_callback。讓我們逐步分析它的功能:

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

2. 如果網絡接口的鏈接狀態為鏈接狀態(通過 netif_is_link_up(netif) 判斷):

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

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

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

- 讀取自動協商結果,根據結果配置以太網MAC的速度和雙工模式。

- 根據速度和雙工模式重新配置以太網MAC控制器的寄存器。

- 重新啟動MAC接口。

- 根據是否啟用了DHCP,設置IP地址、子網掩碼和網關地址,并將網絡接口標記為已啟用。

- 打印消息,表示網絡電纜已連接。

- 將 EthLinkStatus 標記為鏈接狀態。

3. 如果網絡接口的鏈接狀態為斷開狀態,執行以下操作:

- 停止MAC接口。

- 如果啟用了DHCP,將DHCP狀態設置為鏈接斷開,并停止DHCP客戶端。

- 將網絡接口標記為已關閉。

- 打印消息,表示網絡電纜已拔出。

綜上所述,該函數主要用于處理以太網鏈接狀態的變化。根據鏈接狀態的變化,重新啟動自動協商過程(如果啟用了自動協商),配置以太網MAC的參數,并設置IP地址信息。同時,根據鏈接狀態的變化執行相應的動作,例如重新啟動或停止MAC接口,并更新相應的狀態標志。

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

}

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

1.staticuint8_t flagToggle = 0;:定義了一個靜態變量 flagToggle,用于跟蹤網絡連接狀態的變化。

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

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

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

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

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

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

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

在整個函數中,主要處理了TCP、ARP、網絡鏈接狀態和DHCP的周期性任務。這些任務包括定時器的處理以及相應的動作,例如發送ARP請求、更新網絡鏈接狀態和處理DHCP狀態機等。

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網絡堆棧中DHCP過程的函數 LwIP_DHCP_Process_Handle。它通過狀態機來處理DHCP過程的不同階段。讓我們逐步分析其功能:

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

2. 在 DHCP_WAIT_ADDRESS 狀態下,如果DHCP客戶端獲得了IP地址、子網掩碼和網關地址,將狀態切換到 DHCP_ADDRESS_ASSIGNED,打印獲得的IP地址、子網掩碼和網關地址,并停止DHCP客戶端。

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

綜上所述,該函數主要用于處理LwIP網絡堆棧中DHCP過程的不同階段。根據DHCP狀態的不同,執行不同的操作,例如啟動DHCP客戶端、處理獲取到的IP地址信息、處理超時情況等。

4. 實驗現象

1.串口打印相關信息

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

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

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 以太網
    +關注

    關注

    40

    文章

    5458

    瀏覽量

    172326
  • 嵌入式系統
    +關注

    關注

    41

    文章

    3614

    瀏覽量

    129631
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1375

    瀏覽量

    79181
  • DHCP
    +關注

    關注

    0

    文章

    105

    瀏覽量

    19745
  • LwIP
    +關注

    關注

    2

    文章

    88

    瀏覽量

    27286

原文標題:APM32芯得 EP.46 | 增強以太網連接:使用LWIP 2.2實現動態主機配置協議(DHCP)

文章出處:【微信號:geehysemi,微信公眾號:Geehy極海半導體】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何實現以太網功能的,是用F107或F407芯片自己移植Lwip還是采用SPI轉以太網模塊?

    一般大家是如何實現以太網功能的,是用F107或F407芯片自己移植Lwip還是采用SPI轉以太網模塊?
    發表于 05-17 06:49

    基于FPGA的萬兆以太網接口的設計與實現

    基于FPGA的萬兆以太網接口的設計與實現標準中萬兆以太網物理層及媒質接入控制子層的相關協議以 應用物理環境為例,闡述了萬兆以太網接口各個單元模塊的
    發表于 08-11 15:48

    NIOS實現以太網

    基于NIOS2的嵌入式實現以太網通信
    發表于 09-08 12:39

    請問ATK-RM04_WIFI模塊能實現以太網轉WIFI功能嗎?

    ATK-RM04_WIFI模塊能不能實現以太網轉WIFI功能???
    發表于 11-06 01:15

    請問嵌入式系統實現以太網,TCP/IP協議棧是都是移植的嗎?

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

    沒有發現以太網

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

    請教大神怎樣去實現以太網MAC子層協議?

    什么是以太網MAC子層協議?怎樣去實現以太網MAC子層協議?
    發表于 05-06 10:33

    怎么實現以太網的光無線通信系統的設計?

    怎么實現以太網的光無線通信系統的設計?
    發表于 05-28 07:08

    如何利用STM32CubeMX實現FreeRTOS+LAN8720A+LWIP以太網ping通?

    如何利用STM32CubeMX實現FreeRTOS+LAN8720A+LWIP以太網ping通?
    發表于 02-22 07:49

    單片機實現以太網通訊硬件設計

    介紹以太網的幀協議和以太網控制芯片RTL8019AS的結構特性;介紹單片機控制RTL8019AS實現以太網通訊的硬件設計方案;采用c51語言實現RPP協議(地址解析協議),并進行了系統
    發表于 08-29 16:32 ?126次下載
    單片機<b class='flag-5'>實現以太網</b>通訊硬件設計

    ST有關以太網講座課件

    ST公司培訓有關以太網講座課件,包括tcp/ip協議、以太網基礎、Lwip、網卡設計與實現等等介紹
    發表于 03-07 11:50 ?20次下載

    以太網Lwip例程

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

    AT89C52單片機實現以太網接口的控制設計

    隨著互聯網的迅速發展,網絡用戶飛速增長,在使用計算機進行網絡互聯的同時,各種家電設備、儀表設備及工業中數據采集與控制設備也在逐步走向網絡化,基于此結合專用的以太網控制芯片RTL8019學習了利用單片機實現以太網接口的設計。
    發表于 03-03 11:17 ?2855次閱讀
    AT89C52單片機<b class='flag-5'>實現以太網</b>接口的控制設計

    PLC如何實現以太網口無線通訊

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

    Android 9以太網功能移植以及設置IP地址

    基于Android 9實現以太網的IP地址設置和功能實現
    發表于 06-20 14:42 ?2次下載
    主站蜘蛛池模板: 国产精品亚洲高清一区二区| 日韩视频在线观看| 亚洲人成伊人成综合网久久久| 国产亚洲精品线视频在线| 亚洲精品久久久久一区二区三| 久久电影精品| 成3d漫二区三区四区| 亚洲成人免费观看| 恋老视频 国产国佬| 成人小视频在线观看免费| 亚洲AV无码影院在线播放| 伦理片天堂eeuss影院| 超碰98人人插| 亚洲午夜久久久精品影院| 奇米网一区二区三区在线观看| 国产手机在线视频| 97色伦亚洲自偷| 无人区国产片| 男人桶女人j的视频在线观看| 国产精品国产三级国AV在线观看| 竹菊影视一区二区三区| 使劲别停好大好深好爽动态图 | 最近2019中文字幕免费| 日本xxxxxxxxx老师59| 黑人巨大交牲老太| 被滋润的艳妇疯狂呻吟白洁老七| 亚洲成人国产| 欧洲-级毛片内射八十老太婆| 黑人 尺寸 强行害怕 痛哭| 99视频免费在线| 亚洲色噜噜狠狠网站| 日韩欧美一区二区中文字幕| 久久中文字幕亚洲| 国产免费啪嗒啪嗒视频看看| caoporn 超碰免费视频| 亚洲午夜一区二区电影院| 色久久一个亚洲综合网| 男人的天堂黄色片| 久久 这里只精品 免费| 高清mv视频免费观看| 69国产精品成人无码视频|