stm32f429盤盤lwip開發(fā)手冊_第1頁
stm32f429盤盤lwip開發(fā)手冊_第2頁
stm32f429盤盤lwip開發(fā)手冊_第3頁
stm32f429盤盤lwip開發(fā)手冊_第4頁
stm32f429盤盤lwip開發(fā)手冊_第5頁
已閱讀5頁,還剩150頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

淘寶淘寶技術(shù)支持(開源): 。。 →添加朋友 →輸入“正點原子”→關(guān)→添加朋友→輸入“alientek_stm32”→第一章LWIP無操作系統(tǒng)移植第二章LWIP帶操作系統(tǒng)移植RAWTCP客戶端實驗RAWTCP服務(wù)器實驗RAWWebServer實驗第七章NETCONN編程接口簡介第八章NUDP TCP/IP協(xié)議以及LWIP簡 移植準(zhǔn)備工 添加網(wǎng)卡驅(qū)動程 添加中間文 第二章LWIP帶操作系統(tǒng)移 第三章RAW編程接口UDP實 RAW編程接口UDP簡 第四章RAW編程接口TCP客戶端實 第五章RAW編程接口TCP服務(wù)器實 第六章RAW編程接口WEBSERVER實 NETCONNAPI函 第八章NETCONN編程接口UDP實 8.2驗 第九章NETCONN編程接口TCP客戶端實 9.2驗 第十章NETCONN編程接口TCP服務(wù)器實 10.2驗 本章,向大家介紹ALIENETKSTM32F429開發(fā)板以太網(wǎng)接口及其使用層和TCP/IP協(xié)議棧的支持。ALIENTEK板載一顆PHY層。本章主要介紹基本的以太網(wǎng)知識以及LWIP在ALIENTEKSTM32F429開發(fā)板上的移植。本章將分為如下幾個部分:TCP/IPLWIP結(jié)構(gòu),每一層都呼叫它的下一層所提供的協(xié)議來完成自己的需求。通俗而言:TCP負(fù)責(zé)發(fā)現(xiàn)傳IP是給因特網(wǎng)的每一臺聯(lián)網(wǎng)設(shè)備規(guī)定一個地址。分層模型方面來講,TCP/IP由四個層次組成:網(wǎng)絡(luò)接口層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層。OSI是網(wǎng)絡(luò)層(網(wǎng)絡(luò)層、傳輸層(傳輸層、會話層、表示層和應(yīng)用層(應(yīng)用層。TCP/IP模型與OSI模型對比如表1.1.1所示。12345671.1.1TCP/IP模型與OSI在我們的LWIP實驗中PHY層LAN8720相當(dāng)于物理層,STM32F429自帶的MAC層LAN8720是低功耗的10/100M以太網(wǎng)PHY層,I/O引腳電壓符合IEEE802.3-2005準(zhǔn)。LAN8720支持通過RMIIMAC10-BASE-T/100BASE-TX全雙接方式(速度和雙工模式)HPAuto-MDIX自動翻轉(zhuǎn)功能,無需更換網(wǎng)線即可將連接更改為直連或交叉連接。LAN8720的主要特點如下:支持RMIILAN8720的器件管理接口支持非IEEE802.3規(guī)范的中斷功能。當(dāng)一個中斷發(fā)生并且相LAN8720上電或復(fù)位后就工作在主中斷模式,當(dāng)模式控制/狀態(tài)寄存器(十進(jìn)制地址為17)的ALTINT0LAN8720ALTINT1時工作在復(fù)用中斷模式。我們的STM32F429開發(fā)板中并未用到中斷功能,關(guān)于中斷的具體用法可以參考LAN8720的29,30頁。MAC層通過SMI總線對PHY進(jìn)行讀寫操作,SMI可以控制32個PHY,通過不同的PHY地址來對不同的PHY操作。LAN8720通過設(shè)置RXER/PHYAD0引腳來設(shè)置其PHY址,也就是0X00。如表1.1.3所示。我們STM32F429開發(fā)板使用的是REF_CLKOut模式。nINTSEL=1.1.3nINTSEL當(dāng)工作在REF_CLKIn模式時,50MHzLAN8720的引腳上,如圖為了降低成本,LAN872025MHzREF_CLK時鐘。到要使用此功能時應(yīng)工作在REF_CLKOut模式時。當(dāng)工作在REF_CLOOut模式時REF_CLK的時鐘源如圖1.1.3所示。PHYIEEE802.3定義的,一般通過SMIPHY進(jìn)行管理和控制,也就是讀寫PHY內(nèi)部寄存器。PHY50~3132PHY芯不討論這種情況。IEEE802.3定義了0~15這16個寄存器的功能,16~31寄存器由制造商此處使用十進(jìn)制表示:BCR(0),BSR(1),PHY特殊功能寄存器(31)這三個寄存器。位1:PHY的RMII接口電氣981.1.4BCR我們配置LAN8720其實就是配置BCR寄存器,我們通過調(diào)用ST的以太網(wǎng)庫的的讀寫操作。在ST以太網(wǎng)庫的stm32f4xx_hal_conf.h中已經(jīng)定義了BCR和BSR寄存器,/*Section3:CommonPHYRegisters#define/*!<TransceiverBasicControl#define/*!<TransceiverBasicStatusLAN8720初始化的中并沒有看到我們直接操作PHY的寄存器,原因就在這里當(dāng)我們調(diào)用HAL_ETH_Init()函數(shù)以后就會根據(jù)我們輸入的參數(shù)配置LAN8720的相應(yīng)寄存器。位類型0:不支持543211:檢測到j(luò)abber01.1.5BSRBSR寄存器為LAN8720的狀態(tài)寄存器,通過該寄存器的值我們可以得到當(dāng)前的連接次使用到BCR和BSR寄存器。位001:10BASE-T101:10BAST-T010:100BAST-TX/*Section4:ExtendedPHYRegisters#define #define#define/*Section4:ExtendedPHYRegisters#define #define#define通過以上代碼可以看出定義了PHY_SR,PHY_SR中的值與PHY_SPEED_STATUS和站管理接口(SMI)允許應(yīng)用程序通過2條線:時鐘(MDC)和數(shù)據(jù)線(MDIO)任意寄存器。該接口支持多達(dá)32個PHY。應(yīng)用程序可以從32個PHY中選擇一個PHY,然后從任意PHY32個寄存器中選擇一個寄存器,發(fā)送控制數(shù)據(jù)或接收狀態(tài)信息。任意給定時間內(nèi)只能對一個PHYMACPHY進(jìn)行讀寫操作的時候,應(yīng)1.1.7圖1.1.7STM32F429與PHY層連10Mbit/s2.5MHz100Mbit/s25MHz。10Mbit/s2.5MHz100Mbit/s25MHz。精簡介質(zhì)獨立接口(RMII)10/100Mbit/sPHYIEEE802.3u標(biāo)準(zhǔn),MII16個數(shù)據(jù)和控制信號的引腳。RMII規(guī)范將引腳數(shù)減少為7個。STM32F429通過RMII接口與PHY層的連接如圖1.1.8所示。因為RMII相比MII,其100Mbit/s的速度其時鐘頻率應(yīng)為50MHzMII2.5MHZ25MHZ。我們的STM32F429開發(fā)板采用RMII接口連接LAN8720。

圖1.1.8STM32F429通過RMII與PHYLWIP是瑞典計算機(jī)(SICS)的AdamDunkels等開發(fā)的一個小型開源的TCP/IP協(xié)議棧LWIPIP協(xié)議,有無操作系統(tǒng)的支持都可以運行,LWIP實現(xiàn)的重點是在保持TCP協(xié)RAMKBRAM40KROM就可以運行,這使LWIP協(xié)議棧適合在的嵌入式系統(tǒng)中使用。目前LWIP的版本是1.4.1。本采用的就是1.4.1版本的LWIP。關(guān)于LWIP的詳細(xì)信息大家可以去這個去查閱,LWIP的主要特性如下打開從官網(wǎng)上下來的LWIP1.4.1其中包括docsrc和test三個文件夾和5個其他文件。doc文件夾下包含了幾個與協(xié)議棧使用相關(guān)的文本文檔,doc文件夾里面有兩個比較重要的文檔:rawapi.txt和sys_arch.txtrawapi.txt告訴讀者怎么使用raw/callbackAPI進(jìn)行編程,sys_arch.txttestLWIP提供的一些測試程序,這里用不到。打開src源碼文件夾,如圖1.1.10所示。LAN8720通過自協(xié)商確定自身的工作速度以及雙工模式,通過串口打印MAC地址、IP地址、子網(wǎng)掩碼和默認(rèn)網(wǎng)關(guān)等信息。同時DS0提示程序正在運行。這里介紹LAN8720以太網(wǎng)模塊原理圖如圖1.2.1所示,其中上半部分為LAN87201.2.1在本節(jié)和后續(xù)所有有關(guān)LWIP的中需要使用到動態(tài)內(nèi)存管理實驗的知識,因此請讀者務(wù)必了解動態(tài)內(nèi)存管理實驗,此只針對LWIP,不會對其他知識做講解。38內(nèi)存管理實驗作為基礎(chǔ)工程,我們在這個工程的基礎(chǔ)上完成本章的移植過程。本章我們要使用到USMARTUSMART開發(fā)指南實驗15USMART實驗。 網(wǎng) 這兩個文件,如圖所示為我們要的兩個文件。其中l(wèi)wip-1.4.1.zip為LWIP的源碼,contrib-1.4.1.zip包含的一些我們已經(jīng)好了這兩個文件放在光盤中,在軟件資料文件夾下的LWIP學(xué)習(xí)資料文件夾中。目前的版本是1.4.1,本所有的實驗均使用1.4.1版本的LWIP。外以太網(wǎng)庫,因為STD(標(biāo)準(zhǔn)外設(shè)庫)庫沒有集成以太網(wǎng)庫。但是現(xiàn)在我們用的ST的HALHAL庫中集成了以太網(wǎng)庫,以太網(wǎng)庫為:stm32f4xx_hal_eth.c,因此我們就不需要在重新以太網(wǎng)庫了,直接將文件stm你32f4xx_hal_eth.c添加到HALLIB分組中。STM32F429DMA描述符,STM32F429網(wǎng)模塊中的接收/FIFODMADMA描述符ETH_DMARDLAR寄存器和ETH_DMATDLAR寄存器中。圖展示了DMA描述符的兩種結(jié)構(gòu):環(huán)形結(jié)構(gòu)和結(jié)構(gòu),在ST提供的以太網(wǎng)驅(qū)結(jié)構(gòu)的具體描述如圖所示。圖DMA描述符結(jié)圖就是文件stm32f4xx_hal_eth.c中函數(shù)HAL_ETH_DMATxDescListInit2、一個DMAtypedef IO typedef IO }DMA描述符分為增強描述符和常規(guī)描述符,本中我們使用的是常規(guī)描述符,如果ETH_DMADescTypeDef結(jié)構(gòu)體的前四個成員變量,有關(guān)常規(guī)描述符和增強描述符的區(qū)別大家可以參考STM32F4xx中文參考手冊的865869頁。STM32F429的描述符分為發(fā)送描述符和接收描述符,發(fā)送描述符和接收描述符常規(guī)TxDMA存器”并不是STM32F429STM32F4294些“寄存器”也叫做描述符字,描述符字和ETH_DMADescTypeDef這個結(jié)構(gòu)體的關(guān)系如表增強TxDMA1增強TxDMA增強TxDMA增強TxDMATxDMA描述符,常規(guī)RxDMA描述符與之類似。同我們操個位的含意大家可以參考STM32F4xx中文參考手冊的865頁(RxDMA描述符在873頁)。我們前面ST的以太網(wǎng)庫stm32f4xx_hal_eth.c中使用結(jié)構(gòu)的DMA描述符,那么在以太網(wǎng)描述符結(jié)構(gòu)體ETH_DMADescTypeDef中Buffer1Addr就是緩沖區(qū)的地址,Buffer2NextDescAddr就是下一個描述符的地址,如圖所示那樣。在例,我們會在例的lan8720.c文件中定義兩個指向ETH_DMADescTypeDef我們ST以太網(wǎng)驅(qū)動庫stm32f4xx_hal_eth.c中我們采用的是DMA結(jié)構(gòu),但是改為結(jié)構(gòu)。在stm32f4xx_hal_eth.c文件中有兩個函數(shù)HAL_ETH_DMATxDescListInit()和HAL_ETH_DMARxDescListInit,通過這兩個函數(shù)我們就可以將上面兩個指針(或數(shù)組)變?yōu)殒渦int8_tuint8_t我們知道如果采用結(jié)構(gòu)的話ETH_DMADescTypeDefuint8_tuint8_tuint8_tTx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];宏ETH_RXBUFNB和ETH_TXBUFNB上面我們已經(jīng)講過了,ETH_RX_BUF_SIZE和ETH_TX_BUF_SIZE也是兩個宏,在stm32f4xx_hal_conf.h中有定義,它們都為ETH_MAX_PACKET_SIZE,宏ETH_MAX_PACKET_SIZE為1524。為了追蹤Rx/TxDMAETH_HandleTypeDef中定義了兩個非常重要的指針變量,如圖所示。ETH_DMADescTypeDef結(jié)構(gòu)體,在使用中他們兩個分別指向下一個STM32F429DMA描述符講解就完了,關(guān)于DMA描述符的詳細(xì)內(nèi)容大家可以參考STM32F4xx中文參考手冊。LAN8720MACDMALAN8720文件,在這個文件中有l(wèi)an8720.c和lan8720.h這兩個文件,這兩個文件里面包含自己的HARDWARE文件中,并且將lan8720.c和添加到工,如圖所示。lan8720.c中有9個函數(shù),如表所示。 lan8720.c u8{u8macaddress[6];

//速度100M,如果開啟了自協(xié)商模式, //LAN8720地址 //MAC地址 //中斷接收模式 //RMII接口{return }elsereturn }位完成以后就是調(diào)用HAL_ETH_Init()初始化網(wǎng)絡(luò),很簡單的一個函數(shù)。{/*RMII > > > > > > > PCF8574擴(kuò)展 }LAN8720HAL_ETH_ReadPHYRegister()u8{u8speed=((LAN8720_ReadPHY(31)&0x1C)>>2從LAN872031號寄存器中return}void{void{{}}00的時候就調(diào)用lwip_pkt_handle函數(shù)處理接收到的數(shù)據(jù)包,這個函數(shù)我們稍后會做講解,DMA接收中斷標(biāo)志位和DMA總中斷標(biāo)志位。 {u32frameLength=((DMARxDesc->StatusÐ_DMARXDESC_ES)==(uint32_t)RESET)&&{}return}ETH_Mem_Malloc函數(shù)就是為我們前面提到的那四個指針:Rx_Buff、Tx_Buff u8{Rx_Buff=mymalloc(SRAMIN,ETH_RX_BUF_SIZE*ETH_RXBUFNB);//申請內(nèi)存Tx_Buff=mymalloc(SRAMIN,ETH_TX_BUF_SIZE*ETH_TXBUFNB);//申請內(nèi)存{ return1}return }接收中斷服務(wù)函數(shù)ETH_IRQHandler()中調(diào)用了lwip_pkt_handle()函數(shù),而這個函數(shù)沒有在lan8720.c文件中定義,這個錯誤提示不用管,lwip_pkt_handle()函數(shù)后續(xù)會講解。LWIPLWIP協(xié)議深LWIP協(xié)議棧使用pbuf結(jié)構(gòu)體來描述協(xié)議棧使用中的數(shù)據(jù)包,pbuf結(jié)構(gòu)體在pbuf.hstructpbufvoid*payload;u16_ttot_len;

u16_tu16_tlen;u8_ttype;u8_tu16_tpayload:指向該pbuf的數(shù)據(jù)區(qū)的首地址,STM32F407內(nèi)部網(wǎng)絡(luò)模塊接收到數(shù)據(jù),并將數(shù)據(jù)提交給LWIP的時候,就是將數(shù)據(jù)在payload指定的區(qū)中。同樣在發(fā)送數(shù)據(jù)的時候?qū)ayload所指向的區(qū)數(shù)據(jù)轉(zhuǎn)給STM32F429的網(wǎng)絡(luò)模塊去發(fā)送。PBUF_RAMpbuf是通過內(nèi)存堆分配得到的,PBUF_RAMpbufpayload并未指向數(shù)據(jù)區(qū)的起始地址,而是隔了一段區(qū)域,這段區(qū)域就是offset,在里面通常存放TCP報文首部,IP首部、以太網(wǎng)幀首部等等。PBUF_POOLpbuf,PBUF_POOL是通過內(nèi)存池分配的到的,PBUF_POOL類型的pbufpbufpbuf的payload未指向數(shù)據(jù)區(qū)的起始位置,原因同PBUF_RAM一樣,用來存放一些首部的,pbufpbuf結(jié)構(gòu)體中payload字段就指向了數(shù)據(jù)區(qū)的起始位置。

中有定義,定義如下,由于netifnetifnetif.hstructnetifstructnetif*next;ip_addr_tip_addr;ip_addr_tnetmask;ip_addr_tgw;netif_input_fninput;

netif_linkoutput_fnlinkoutput;//底層數(shù)據(jù)包發(fā)送void u16_t u8_t u8_tflags; char u8_t }LWIPnetif結(jié)構(gòu)體組成鏈表來管理這些網(wǎng)絡(luò)接口。ipaddr,netmaskgwIP地址、子網(wǎng)掩碼和默認(rèn)網(wǎng)關(guān)。input:此字段為一個函數(shù),這個函數(shù)將網(wǎng)卡接收到的數(shù)據(jù)交給IP層。outputIP層向接口發(fā)送一個數(shù)據(jù)包時調(diào)用此函數(shù)。這個函數(shù)通常linkoutputARP模塊調(diào)用,完成網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送。上面說的etharp_outputIP數(shù)據(jù)包封裝成以太網(wǎng)數(shù)據(jù)幀以后就會調(diào)用linkoutput函數(shù)將數(shù)據(jù)發(fā)送能,ARP使能等。本節(jié)中LWIP源碼添加到我們的工,我們在工程中新建一個LWIP文件夾,貝到LWIP文件夾下,如圖所示。.c文件添加到工以后,還需要添加LWIP源碼中的頭文件路徑,頭文件路徑按照圖所示添加,這時如果我們編譯的話會有很多錯誤提示,這個不用管。

1LWIPLWIParch如果使用操作系統(tǒng)的話還有臨界代碼區(qū)保護(hù)等等,cc.h文件內(nèi)容如下所示。typedeftypedeftypedeftypedeftypedef#defineSYS_ARCH_UNPROTECT(lev) #ifOS_CRITICAL_METHOD==#define u32_t#define lev=#defineSYS_ARCH_UNPROTECT(lev) #ifdefined(ICCARM)#definePACK_STRUCT_BEGIN#definePACK_STRUCT_STRUCT#definePACK_STRUCT_END#define#elifdefined #definePACK_STRUCT_BEGIN #definePACK_STRUCT_STRUCT#definePACK_STRUCT_END#elifdefined(GNUC)#definePACK_STRUCT_STRUCT ((packed))#definePACK_STRUCT_END#elifdefined(TASKING)#definePACK_STRUCT_BEGIN#definePACK_STRUCT_STRUCT#definePACK_STRUCT_END#defineU16_F"4d"#defineS16_F"4d"#defineX16_F#define#defineU32_F"8ld"#defineS32_F"8ld"#defineX32_F"8lx"#ifndefLWIP_ #defineLWIP_ do\ printf("Assertion\"%s\"failedatline%din%s\r\n",x,LINE,FILE);#ifndef #defineLWIP_ #define #define #defineBYTE_ORDERperf.h是和系統(tǒng)測量與統(tǒng)計相關(guān)的文件,我們不使用任何的測量和統(tǒng)計,因此這個文件中#ifndef#ifndefPERF_H#definePERF_H#definePERF_START#defineu32_t{return}sys_arch.h和sys_arch.c是在使用操作系統(tǒng)的時候才使用到的文件,在這里我們只是在u32_t{return}加相應(yīng)的頭文件路徑,如圖所示。打開我們的網(wǎng)絡(luò)實驗1LWIP無操作系統(tǒng)移植實驗的LWIP文件夾可以發(fā)現(xiàn)有一個文件夾,將這個文件夾到自己工,lwip_app文件夾用來放我們以后所有實驗的代碼。在lwip_app下有一個m文件夾,這個文件中有 m.h和lwipopts.h這三個文件,m.c和m.h是將LWIP源碼和前面的以太網(wǎng)驅(qū)動庫結(jié)合起來的的文件,以后我們想要使用LWIP的什么功能的話就在這個文件中配置就行了。同樣的,我們在工新建一個LWIP_APP分組,并將m.c文件添加到這個分組中并且添加相應(yīng)的頭文件路徑,如圖所示在m.hALIENTEK定義了一個重要的結(jié)構(gòu)體lwip_devtypedeftypedef{u8 u8 u8 u8 u8 vu8 //0,未獲取DHCP地址//1,//1,進(jìn)入DHCP//2,成功獲取DHCP}DHCP狀態(tài)這幾個成員變量。在 m.c中定義了一個lwip_dev結(jié)構(gòu)體類型變量lwipdev,m_default_ip_set(lwip_devm_default_ip_set(lwip_devvoidlwip_pkt_handle(void)voidvoid {u32mempsize; //為ram_heap申請內(nèi)存{ return}return}

m_default_ip_set()函數(shù)用來設(shè)置默認(rèn)地址,我們前面提過lwip_devlwipdev,m_default_ip_set()lwipdevMACMAC32、0、0。后三個字節(jié)我們MAC地址不會重復(fù)就行。IP地址、子網(wǎng)掩碼、默認(rèn)網(wǎng)關(guān)地址可以自行設(shè)置,這里//lwipIP m_default_ip_set(//lwipIP m_default_ip_set(lwip_dev{u32lwipx->mac[3]=(sn0>>16)&0XFF;//低三字節(jié)用STM32IDlwipx->dhcpstatus=0;//沒有} {u8structnetifstructip_addr structip_addr structip_addr if(ETH_Mem_Malloc())return1; m_mem_malloc())return2;//內(nèi)存申請失 {} #ifLWIP_DHCP ipaddr.addr=0;netmask.addr= printf("網(wǎng)卡en的MAC地址 printf("靜 地 #ifLWIP_DHCP //DHCP標(biāo)記為0dhcp_start(&lwip_netif);//開啟DHCP服務(wù){(diào)設(shè)置 }}1ETH_Mem_Malloc()和m_mem_malloc()這兩個函數(shù)完成前面提到的那四個指針和內(nèi)存堆ram_heap和內(nèi)存池memp_memory的內(nèi)存分配。初始化,LAN8720_Init()函數(shù)在LAN8720.c文件中,由ALIENTEK提供。3lwip_initLWIP的內(nèi)核初始化,lwip_init()通過調(diào)用各個模塊的初始化函函數(shù)、IPTCP等的初始化函數(shù),lwip_init()init.c文件中,屬于LWIP源碼。 5、判斷是否使用DHCP,如果使用DHCP的話就通過DHCP服務(wù)來獲取IP地址、子網(wǎng)掩IP地址的話就用m_default_ip_se()函數(shù)設(shè)置的地址6、我們通過netif_add()函數(shù)來完成網(wǎng)卡的,netif_add()在netif.c文件中,此函數(shù)屬于LWIP源碼。netif_add()lwip_netif是我們定義的一個網(wǎng)絡(luò)接口,這個函數(shù)除了使用上面說的IP地址,子網(wǎng)掩碼和默認(rèn)網(wǎng)關(guān)作為參數(shù)外,還使用了兩個函數(shù)地址作為參數(shù):ethernetif_init和ethernet_input,這兩個函數(shù)地址會被賦值給netif結(jié)構(gòu)體的相關(guān)字段,ethernetif_init()ALIENTEK提供,ethernet_input()etharp.c文件中,屬于LWIP源碼,是ARP層數(shù)據(jù)包輸入函數(shù)。7、如果使用DHCPDHCPdhcp_start()DHCPvoid{}當(dāng)程序中調(diào)用m_init()函數(shù)后,網(wǎng)卡就可以工作了。STM32F429內(nèi)部網(wǎng)絡(luò)模塊接void{}可以看出lwip_pkt_handle()函數(shù)其實只是對ethernetif_input()函數(shù)的簡單封裝,通過調(diào)用void{}{{}}LWIPvoid{}{{}}void{//500ms調(diào)用一次{DHCPfineTimer= { }}void{//500ms調(diào)用一次{DHCPfineTimer= { }}//60s執(zhí)行一次DHCP{DHCPcoarseTimer= }}void{{case0: //開啟DHCPprintf("正在查找DHCP服務(wù)器,請稍 case { { //DHCP獲取到的子網(wǎng)掩碼地址 {//使用靜態(tài)IP地址 }}default:}}DHCP完成以后讓dhcpstatus=2,表示DHCP成功。但是當(dāng)DHCP重試次數(shù)大于并且使用靜態(tài)IP地址。打開我們的網(wǎng)絡(luò)實驗1LWIP無操作系統(tǒng)移植實驗,路徑:碼中是不存在的,這個文件由ALIENTEK提供,將ethernetif.h文件到自己工程的相應(yīng)位置,如圖所示。

ethernetif.h//ethernetif_init()調(diào)用用于初始化硬件 static//ethernetif_init()調(diào)用用于初始化硬件 staticerr_tlow_level_init(structnetif我們按路徑:lwip-1.4.1->src->core可以發(fā)現(xiàn)在core文件下有一個sys.clwip-1.4.1->src->include->lwipsys.h文件。sys.csys.h這兩個文件和我們的SYSTEM文件中的sys.c和sys.h重名,因此LWIP中sys.c和sys.h改為lwip_sys.c和lwip_sys.h,然后在工將LWIP源碼里面的#include“sys.h”代碼也要改掉,更改為#includestaticerr_tlow_level_init(structnetifstaticstaticerr_tlow_level_init(structnetifstaticerr_tlow_level_output(structnetif*netif,structpbuf*p)staticstructpbuf*low_level_input(structnetif*netif)符鏈表的初始化,硬件幀校驗的開啟并且打開以太網(wǎng)。low_level_init函數(shù)如下:{{netif->mtu=1500;最大允許傳輸單元,允許該網(wǎng)卡廣播和ARPnetif->flags=NETIF_FLAG_BROADCAST|\;HAL_ETH_Start(Ð_Handler);MAC和DMAreturnERR_OK;} staticerr_tlow_level_output(structnetif*netif,structpbuf{err_terrval;IOETH_DMADescTypeDef*DmaTxDesc;uint32_tframelength=0;uint32_tbufferoffset=0;uint32_tpayloadoffset=0;bufferoffset=0;{{goto } {{errval=goto } }}errval=ERR_OK;{}return}staticstructpbuf*low_level_input(structstaticstructpbuf*low_level_input(structnetif{structpbuf*p=NULL;structpbuf*q;uint16_tlen;uint32_tbufferoffset=0;uint32_tpayloadoffset=0;uint32_ti=0; returnNULL; buffer=(uint8_t*)ETH_Handler.RxFrameInfos.buffer; {//pbufbufferoffset=0;{{//buffer地址,指向新的接收描述符的RxBufferbuffer=(uint8_t*)(dmarxdesc->Buffer1Addr);}}}//釋放DMA描述符{ //標(biāo)記描述符歸DMA}= {//寫入任意一個值來喚醒RxDMA}}return} {err_terr; { p=}return} {#if //初始化變量netif的name字段 netif->output=etharp_output;//IP層發(fā)送數(shù)據(jù)包函數(shù) returnERR_OK; mem.cmemp.c將這兩個數(shù)組改用ALIENTEK的內(nèi)存分配函數(shù)對其進(jìn)行內(nèi)存分配。在mem.c文件中ram_heap數(shù)組注銷掉,定義為指向u8_t的指針,如圖所示。ram_heap數(shù)組改為指針(mem.c文件中memp_memory數(shù)組改為指針(memp.c文件中u32_t{#includereturn}u32_t{#includereturn}圖 #define #define#defineNO_SYS#define0 //不使用UCOS4#define #define #define#defineNO_SYS#define0 //不使用UCOS4#define #define #defineMEMP_NUM_UDP_PCB #define 的TCP連接數(shù)#define #define Pbuf#define #definePBUF_POOL_BUFSIZE TCP選 #define #define #defineTCP_QUEUE_OOSEQ #define (1500 //TCP_MSSMTUIPTCP//TCP發(fā)送緩沖區(qū)大小#define //(2*#define (2*#define /*----------ICMP選 #define /*----------DHCP選 //當(dāng)使用DHCP時此位應(yīng)該為1,LwIP0.5.1版本中沒有DHCP服務(wù).#defineLWIP_DHCP UDP選 #define #define /*----------Statistics //#ifdef#define :#define #define :#define :#define //CHECKSUM_CHECK_TCP==0:硬件檢查輸入的TCP#define #defineCHECKSUM_GEN_ICMP #define CHECKSUM_GEN_UDP==1:軟件生成UDOP#define #define :#define :#define //CHECKSUM_CHECK_TCP==1:軟件檢查輸入的TCP#define #defineLWIP_NETCONN //LWIP_SOCKET==1:使能SocketAPI(要求使用sockets.c)#defineLWIP_SOCKET #define 1//通過定義LWIP_SO_RCVTIMEO//#define #define 需求來編寫lwipopts.h里面的內(nèi)容經(jīng)過上面幾節(jié)的講解,LWIPmian.c文件來測試int{u16int{u16POINT_COLOR=//HAL//初始化LCD_ShowString(30,50,200,16,16,"EthernetlwIPest");{LCD_ShowString(30,110,200,20,16,"LWIPInitFalied!"); } #if {} {{}}} 獲取地址失敗的話將使用我們的默認(rèn)的地址,最后我們在一個while循環(huán)中循環(huán)調(diào)用lwip_periodic_handle()main函數(shù)中我們要注意到不管是在等待DHCP完成還是DHCPlwip_periodic_handle()函數(shù),因為在這個函數(shù)中周期性調(diào)用協(xié)議棧內(nèi)核的一些定時函數(shù)以滿足LWIP的內(nèi)核要求。通過USMART組件就可以或者改寫LAN8720內(nèi)部寄存器的配置,這是非常好的一種調(diào)試網(wǎng)絡(luò)的方法。這里我們要用到lan8720.c中的讀寫PHY的函數(shù):LAN8720_ReadPHY()和LAN8720_WritePHY(),這兩個函數(shù)添加到usmart_config.c文件中的usmart_nametab[]數(shù)是沒有使用,這兩個Warning我們不用管他。在代碼編譯成功以后,我們代碼到開發(fā)板中,通過網(wǎng)線連接開發(fā)板到路由器上,如以連接電腦RJ45RJ45接口上那么開發(fā)板就不能使用DHCP功能,需要使用靜態(tài)地址,我們例的默認(rèn)靜態(tài)IP地址:0,子網(wǎng)掩腦的網(wǎng)絡(luò)設(shè)置,步驟如下,此處以WIN7系統(tǒng)為例。1.5.3圖1.5.4本地連 框圖1.5.5本地連接屬 IPIP地址在一個網(wǎng)絡(luò)內(nèi)!以后我們的實驗都是連接到路由器上的,如果沒有路由器的話都可以使用上面這種方法這種方法完成實驗,只是不能使用DHCP服務(wù)。打開串口調(diào)試助手,復(fù)位一下開發(fā)板。這里我們開啟了DHCP關(guān)閉DHCP使用靜態(tài)IP地址,完成后LCD顯示如圖1.5.7所示1.5.7LCD1.5.8可以看到此時通過路由器的DHCP分配到的IP地址為:49,默認(rèn)網(wǎng)關(guān)為:,子網(wǎng)掩碼為:。在電腦上開發(fā)板的IP地址,結(jié)果如圖1.5.9所圖1.5.9測(這里以我們的串口調(diào)試助手為例)打印出USMART支持的函數(shù),如圖1.5.10所示,從圖中可以看出函數(shù)有6個函數(shù),其中就有我們前面添加過的LAN8720_ReadPHY()和LAN8720_WritePHY()這兩個函數(shù)。們使用LAN8720_ReadPHY()函數(shù)測試。這里我們LAN8720的寄存器31,也就是特殊功能寄存器,所以串口調(diào)試助手發(fā)送框輸入LAN8720_ReadPHY(31),點擊發(fā)送,我們就可以看此時LAN8720的值為0X1058。圖1.5.11LAN8720寄存器31的bit2-4代表著網(wǎng)絡(luò)的連接速度和雙工狀態(tài),可以看出“110100M全用LAN8720_WritePHY()函數(shù)改寫某些寄存器的值。第二章LWIPrawAPI,raw編程難度很大,需LWIPLWIPLWIPUCOS的LWIP移植。本章的移植是面無操作系統(tǒng)的基礎(chǔ)上修改的,本章不講解UCOS的移植,關(guān)于UCOS的移植請大家參考我們的《STM32F429UCOS開發(fā)手冊》。我們只需要對lwipopts.h要實現(xiàn)的宏定義和函數(shù)如表2.1.1所示。2.1.1hd2.1.1中可以看出,sys_arch.c中要實現(xiàn)的主要是與消息郵箱、信號量和創(chuàng)建進(jìn)程有關(guān)sys_thread_new函數(shù)創(chuàng)建一個進(jìn)程,因此這個函數(shù)必須實現(xiàn),實現(xiàn)過程也是對UCOS中的進(jìn)程創(chuàng)建函數(shù)做簡單的封裝。cc.h#ifOS_CRITICAL_METHOD==1#define#define#ifOS_CRITICAL_METHOD==1#define#define #defineSYS_ARCH_UNPROTECT(lev) #ifOS_CRITICAL_METHOD==#defineu32_t#definelev=2.1.1includes.h頭文件(cc.h文件中我們lwipopts.h是用來裁剪和配置LWIP的,那么我們要使用操作系統(tǒng)的話就需要 #define #define #ifndef#define5 #define2#defineSYS_LIGHTWEIGHT_PROT#defineNO_SYS #defineMEM_ALIGNMENT //使用4字節(jié)對齊模式#defineMEM_SIZE 16000//內(nèi)存堆heap大小 #define #defineMEMP_NUM_UDP_PCB #define 的TCP連接數(shù)#define #define #define #define#define1#define#undef#defineTCP_QUEUE_OOSEQ #undef//tcpip創(chuàng)建主 #define #undef#define #undef#define //TCP分段,TCP_MSSMTUIPTCP#define (1500-#define //最小為(2*#define (2*#define#define1#define1#define1#define#ifdefCHECKSUM_BY_HARDWARE#define :#define #define :#define :#define //CHECKSUM_CHECK_TCP==0:硬件檢查輸入的TCP#define #defineCHECKSUM_GEN_ICMP #define CHECKSUM_GEN_UDP==1:軟件生成UDOP#define #define :#define :#define //CHECKSUM_CHECK_TCP==1:軟件檢查輸入的TCP#define#define1#define #define#define1LWIP_SOCKET==1:使能SicketAPI( #define #define#defineDEFAULT_UDP_RECVMBOX_SIZE#defineDEFAULT_THREAD_STACKSIZE#define01、因為我們要使用UCOSII系統(tǒng),所以NO_SYS02LWIP3、如果使用NETCONNLWIP_NETCONN1上面只是我們列舉的一小部分配置,使用UCOS的話還需要很多的配置,具體配置大家參考我們的lwipopts.h文件。這里就不一一解釋了。sys_arch.h#ifndefARCH_SYS_ARCH_H#defineARCH_SYS_ARCH_H#include<includes.h>#include"arch/cc.h"#include"includes.h"#defineSYS_ARCH_EXT中數(shù)據(jù)類型:sys_sem_t、sys_mutex_t、sys_mbox_tsys_thread_t。分別為信號量、互斥信號#ifndefARCH_SYS_ARCH_H#defineARCH_SYS_ARCH_H#include<includes.h>#include"arch/cc.h"#include"includes.h"#defineSYS_ARCH_EXT#define#definetypedefstruct }TQ_DESCR,typedefOS_EVENT typedefOS_EVENT typedefPQ_DESCR typedefINT8Usys_thread_t; 3)sys_arch.c err_tsys_mbox_new(sys_mbox_t*mbox,int{(*mbox)=mymalloc(SRAMIN,sizeof(TQ_DESCR));//為消息郵箱申請內(nèi)存 //清除mbox的內(nèi)存{if((*mbox)->pQ!=NULL)returnERR_OK;{ return }}elsereturn }void (sys_mbox_t*{u8_tsys_mbox_t }{//msgmsg等于pvNullPointer} err_tsys_mbox_trypost(sys_mbox_t*mbox,void{//msgmsg等于pvNullPointerreturnERR_OK;} u32_tsys_arch_mbox_fetch(sys_mbox_t*mbox,void**msg,u32_t{u8_tvoid*temp;{//轉(zhuǎn)換為節(jié)拍數(shù),UCOS延時使用的是節(jié)拍數(shù),而LWIPms}elseucos_timeout=//請求消息隊列,等待時限為ucos_timeout{else*msg=temp;} {if(timeout_new>timeout)timeout_new=timeout_new-timeout;elsetimeout_new=0xffffffff-timeout+timeout_new;timeout=timeout_new*1000/OS_TICKS_PER_SEC+1;}return}u32_tsys_arch_mbox_tryfetch(sys_mbox_t*mbox,void{}} {u8_tucErr;intOS_Q_DATAq_data;ucErr=OSQQuery(m_box->pQ,&q_data);returnret;}{}這里我們對sys_arch_mbox_fetch()函數(shù)做一下簡單的講解,根據(jù)LWIP協(xié)議棧要求當(dāng)sys_arch_mbox_fetch()timeout0時需要我們返回等待消息所使用的時間(ms),UCOSIIOSQPend()函數(shù)并沒有這個功能,因此需要我們自行實現(xiàn)。因為在timeoutUCOS使用的節(jié)拍數(shù)。為了記錄等待消息時用的此最后要將這個系統(tǒng)節(jié)拍數(shù)轉(zhuǎn)化為ms,并返回該值。如果等待消息超時的話就直接返回 err_t err_tsys_sem_new(sys_sem_t*sem,u8_t{u8_tif(*sem==NULL)returnERR_MEM;OSEventNameSet(*sem,"LWIPSem",&err);returnERR_OK;} ,{u8_t {//轉(zhuǎn)換為節(jié)拍數(shù),UCOS延時使用的是節(jié)拍數(shù),而LWIPmsucos_timeout=(timeout*OS_TICKS_PER_SEC)/1000;if(ucos_timeout<1)ucos_timeout=}elseucos_timeout=0;timeout={timeout_new=if(timeout_new>=timeout)timeout_new=timeout_new-timeout;elsetimeout_new=0xffffffff-timeout+timeout_new;}return}{}voidvoid {u8_tucErr;*sem=} {OS_SEM_DATA}{}sys_arch_sem_wait函數(shù)為等待信號量函數(shù),和sys_arch_mbox_fetch函數(shù)一樣,sys_arch_sem_wait()函數(shù)也要返回待信號量所用的時間,這里我們的處理方法和sys_thread_tsys_thread_new(constchar*name,lwip_thread_fnthread,void*arg,intstacksize,sys_thread_tsys_thread_new(constchar*name,lwip_thread_fnthread,void*arg,intstacksize,int{{{ //創(chuàng)建TCPIP內(nèi)核任務(wù) }return}然后將其轉(zhuǎn)換為LWIP使用的ms,并返回這個時間值。 {structnetifstructip_addr structip_addr structip_addrgw; if(ETH_Mem_Malloc())return1; {} #ifipaddr.addr=netmask.addr=printf("網(wǎng)卡en的MAC地址 {設(shè)置 }}在這里使用了tcpip_init()來初始化LWIP內(nèi)核,我們查看tcpip_init()函數(shù)可以看出其實在tcpip_init()lwip_init()netif_add()函數(shù),與前面不同的是,這里將netif_add函數(shù)最后一個參數(shù)改為函數(shù)tcpip_input()。 行完成后就刪除掉這個任務(wù)。關(guān)于DHCP有三個函數(shù): m_dhcp_creat、m_dhcp_delete和lwip_dhcp_task。前兩個函數(shù)比較好理解,就是建立和刪除DHCP任務(wù),lwip_dhcp_taskDHCP{u32ip=0,netmask=0,gw=0; printf("正在查找DHCP服務(wù)器,請稍 {printf("正在獲取地址..\r\n"); { //DHCP獲取到的子網(wǎng)掩碼地址 }}m_dhcp_delete();//刪除DHCP}lwipdevdhcpstatusDHCP表示DHCP失敗,并且使用靜態(tài)IP地址。注意最后在DHCP任務(wù)執(zhí)行完成后調(diào)用m_dhcp_delete()DHCPint{int{ //初始化HAL庫 // //初始化PCF8574 my_mem_init(SRAMCCM);//初始化CCM內(nèi)存池POINT_COLOR=RED; LCD_ShowString(30,50,200,20,16,"LWIP+UCOSIITest"); {{ }LCD_ShowString(30,110,200,20,16,"LwipInitSuccess!"); OSStart開啟} {pdata=pdata;#if{pdata=pdata;#if }在代碼編譯成功之后,我們代碼到STM32F429開發(fā)板上,這里我們開啟了DHCP,這是串口調(diào)試助手上顯示如圖2.4.2所示。2.4.1LCD2.4.2可以看到此時通過路由器的DHCP分配到的IP地址為:49,默認(rèn)網(wǎng)關(guān)為:,子網(wǎng)掩碼為:。在電腦上開發(fā)板的IP地址,結(jié)果如圖2.4.3所圖2.4.2測第三章RAWUDPUDPTCP/IPTCP協(xié)議。UDP不提供數(shù)據(jù)包分組、組裝,不能對數(shù)據(jù)包進(jìn)頻和普通數(shù)據(jù)傳輸時使用UDP較多。UDP數(shù)據(jù)報結(jié)構(gòu)如圖3.1.1所示。端表示發(fā)送和接收進(jìn)程,UDP協(xié)議使用端為不同的應(yīng)用保留各自的數(shù)據(jù)傳輸通,UDP和TCP協(xié)議都是采用端對同一時刻內(nèi)多項應(yīng)用同時發(fā)送和接收數(shù)據(jù),而數(shù)據(jù)接收方則通過目標(biāo)端口接收數(shù)據(jù)。有的網(wǎng)絡(luò)應(yīng)用只能使用預(yù)先為其預(yù)留或的靜態(tài)端口;而另外一的有效范圍是從0到65535。一般來說,大于49151的端都代表動態(tài)端口。的不同而各異。從理論上說,包含報頭在內(nèi)的數(shù)據(jù)報的最大長度為65535字節(jié)。法計算得出,在傳遞到接收方之后,還需要再重新計算。如果某個數(shù)據(jù)報在傳輸過被第三LWIP的源碼做了非常詳細(xì)的講解,想要研究LWIP源碼的這本書,不過這本書中采LWIP中RAWAPIUDPLWIP的RAWAPI編程方式是基于回調(diào)機(jī)制的,當(dāng)我們初始化應(yīng)用的時候須為內(nèi)UDP的PCB通過一個PCB3.1.1UDP的RAWAPI不一一列舉,關(guān)于UDP的其他函數(shù)大家可以參考udp.c文件。PCUDP協(xié)議連接起來,PC端使用網(wǎng)發(fā)板上的按鍵發(fā)送數(shù)據(jù)給PCudp_demo.c和udp_demo.h,這udp_demo.c這個文件,在這個文件中我們有5個函數(shù),如表3.2.1所示。我們首先看一下void{u8*tbuf;u16xoff;u8key;LCD_ShowString(30,50,200,16,16,"UDPTest");LCD_ShowString(30,70,200,16,16,"RemoteIPSet"); lwipdev.remoteip[2]);//遠(yuǎn)端IP{elseif(key){if(key==KEY0_PRES)lwipdev.remoteip[3]++;//IP增加if(key==KEY2_PRES)lwipdev.remoteip[3]--;//IP減少}} }KEY0KEY2IPif(p!=NULL)//{ //遍歷完整個pbuf鏈表{if(q->lenUDP_DEMO_RX_BUFSIZE-data_len))data_lenif(p!=NULL)//{ //遍歷完整個pbuf鏈表{if(q->lenUDP_DEMO_RX_BUFSIZE-data_len))data_len+=q-{ udp_demo_flag&=~(1<<5); POINT_COLOR=RED;}lwipdev.remoteip[1]=(upcb->remote_ip.addr>>8)&0xff;//IADDR3lwipdev.remoteip[2]=(upcb->remote_ip.addr>>16)&0xff;//IADDR2lwipdev.remoteip[3]=(upcb->remote_ip.addr>>24)&0xff;//IADDR1udp_demo_flag|=1<<6;//標(biāo)記接收到數(shù)據(jù)了pbuf_(p);//}udp_demo_recvbuf。LWIP在接收數(shù)據(jù)的時候會通過pbuf_alloc()函數(shù)來申請內(nèi)存,申請到的內(nèi)組中。最后我們記錄下遠(yuǎn)端主機(jī)的IP地址和端,標(biāo)記接收到數(shù)據(jù)。tcp_demo_sendbuftcp_demo_sendbufptr字段,然后調(diào)用voidudp_demo_senddata(structudp_pcb{structpbuf{ //udp發(fā)送數(shù)據(jù) }}udp_demo_connection_close()UDP連接的,這個函數(shù)很簡單,通過調(diào)用函LCD_ShowString(30,50,200,16,16,"UDPLCD_ShowString(30,50,200,16,16,"UDPTest");}最后我們重點介紹一下udp_demo_test(){//UDP客戶端連接到指定IP地址和端 {//UDP客戶端連接到指定IP地址和端 {if(err==ERR_OK)//{ udp_demo_flag|=1<<5; }else}else}elseres=1;{{}{}{}}1。4、綁定成功以后使用udp_recv()函數(shù)UDP的接收函數(shù),并且置位udp_demo_flag的的話令res等1。6whileKWY_UP鍵的時候退出循環(huán),接收到數(shù)據(jù)的時候就在LCD上顯示接收到的數(shù)據(jù)。個函數(shù)那么LWIP的內(nèi)核就不能運行,那么網(wǎng)絡(luò)肯定不會工作!至此,udp_demo.c文件就講完了,接下來就是編寫main函數(shù),main函數(shù)相對來說簡單一點,mian函數(shù)代碼如下。int{u8key;

//初始化POINT_COLOR=RED;{LCD_ShowString(30,110,200,20,16,"LWIPInitFalied!"); } #if{} //TCP{ {if((udp_demo_flag&1<<5))printf("UDP連接已經(jīng)建立,不能重復(fù)連接\r\n");elseudp_demo_test(); //當(dāng)斷開連接后,調(diào)用udp_demo_test()函數(shù)}}main函數(shù)一開始完成外設(shè)的初始化,如果開啟DHCPDHCPIP地址,IP地udp_demo_test()UDPudp_demo_test()函數(shù)while()KEY1按下并且UDPudp_demo_test()函數(shù)重新開始UDP實驗。3.3驗完代碼后,打開網(wǎng)絡(luò)調(diào)試助手,等待開發(fā)板的LCD3.3.7所示界面,在這個KEY_UP確認(rèn),確認(rèn)完了以后LCD就如圖3.3.8所示的數(shù)據(jù)接收界面。圖 遠(yuǎn)端IP地址設(shè) 圖3.3.8數(shù)據(jù)接收界網(wǎng)絡(luò)調(diào)試助手如圖3.3.9所示,3.3.9 ApolloSTM32F4/F7UDPdemosenddata。3.3.10UDP第四章RAWTCPRAW編程接口TCPRAW編程接口TCPTCPIPTCPTCP層發(fā)送用于網(wǎng)間傳輸通常受該計算機(jī)連接的網(wǎng)絡(luò)的數(shù)據(jù)鏈路層的最大傳送單元(MTU)限制。之后TCP把數(shù)據(jù)包傳給IP層,由它來通過網(wǎng)絡(luò)將包傳送給接收端的TCP層。TCP為了保證報文傳輸?shù)目煽?,就給每個包一個序號,同時序號也保證了傳送到接收端的在數(shù)據(jù)正確性與上,TCP用一個校驗和函數(shù)來檢驗數(shù)據(jù)是否有錯誤,在發(fā)送和接收動窗口協(xié)議,協(xié)議中規(guī)定,對于窗口內(nèi)TCP擁TCP個值加上IP首部中的源IP地址和目的IP地址唯一確定一個TCP連接。TCPTCP接收端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個報文ISN(InitialSequenceNumber),當(dāng)連接建立好以后發(fā)送方要發(fā)送的第一個字節(jié)序號為ISN+1。ACK1的時候才有用,確認(rèn)號中包含發(fā)送確認(rèn)的一方所期望收到的32bit4字節(jié)為單位,4bitTCP60字節(jié)的首部,如果沒有任何的選項字段,正常的首部長度是20字節(jié)。TCP16bit6553516UDP的校驗和的計算過程和原理相同,這是一個強制性的字段,校驗和覆蓋了整個TCP報文段:TCP首部和TCP數(shù)據(jù)。URG1時有效,緊急指針是一個正的偏移量,和序號字段中的值相加LWIP中RAWAPITCPtcp.c、tcp.h、tcp_in.ctcp_out.cLWIPTCP協(xié)議的文件,TCP4.1.3API創(chuàng)建一個TCP的PCBTCP的PCBIP地址和端開始TCP的PCB發(fā)送TCP數(shù)接收TCP數(shù)用關(guān)閉一個TCP中斷TCP

LWIP中關(guān)于TCP的函數(shù),本節(jié)中我們就用這幾個函數(shù)編寫我們本章的例程,本章實驗的目標(biāo)是PC端和開發(fā)板通過TCP協(xié)議連接起來,開發(fā)板做TCP客戶端,PCLCD上顯文件tcp__demo.c和tcp__demo.h。tcp_ tcp_ tcp_tcp_tcp_tcp_ tcp_關(guān)閉TCPerr_terr_t _connected(void*arg,structtcp_pcb*tpcb,err_t{structtcp_ {es=(struct //{ //estpcb//LwIPtcp_sent//LwIPtcp_poll{ }{ }return} TCP控制塊中相關(guān)字段的回調(diào)函數(shù),這樣當(dāng)有 {_recv(void*arg,structtcp_pcb*tpcb,structpbuf*p,err_tcp__e函數(shù)是當(dāng)接收到數(shù)據(jù)時的回調(diào)函數(shù),在這個函數(shù)中我們根據(jù)不同的狀態(tài)有歷的buf到cp__cbuf和c__{_recv(void*arg,structtcp_pcb*tpcb,structpbuf*p,err_tstructpbuf*q;structtcp_ err_tret_err; { ={ }elseif(es {{ //遍歷完整個pbuf鏈表{ _recvbuf+data_len,q->payload,\ elsememcpy(tcp_ data_len+=q->len; //} } { }return} err_t {err_tstructtcp_ {err_t {err_tstructtcp_ { pbuf {}return}以后記得將_flagtcp__poll()函數(shù)為控制塊中poll字段的回調(diào)函數(shù),這個函數(shù)會被周期調(diào)用,因此我們tcp__connection_close()斷開與服務(wù)器的連{{err_tstructtcp_ _struct*es;es=(structtcp_ { //關(guān)閉TCP}returnret_err;} err_ttcp_ _sent(void*arg,structtcp_pcb*tpcb,u16_tlen){structtcp_ _struct*es; returnERR_OK;}voidvoid{_senddata(structtcp_pcb*tpcb,struct_struct*structpbuferr_t{{ //pbufref// }} tcp__connection_close()函數(shù)的功能是關(guān)閉與服務(wù)器的連接,通過調(diào)用tcp_abort()函數(shù)void{_connection_close(structtcp_pcb*tpcb,struct }這個函數(shù)和我們上一章講的udp_demo_test()函數(shù)功能類似。首先我們通過調(diào)用tcppcb=tcp_new();tcppcb=tcp_new();//創(chuàng)建一個新的 {}elseres=1;{{}{ }{ }else {}{if({tcppcb=tcp_new();//創(chuàng)建一個新的 {//連接到目的地址的指定端口上,當(dāng)連接成功后回調(diào)tcp_ }}}_connection_close(tcppcb,0);//關(guān)閉腦發(fā)送數(shù)據(jù)。通過判斷tcp__flag的bit6來確定是否接收到數(shù)據(jù),如果接收到數(shù)據(jù)的話就intint{u8key;POINT_COLOR=RED;//初始化{LCD_ShowString(30,110,200,20,16,"LWIPInitFalied!"); } #if{} {key=KEY_Scan(0);key=KEY_Scan(0);{else//當(dāng)斷開連接后,}}}4.3驗在代碼編譯成功以后,我們代碼到開發(fā)板中,通過網(wǎng)線連接開發(fā)板到路由器上,如果打開網(wǎng)絡(luò)調(diào)試助手軟件設(shè)置為如圖4.3.1所示。4.3.1Connected的時候就可以和網(wǎng)絡(luò)調(diào)試助手互相發(fā)送數(shù)據(jù)了。 圖4.3.2設(shè)置服務(wù)器IP地 圖4.3.3連接到服務(wù) ,此時開發(fā)板LCD上顯示接收到的數(shù)據(jù)如圖4.3.4所示,按下KEY0鍵向網(wǎng)絡(luò)調(diào)試助手發(fā)送數(shù)據(jù),網(wǎng)絡(luò)調(diào)試助手接收到數(shù)據(jù)如圖4.3.5所示。圖 4.3.5第五章RAWTCPRAW編程接口TCPRAW編程接口TCP寫我們本章的例程,本章實驗的目標(biāo)是PC端和開發(fā)板通過TCP協(xié)議連接起來,開發(fā)板做TCPPC。本章實驗中我們主要有兩個文件tcp_server_demo.c和tcp_server_demo.h。tcp_server_demo.c文件中我們一共定義了10個函數(shù),如表5.2.1所示。關(guān)閉TCP{err_tstructtcp_server_struct*es;if(es!=NULL)//內(nèi)存分配成功{ ////TCPServer主動斷開時的timewaitvoidtcp_server_remove_timewait(void){ //初始化tcp_err()回調(diào)函數(shù) //初始化tcp_poll回調(diào)函數(shù) return}tcp_server_error()TCP客戶端實驗中我們沒有實tcp_server_usersent(),tcp_server_poll(),tcp_server_sent()和tcp_server_senddata()這三個函數(shù)分別和上一章TCP客戶端實驗中的tcp__poll(),tcp__sent()和tcp__senddata()函數(shù)功能類似,大家可以參考TCP客戶端實驗中關(guān)于這三個函數(shù)的講解。tcp_server_flagbit5voidtcp_server_flagbit5voidtcp_server_connection_close(structtcp_pcb*tpcb,structtcp_server_struct{ }最后一個函數(shù)是tcp_server_remove_timewait()這個函數(shù)用來強制刪除處于TIME-WATI狀態(tài)structtcp_pcb*pcb,*pcb2;structtcp_pcb*pcb,*pcb2;{}{ }}接下來是很實驗最重要的函數(shù):tcp_server_test()UDP實驗和TCPtcppcbnew=tcp_new();// {tcppcbnew=tcp_new();

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論