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

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

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

有線網(wǎng)絡(luò)通信實驗1之LWIP移植

汽車電子技術(shù) ? 來源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-03-01 14:30 ? 次閱讀

24.1 DM9000概述

DM9000是一款完全集成的、性價比高、引腳數(shù)少、帶有通用處理器接口的單芯片快速以太網(wǎng)控制器。一個10/100MPHY和4K雙字的SRAM,它是出于低功耗和高性能目的設(shè)計的,其IO端口支持3.3V與5V電壓。DM9000為適應(yīng)各種處理器提供了8位、16位數(shù)據(jù)接口訪問內(nèi)部存儲器。DM9000協(xié)議層接口完全支持使用10Mbps下3類、4類、5類非屏蔽雙絞線和100Mbps下5類非屏蔽雙絞線,這是完全遵照IEEE802.3u標(biāo)準(zhǔn)。它的自動協(xié)商功能將自動完成DM9000配置以使其發(fā)揮出最佳性能,它還支持IEEE802.3x全雙工流量控制,DM9000的特性如下:

(1)支持處理器接口:I/O口的字節(jié)或字命令對內(nèi)部存儲器進(jìn)行讀寫操作

(2)集成自適應(yīng)(AUTO-MDIX)10/100M收發(fā)器

(3)半雙工模式流量控制的背壓模式

(4)IEEE802.3x全雙工模式的流量控制

(5)支持喚醒幀,鏈路狀態(tài)改變和遠(yuǎn)程喚醒

(6)內(nèi)置16K字節(jié)SRAM

(7)內(nèi)置3.3V至2.5V的調(diào)節(jié)器

(8)支持IP/TCP/UDP的校驗和生成以及校驗支持MAC接口

(9)支持自動加載EEPROM里面生產(chǎn)商ID和產(chǎn)品ID

(10)可選EEPROM配置

(11)超低功耗模式

A.功率降低模式(電纜偵測)

B.掉電模式

C.可選擇1:1或1.25:1變壓比例降低額外功率

(12)兼容3.3V和5.0V輸入輸出電壓

DM9000的結(jié)構(gòu)框圖如下圖所示。

圖片

1、DM9000中斷引腳電平設(shè)置

DM9000的INT引腳為中斷輸出引腳,默認(rèn)情況下該引腳高電平有效。可以通過設(shè)置DM9000的EECK引腳來改變INT的有效電平,當(dāng)EECK拉高以后,INT低電平有效,否則的話INT是高電平有效的。

2、DM9000數(shù)據(jù)位寬設(shè)置

DM9000支持8位和16位兩種數(shù)據(jù)位寬,可以通過DM9000的EECS引腳設(shè)置其數(shù)據(jù)位寬,當(dāng)EECS上拉的時候DM9000選擇8位數(shù)據(jù)位寬,否則的話選擇16位數(shù)據(jù)位寬。一般設(shè)置默認(rèn)位寬為16位。

3、DM9000直接內(nèi)存訪問控制DMAC

DM9000支持DMA方式以簡化對內(nèi)部存儲器的訪問。在我們編程寫好內(nèi)部存儲器地址后,就可以用一個讀/寫命令偽指令把當(dāng)前數(shù)據(jù)加載到內(nèi)部數(shù)據(jù)緩沖區(qū),這樣,內(nèi)部存儲器指定位置就可以被讀/寫命令寄存器訪問。存儲器地址將會自動增加,增加的大小與當(dāng)前總線操作模式相同(8-bit或16-bit),接著下一個地址數(shù)據(jù)將會自動加載到內(nèi)部數(shù)據(jù)緩沖區(qū)。內(nèi)部存儲器空間大小為16K字節(jié)。前3K字節(jié)單元用作發(fā)送包的緩沖區(qū),其他13K字節(jié)用作接收包的緩沖區(qū)。所以在寫存儲器操作時,如果地址越界(即超出3K空間),在IMR寄存器bit7置位的情況下,地址指針將會返回到存儲器0地址處。同樣,在讀存儲器操作時,如果地址越界(即超出16K空間),在IMR寄存器bit7置位的情況下,地址指針將會返回到存儲器0C00H地址處。

4、DM9000數(shù)據(jù)包發(fā)送

DM9000有兩個發(fā)送數(shù)據(jù)包:index1和index2,同時存儲在TXSRAM中。發(fā)送控制寄存器控制循環(huán)冗余校驗碼和填充的插入,其狀態(tài)分別記錄在發(fā)送狀態(tài)寄存器1和發(fā)送狀態(tài)寄存器2中。發(fā)送器的起始地址為00H,在軟件或硬件復(fù)位后,默認(rèn)的數(shù)據(jù)發(fā)送包為index1。首先,將數(shù)據(jù)寫入TXSRAM中,然后,在發(fā)送數(shù)據(jù)包長度寄存器中把數(shù)據(jù)字節(jié)數(shù)寫入字節(jié)計數(shù)寄存器。置位發(fā)送控制寄存器(02H)的bit0位,則DM9000開始發(fā)送index1數(shù)據(jù)包。在index1數(shù)據(jù)包發(fā)送結(jié)束之前,數(shù)據(jù)發(fā)送包index2被移入TXSRAM中。在index1數(shù)據(jù)包發(fā)送結(jié)束后,將index2數(shù)據(jù)字節(jié)數(shù)寫入字節(jié)計數(shù)寄存器中,然后,置位發(fā)送控制寄存器(02H)的bit0位,則index2數(shù)據(jù)包開始發(fā)送。以此類推,后面的數(shù)據(jù)包都以此方式進(jìn)行發(fā)送。

5、DM9000數(shù)據(jù)包接收

RXSRAM是一個環(huán)形數(shù)據(jù)結(jié)構(gòu)。在軟件或硬件復(fù)位后,RXSRAM的起始地址為C00H。每個接收數(shù)據(jù)包都包含有CRC校驗域,數(shù)據(jù)域,以及緊跟其后的4字節(jié)包頭域。4字節(jié)包頭格式為:01H、狀態(tài)、BYTE_COUNT低、BYTE_COUNT高。請注意:每個接收包的起始地址處在適當(dāng)?shù)牡刂愤吔纾@取決于當(dāng)前總線操作模式(8bit或者16bit)。DM9000是通過16位數(shù)據(jù)總線,掛在STM32的FSMC上面,DM9000的片選由FSMC_NE2控制,CMD則由FSMC_A7控制。這個連接方法,類似于TFTLCD顯示,總共用到了22個IO口。

24.2 TCP/IP協(xié)議概述

TCP/IP中文名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議,又名網(wǎng)絡(luò)通訊協(xié)議,是Internet最基本的協(xié)議、Internet國際互聯(lián)網(wǎng)絡(luò)的基礎(chǔ),由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成。TCP/IP定義了電子設(shè)備如何連入因特網(wǎng),以及數(shù)據(jù)如何在它們之間傳輸?shù)臉?biāo)準(zhǔn)。協(xié)議采用了4層的層級結(jié)構(gòu),每一層都呼叫它的下一層所提供的協(xié)議來完成自己的需求。通俗而言:TCP負(fù)責(zé)發(fā)現(xiàn)傳輸?shù)膯栴},一有問題就發(fā)出信號,要求重新傳輸,直到所有數(shù)據(jù)安全正確地傳輸?shù)侥康牡?。而IP是給因特網(wǎng)的每一臺聯(lián)網(wǎng)設(shè)備規(guī)定一個地址。

TCP/IP協(xié)議不是TCP和IP這兩個協(xié)議的合稱,而是指因特網(wǎng)整個TCP/IP協(xié)議族。從協(xié)議分層模型方面來講,TCP/IP由四個層次組成:網(wǎng)絡(luò)接口層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層。OSI是傳統(tǒng)的開放式系統(tǒng)互連參考模型,該模型將TCP/IP分為七層:物理層、數(shù)據(jù)鏈路層(網(wǎng)絡(luò)接口層)、網(wǎng)絡(luò)層(網(wǎng)絡(luò)層)、傳輸層(傳輸層)、會話層、表示層和應(yīng)用層(應(yīng)用層)。TCP/IP模型與OSI模型對比如下表所示。

層級 OSI模型 TCP/IP模型
1 應(yīng)用層 應(yīng)用層
2 表示層
3 會話層
4 傳輸層 傳輸層
5 網(wǎng)絡(luò)層 互聯(lián)層
6 數(shù)據(jù)鏈路層 鏈路層
7 物理層

我們剛才介紹的DM9000相當(dāng)于鏈路層,而LWIP提供的就是網(wǎng)絡(luò)層的功能,應(yīng)用層則需要用戶自己編寫代碼去實現(xiàn)。

24.3 LWIP概述

LWIP是瑞典計算機(jī)科學(xué)院(SICS)的AdamDunkels等開發(fā)的一個小型開源的TCP/IP協(xié)議棧。LWIP是輕量級IP協(xié)議,有無操作系統(tǒng)的支持都可以運(yùn)行,LWIP實現(xiàn)的重點(diǎn)是在保持TCP協(xié)議主要功能的基礎(chǔ)上減少對RAM的占用,它只需十幾KB的RAM和40K左右的ROM就可以運(yùn)行,這使LWIP協(xié)議棧適合在低端的嵌入式系統(tǒng)中使用。目前LWIP的最新版本是2.1.2。在這里采用比較常用的1.4.1版本進(jìn)行介紹。

LWIP的主要特性如下:

(1)ARP協(xié)議:以太網(wǎng)地址解析協(xié)議

(2)IP協(xié)議:包括IPv4和IPv6,支持IP分片與重裝,支持多網(wǎng)絡(luò)接口下數(shù)據(jù)轉(zhuǎn)發(fā)

(3)ICMP協(xié)議:用于網(wǎng)絡(luò)調(diào)試與維護(hù)

(4)IGMP協(xié)議:用于網(wǎng)絡(luò)組管理,可以實現(xiàn)多播數(shù)據(jù)的接收

(5)UDP協(xié)議:用戶數(shù)據(jù)報協(xié)議

(6)TCP協(xié)議:支持TCP擁塞控制,RTT估計,快速恢復(fù)與重傳等

(7)提供三種用戶編程接口方式:raw/callbackAPI、sequentialAPI、BSD-stylesocketAPI

(8)DNS:域名解析

(9)SNMP:簡單網(wǎng)絡(luò)管理協(xié)議

(10)DHCP:動態(tài)主機(jī)配置協(xié)議

(11)AUTOIP:IP地址自動配置

(12)PPP:點(diǎn)對點(diǎn)協(xié)議,支持PPPoE

24.4 DM9000驅(qū)動編寫

24.4.1 DM9000寄存器介紹

(1) 網(wǎng)絡(luò)控制寄存器 :NCR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
- WAKEEN - FCTOL FDX LBK RST

Bit 6:置位時將啟用喚醒功能。清除該位還將清除所有喚醒事件狀態(tài),軟件復(fù)位后,該位將不受影響

0:開啟

1:關(guān)閉

Bit 4:強(qiáng)制沖突模式,用于檢測

Bit 3:內(nèi)部PHY全雙工模式

Bit 2~Bit 1:回環(huán)模式

00:正常

01:MAC內(nèi)部回環(huán)

10:內(nèi)部PHY100M模式數(shù)字回環(huán)

11:保留

Bit 0:軟件復(fù)位,寫1啟動復(fù)位,10us后自動清零

(2) 網(wǎng)絡(luò)狀態(tài)寄存器 :NSR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
SPEED LINKST WAKEST - TXD2END TX1END RXOV -

Bit 7:網(wǎng)絡(luò)速度,在使用內(nèi)部PHY的情況下,0表示100Mbps,1表示10Mbps,當(dāng)LINKST=0時,該位無意義

Bit 6:連接狀態(tài)

0:連接失敗

1:連接成功

Bit 5:喚醒狀態(tài),讀或者對該位寫1清0,復(fù)位后該位不受影響

0:產(chǎn)生喚醒事件

1:沒有喚醒事件

Bit 3:發(fā)送數(shù)據(jù)包2完成標(biāo)志,讀或者對該位寫1清0

Bit 2:發(fā)送數(shù)據(jù)包1完成標(biāo)志,讀或者對該位寫1清0

Bit 1:接收緩存溢出標(biāo)志

(3) 發(fā)送控制寄存器 :TCR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
- TJDIS EXCECM PAD_DIS2 CRC_DIS2 PAD_DIS1 CRC_DIS1 TXREQ

Bit 6:Jabber傳輸禁止

0:進(jìn)制Jabber傳輸定時器(2K字節(jié))

1:使能

Bit 5:嚴(yán)重沖突模式檢測

0:當(dāng)沖突計數(shù)多于15則終止本次數(shù)據(jù)包

   1:始終嘗試發(fā)送本次數(shù)據(jù)包

Bit 4:禁止為數(shù)據(jù)包2添加填充

Bit 3:禁止為數(shù)據(jù)包2添加CRC校驗

Bit 2:禁止為數(shù)據(jù)包1添加填充

Bit 1:禁止為數(shù)據(jù)包1添加CRC校驗

Bit 0:發(fā)送請求,發(fā)送完成后自動清除該位

(4) 接收控制寄存器 :RCR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
- WTDIS DIS_LONG DIS_CRC ALL RUNT PRMSC RXEN

Bit 6:看門狗定時器進(jìn)制

0:使能

   1:禁止

Bit 5:丟棄包長度超過1522字節(jié)的數(shù)據(jù)包

Bit 4:丟棄CRC校驗錯誤的數(shù)據(jù)包

Bit 3:允許廣播

Bit 2:允許小于最小長度的數(shù)據(jù)包

Bit 1:各種模式

Bit 0:接收使能

(5) 流控制閾值寄存器 :FCTR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
HWOT LWOT

Bit 7~Bit 4:接收緩存高位溢出門限

當(dāng)接收SRAM空閑空間小于該門限值則發(fā)送一個暫停時間為FFFF H的暫停包,若該值為0,則沒有接收條件,若該值為1,則默認(rèn)值為3K字節(jié)的空閑空間

Bit 3~Bit 0:接收緩存低位溢出門限

當(dāng)接收SRAM空閑空間大于該門限值則發(fā)送一個暫停時間為0000 H的暫停包,當(dāng)溢出門限最高值的暫停包發(fā)送之后,溢出門限值最低值的暫停包才有效,默認(rèn)值為8K

(6) 背壓閾值寄存器 :BPTR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
BPHW JPT

Bit 7~Bit 4:背壓閾值最高值

當(dāng)接收SRAM空閑空間低于該閾值,則MAC將產(chǎn)生一個擁擠狀態(tài),默認(rèn)值3K字節(jié)空閑空間

Bit 3~Bit 0:擁擠狀態(tài)時間,默認(rèn)為200us

JPT值 擁擠狀態(tài)時間(us) JPT值 擁擠狀態(tài)時間(us)
0000 5 1000 250
0001 10 1001 300
0010 15 1010 350
0011 25 1011 400
0100 50 1100 450
0101 100 1101 500
0110 150 1110 550
0111 200 1111 600

(7) 發(fā)送控制寄存器2 :TCR2

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
LED RLCP DTU ONEPM IFGS

Bit 7:LED模式

0:設(shè)置LED引腳為模式0或者根據(jù)EEPROM的設(shè)定

1:設(shè)置LED引腳為模式1

Bit 6:重試沖突延遲數(shù)據(jù)包

Bit 5:禁止重新發(fā)送“underruned”數(shù)據(jù)包

Bit 4:單包模式

0:發(fā)送完成前發(fā)送最多兩個數(shù)據(jù)包的命令能被執(zhí)行

1:發(fā)送完成前發(fā)送一個數(shù)據(jù)包的命令能被執(zhí)行

Bit 3~Bit 0:幀間隔設(shè)置

0xxx:96 bit

1000:64 bit

1001:72 bit

1010:80 bit

1011:88 bit

1100:96 bit

1101:104 bit

1110:112 bit

1111:120 bit

(8) 中斷狀態(tài)寄存器 :ISR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
IOMODE - LNKCHG UNRUN ROO ROS PT PR

Bit 7:數(shù)據(jù)寬度選擇

0:16位模式

1:8位模式

Bit 5:連接狀態(tài)改變

Bit 4:發(fā)送“underrun”

Bit 3:接收計數(shù)器溢出

Bit 2:接收溢出

Bit 1:數(shù)據(jù)包發(fā)送

Bit 0:數(shù)據(jù)包接收

(9) 中斷狀態(tài)寄存器 :IMR

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
PAR - LNKCHGI UDRUNI ROOI ROSI PTI PRI

Bit 7:使能SRAM讀寫指針在指針地址超過SRAM的大小時自動跳回起始位置,需要驅(qū)動程序設(shè)置該位,若設(shè)置該位,REG_F5將自動設(shè)置為0x H

Bit 5:使能連接狀態(tài)改變中斷

Bit 4:使能發(fā)送“underrun”中斷

Bit 3:使能接收計數(shù)器溢出中斷

Bit 2:使能接收溢出中斷

Bit 1:使能數(shù)據(jù)包發(fā)送中斷

Bit 0:使能數(shù)據(jù)包接收中斷

24.4.2 DM9000驅(qū)動

(1)初始化DM9000外設(shè)與寄存器配置

u8 DM9000_Init()
{
  u32 temp;
  //初始化和DM9000連接的IO和FSMC
  RCC->AHBENR |= 1<<8 ;            //使能FSMC時鐘
  RCC->APB2ENR |= 1<<5 ;            //使能PORTD時鐘
  RCC->APB2ENR |= 1<<6 ;            //使能PORTE時鐘
  RCC->APB2ENR |= 1<<7 ;            //使能PORTF時鐘
  RCC->APB2ENR |= 1<<8 ;            //使能PORTG時鐘
  //PD7->DM9000_RST
  GPIOD->CRH &= 0x00FFF000 ;
  GPIOD->CRH |= 0xBB000BBB ;
  GPIOD->CRL &= 0x0F00FF00 ;
  GPIOD->CRL |= 0x30BB00BB ;
  //PE
  GPIOE->CRH &= 0x00000000 ;
  GPIOE->CRH |= 0xBBBBBBBB ;
  GPIOE->CRL &= 0x0FFFFFFF ;
  GPIOE->CRL |= 0xB0000000 ;
  //PF13-->FSMC_A7
  GPIOF->CRH &= 0xFF0FFFFF ;
  GPIOF->CRH |= 0x00B00000 ;
  //PG9->NE2
  GPIOG->CRH &= 0xFFFFFF0F ;
  GPIOG->CRH |= 0x000000B0 ;
  GPIOG->CRL &= 0xF0FFFFFF ;
  GPIOG->CRL |= 0x08000000 ;
  GPIOG->ODR |= 1<<6 ;
  EXIT_Config( 6, 6, 1 ) ;              //下降沿觸發(fā)
  NVIC_Init( 0, 0, EXTI9_5_IRQn, 2 ) ;        //優(yōu)先級最高
  //寄存器清零
  FSMC_Bank1->BTCR[ 2 ] = 0x00000000 ;
  FSMC_Bank1->BTCR[ 3 ] = 0x00000000 ;
  FSMC_Bank1E->BWTR[ 2 ] = 0x00000000 ;
  FSMC_Bank1->BTCR[ 2 ] |= 1<<12 ;        //存儲器寫使能
  FSMC_Bank1->BTCR[ 2 ] |= 1<<4 ;        //存儲器數(shù)據(jù)寬度為16bit
  //操作BTR寄存器
  FSMC_Bank1->BTCR[ 3 ] |= 3<<8 ;        //數(shù)據(jù)保持時間(DATAST)為3個HCLK 4/72M=55ns
  FSMC_Bank1->BTCR[ 3 ] |= 0<<4 ;        //地址保持時間(ADDHLD)未用到
  FSMC_Bank1->BTCR[ 3 ] |= 1<<0 ;        //地址建立時間(ADDSET)為2個HCLK 2/72M=27ns
  FSMC_Bank1E->BWTR[ 2 ] = 0x0FFFFFFF ;      //閃存寫時序寄存器
  FSMC_Bank1->BTCR[ 2 ] |= 1<<0 ;        //使能BANK1區(qū)域2
  temp = *( vu32* )( 0x1FFFF7E8 ) ;        //獲取STM32的唯一ID的前24位作為MAC地址后三字節(jié)
  dm9000cfg.mode = DM9000_AUTO ;
   dm9000cfg.queue_packet_len = 0 ;
//DM9000的SRAM的發(fā)送和接收指針自動返回到開始地址,并開啟接收中斷
  dm9000cfg.imr_all = IMR_PAR|IMR_PRI ; 
  //初始化MAC地址
  dm9000cfg.mac_addr[ 0 ] = 2 ;
  dm9000cfg.mac_addr[ 1 ] = 0 ;
  dm9000cfg.mac_addr[ 2 ] = 0 ;
  dm9000cfg.mac_addr[ 3 ] = ( temp>>16 )&0xFF ;  //低三字節(jié)用STM32的唯一ID
  dm9000cfg.mac_addr[ 4 ] = ( temp>>8 )&0xFFF ;
  dm9000cfg.mac_addr[ 5 ] = temp&0xFF ;
  //初始化組播地址
  dm9000cfg.multicase_addr[ 0 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 1 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 2 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 3 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 4 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 5 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 6 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 7 ] = 0xFF ;
  DM9000_Reset() ;                //復(fù)位DM9000
  delay_ms( 100 ) ;
  //獲取DM9000ID
  temp = DM9000_ReadReg( DM9000_VIDL ) ;
  temp |= DM9000_ReadReg( DM9000_VIDH )<<8 ;
  temp |= DM9000_ReadReg( DM9000_PIDL )<<16 ;
  temp |= DM9000_ReadReg( DM9000_PIDH )<<24 ;
  //讀取ID錯誤
  if( temp!=DM9000_ID )
    return 1 ;
  DM9000_Set_PHYMode( dm9000cfg.mode ) ;    //設(shè)置PHY工作模式
  DM9000_WriteReg( DM9000_NCR, 0x00 ) ;
  DM9000_WriteReg( DM9000_TCR, 0x00 ) ;      //發(fā)送控制寄存器清零
  DM9000_WriteReg( DM9000_BPTR, 0x3F ) ;
  DM9000_WriteReg( DM9000_FCTR, 0x38 ) ;
  DM9000_WriteReg( DM9000_FCR, 0x00 ) ;
  DM9000_WriteReg( DM9000_SMCR, 0x00 ) ;    //特殊模式
  DM9000_WriteReg( DM9000_NSR, NSR_WAKEST|NSR_TX2END|NSR_TX1END ) ;  //清除發(fā)送狀態(tài)
  DM9000_WriteReg( DM9000_ISR, 0x0F ) ;      //清除中斷狀態(tài)
  DM9000_WriteReg( DM9000_TCR2, 0x80 ) ;    //切換LED到mode1
  //設(shè)置MAC地址和組播地址
  DM9000_Set_MACAddress( dm9000cfg.mac_addr ) ;//設(shè)置MAC地址
  DM9000_Set_Multicast( dm9000cfg.multicase_addr ) ; //設(shè)置組播地址
  DM9000_WriteReg( DM9000_RCR, RCR_DIS_LONG|RCR_DIS_CRC|RCR_RXEN ) ;
  DM9000_WriteReg( DM9000_IMR, IMR_PAR ) ; 
  DM9000_Get_SpeedAndDuplex() ;        //獲取DM9000的連接速度和雙工狀態(tài)
  DM9000_WriteReg( DM9000_IMR, dm9000cfg.imr_all ) ;  //設(shè)置中斷
  return 0 ;
}

注:函數(shù)中用到了未定義的數(shù)據(jù)類型,需要在sys.h中添加該類型的定義typedef volatile uint32_t vu32。

(2)DM9000內(nèi)部寄存器讀寫函數(shù)

u8 DM9000_Init()
{
  u32 temp;
  //初始化和DM9000連接的IO和FSMC
  RCC->AHBENR |= 1<<8 ;            //使能FSMC時鐘
  RCC->APB2ENR |= 1<<5 ;            //使能PORTD時鐘
  RCC->APB2ENR |= 1<<6 ;            //使能PORTE時鐘
  RCC->APB2ENR |= 1<<7 ;            //使能PORTF時鐘
  RCC->APB2ENR |= 1<<8 ;            //使能PORTG時鐘
  //PD7->DM9000_RST
  GPIOD->CRH &= 0x00FFF000 ;
  GPIOD->CRH |= 0xBB000BBB ;
  GPIOD->CRL &= 0x0F00FF00 ;
  GPIOD->CRL |= 0x30BB00BB ;
  //PE
  GPIOE->CRH &= 0x00000000 ;
  GPIOE->CRH |= 0xBBBBBBBB ;
  GPIOE->CRL &= 0x0FFFFFFF ;
  GPIOE->CRL |= 0xB0000000 ;
  //PF13-->FSMC_A7
  GPIOF->CRH &= 0xFF0FFFFF ;
  GPIOF->CRH |= 0x00B00000 ;
  //PG9->NE2
  GPIOG->CRH &= 0xFFFFFF0F ;
  GPIOG->CRH |= 0x000000B0 ;
  GPIOG->CRL &= 0xF0FFFFFF ;
  GPIOG->CRL |= 0x08000000 ;
  GPIOG->ODR |= 1<<6 ;
  EXIT_Config( 6, 6, 1 ) ;              //下降沿觸發(fā)
  NVIC_Init( 0, 0, EXTI9_5_IRQn, 2 ) ;        //優(yōu)先級最高
  //寄存器清零
  FSMC_Bank1->BTCR[ 2 ] = 0x00000000 ;
  FSMC_Bank1->BTCR[ 3 ] = 0x00000000 ;
  FSMC_Bank1E->BWTR[ 2 ] = 0x00000000 ;
  FSMC_Bank1->BTCR[ 2 ] |= 1<<12 ;        //存儲器寫使能
  FSMC_Bank1->BTCR[ 2 ] |= 1<<4 ;        //存儲器數(shù)據(jù)寬度為16bit
  //操作BTR寄存器
  FSMC_Bank1->BTCR[ 3 ] |= 3<<8 ;        //數(shù)據(jù)保持時間(DATAST)為3個HCLK 4/72M=55ns
  FSMC_Bank1->BTCR[ 3 ] |= 0<<4 ;        //地址保持時間(ADDHLD)未用到
  FSMC_Bank1->BTCR[ 3 ] |= 1<<0 ;        //地址建立時間(ADDSET)為2個HCLK 2/72M=27ns
  FSMC_Bank1E->BWTR[ 2 ] = 0x0FFFFFFF ;      //閃存寫時序寄存器
  FSMC_Bank1->BTCR[ 2 ] |= 1<<0 ;        //使能BANK1區(qū)域2
  temp = *( vu32* )( 0x1FFFF7E8 ) ;        //獲取STM32的唯一ID的前24位作為MAC地址后三字節(jié)
  dm9000cfg.mode = DM9000_AUTO ;
   dm9000cfg.queue_packet_len = 0 ;
//DM9000的SRAM的發(fā)送和接收指針自動返回到開始地址,并開啟接收中斷
  dm9000cfg.imr_all = IMR_PAR|IMR_PRI ; 
  //初始化MAC地址
  dm9000cfg.mac_addr[ 0 ] = 2 ;
  dm9000cfg.mac_addr[ 1 ] = 0 ;
  dm9000cfg.mac_addr[ 2 ] = 0 ;
  dm9000cfg.mac_addr[ 3 ] = ( temp>>16 )&0xFF ;  //低三字節(jié)用STM32的唯一ID
  dm9000cfg.mac_addr[ 4 ] = ( temp>>8 )&0xFFF ;
  dm9000cfg.mac_addr[ 5 ] = temp&0xFF ;
  //初始化組播地址
  dm9000cfg.multicase_addr[ 0 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 1 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 2 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 3 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 4 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 5 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 6 ] = 0xFF ;
  dm9000cfg.multicase_addr[ 7 ] = 0xFF ;
  DM9000_Reset() ;                //復(fù)位DM9000
  delay_ms( 100 ) ;
  //獲取DM9000ID
  temp = DM9000_ReadReg( DM9000_VIDL ) ;
  temp |= DM9000_ReadReg( DM9000_VIDH )<<8 ;
  temp |= DM9000_ReadReg( DM9000_PIDL )<<16 ;
  temp |= DM9000_ReadReg( DM9000_PIDH )<<24 ;
  //讀取ID錯誤
  if( temp!=DM9000_ID )
    return 1 ;
  DM9000_Set_PHYMode( dm9000cfg.mode ) ;    //設(shè)置PHY工作模式
  DM9000_WriteReg( DM9000_NCR, 0x00 ) ;
  DM9000_WriteReg( DM9000_TCR, 0x00 ) ;      //發(fā)送控制寄存器清零
  DM9000_WriteReg( DM9000_BPTR, 0x3F ) ;
  DM9000_WriteReg( DM9000_FCTR, 0x38 ) ;
  DM9000_WriteReg( DM9000_FCR, 0x00 ) ;
  DM9000_WriteReg( DM9000_SMCR, 0x00 ) ;    //特殊模式
  DM9000_WriteReg( DM9000_NSR, NSR_WAKEST|NSR_TX2END|NSR_TX1END ) ;  //清除發(fā)送狀態(tài)
  DM9000_WriteReg( DM9000_ISR, 0x0F ) ;      //清除中斷狀態(tài)
  DM9000_WriteReg( DM9000_TCR2, 0x80 ) ;    //切換LED到mode1
  //設(shè)置MAC地址和組播地址
  DM9000_Set_MACAddress( dm9000cfg.mac_addr ) ;//設(shè)置MAC地址
  DM9000_Set_Multicast( dm9000cfg.multicase_addr ) ; //設(shè)置組播地址
  DM9000_WriteReg( DM9000_RCR, RCR_DIS_LONG|RCR_DIS_CRC|RCR_RXEN ) ;
  DM9000_WriteReg( DM9000_IMR, IMR_PAR ) ; 
  DM9000_Get_SpeedAndDuplex() ;        //獲取DM9000的連接速度和雙工狀態(tài)
  DM9000_WriteReg( DM9000_IMR, dm9000cfg.imr_all ) ;  //設(shè)置中斷
  return 0 ;
}

(3)設(shè)置MAC地址與組播地址

void DM9000_Set_MACAddress( u8 *macaddr )
{
  u8 i ;
  for( i=0; i<6; i++ )
    DM9000_WriteReg( DM9000_PAR+i, macaddr[ i ] ) ;
}
void DM9000_Set_Multicast( u8 *multicastaddr )
{
  u8 i;
  for( i=0; i<8; i++ )
    DM9000_WriteReg( DM9000_MAR+i, multicastaddr[ i ] ) ;
}

(4)獲取與設(shè)置PHY工作模式

void DM9000_Set_MACAddress( u8 *macaddr )
{
  u8 i ;
  for( i=0; i<6; i++ )
    DM9000_WriteReg( DM9000_PAR+i, macaddr[ i ] ) ;
}
void DM9000_Set_Multicast( u8 *multicastaddr )
{
  u8 i;
  for( i=0; i<8; i++ )
    DM9000_WriteReg( DM9000_MAR+i, multicastaddr[ i ] ) ;
}

(5)復(fù)位

void DM9000_Reset()
{
  DM9000_RST = 0 ;                        //DM9000硬件復(fù)位
  delay_ms( 10 ) ;
  DM9000_RST = 1 ;                        //DM9000硬件復(fù)位結(jié)束
  delay_ms( 100 ) ;                        //等待DM9000準(zhǔn)備就緒
   DM9000_WriteReg( DM9000_GPCR, 0x01 ) ;            //第1步:設(shè)置GPCR寄存器的bit0為1
  DM9000_WriteReg( DM9000_GPR, 0 ) ;              //第2步:設(shè)置GPR寄存器的bit1為0 
   DM9000_WriteReg( DM9000_NCR, 0x02|NCR_RST ) ;        //第3步:軟件復(fù)位DM9000
  //等待DM9000軟復(fù)位完成
  do 
  {
    delay_ms( 25 ) ;
  }while( DM9000_ReadReg( DM9000_NCR )&0x01 ) ;
  DM9000_WriteReg( DM9000_NCR, 0 ) ;
  DM9000_WriteReg( DM9000_NCR, 0x02|NCR_RST ) ;        //DM9000第2次軟復(fù)位
  do
  {
    delay_ms( 25 ) ;
  }while( DM9000_ReadReg( DM9000_NCR )&0x01 ) ;
}

(6)發(fā)送

void DM9000_SendPacket( struct pbuf *p )
{
  struct pbuf *q ;
  u16 pbuf_index=0 ;
  u8 word[ 2 ], word_index=0 ;
  DM9000_WriteReg( DM9000_IMR,IMR_PAR ) ;            //關(guān)閉網(wǎng)卡中斷
  DM9000->REG = DM9000_MWCMD ;              //發(fā)送的數(shù)據(jù)搬到DM9000 TX SRAM中
  q = p ;
  //向DM9000的TX SRAM中寫入數(shù)據(jù),一次寫入兩個字節(jié)數(shù)據(jù)
  //當(dāng)要發(fā)送的數(shù)據(jù)長度為奇數(shù)的時候,需要將最后一個字節(jié)單獨(dú)寫入DM9000的TX SRAM中
   while( q )
  {
    if( pbuf_index

(7)接收

struct pbuf *DM9000_Receive_Packet()
{
  struct pbuf *p ;
  struct pbuf *q ;
  u32 rxbyte ;
  vu16 rx_status, rx_length ;
  u16 *data ;
  u16 dummy ;
  int len ;
  p = NULL ;
__error_retry:  
  DM9000_ReadReg( DM9000_MRCMDX ) ;              //假讀
  rxbyte = ( u8 )DM9000->DATA ;                  //進(jìn)行第二次讀取
  //接收到數(shù)據(jù)
  if( rxbyte )
  {
    //rxbyte大于1,接收到的數(shù)據(jù)錯誤,掛了
    if( rxbyte>1 )
    {
      DM9000_WriteReg( DM9000_RCR, 0x00 ) ;
      DM9000_WriteReg( DM9000_ISR, 0x80 ) ;
      return ( struct pbuf* )p ;
    }
    DM9000->REG = DM9000_MRCMD ;
    rx_status = DM9000->DATA ;
    rx_length = DM9000->DATA ;
    p = pbuf_alloc( PBUF_RAW, rx_length, PBUF_POOL ) ;      //pbufs內(nèi)存池分配pbuf
    //內(nèi)存申請成功
    if( p!=NULL )
    {
      for( q=p; q!=NULL; q=q->next )
      {
        data = ( u16* )q->payload ;
        len = q->len ;
        while( len>0 )
        {
          *data = DM9000->DATA ;
          data ++ ;
          len -= 2 ;
        }
      }
    }
    //內(nèi)存申請失敗
    else
    {
            data = &dummy ;
      len = rx_length ;
      while( len )
      {
        *data = DM9000->DATA ;
        len -= 2 ;
      }
        }
    //根據(jù)rx_status判斷接收數(shù)據(jù)是否出現(xiàn)錯誤,如果有任何一個出現(xiàn)的話丟棄該數(shù)據(jù)幀,
    //當(dāng)rx_length小于64或者大于最大數(shù)據(jù)長度的時候也丟棄該數(shù)據(jù)幀
    if( ( rx_status&0xBF00 )||( rx_length<64 )||( rx_length>DM9000_PKT_MAX ) )
    {
      if( rx_length>DM9000_PKT_MAX )
      {
        DM9000_WriteReg( DM9000_NCR, NCR_RST ) ;      //復(fù)位DM9000
        delay_ms( 5 ) ;
      }
      //釋放內(nèi)存
      if( p!=NULL )
      pbuf_free( ( struct pbuf* )p ) ;
      p = NULL ;
      goto __error_retry ;
    }
  }
  else
  {
    DM9000_WriteReg( DM9000_ISR, ISR_PTS ) ;            //清除所有中斷標(biāo)志位
    dm9000cfg.imr_all = IMR_PAR|IMR_PRI ;              //重新接收中斷
    DM9000_WriteReg( DM9000_IMR, dm9000cfg.imr_all ) ;
  }
  return ( struct pbuf* )p ;
}

24.5 LWIP協(xié)議移植

24.5.1 源碼下載

可以從官網(wǎng)進(jìn)行源碼下載,LWIP官網(wǎng):http://savannah.nongnu.org/projects/lwip/

24.5.2 源碼結(jié)構(gòu)

圖片

打開從官網(wǎng)上下載下來的源碼其中包括doc,src和test三個文件夾和5個其他文件。doc文件夾下包含了幾個與協(xié)議棧使用相關(guān)的文本文檔,doc文件夾里面有兩個比較重要的文檔:rawapi.txt和sys_arch.txt。rawapi.txt告訴讀者怎么使用raw/callbackAPI進(jìn)行編程,sys_arch.txt包含了移植說明,在移植的時候會用到。src文件夾是我們的重點(diǎn),里面包含了LWIP的源碼。test是LWIP提供的一些測試程序。打開src源碼文件夾,src文件夾由4個文件夾組成:api、core、include、netif四個文件夾。api文件夾里面是LWIP的sequentialAPI(Netconn)和socketAPI兩種接口函數(shù)的源碼,要使用這兩種API需要操作系統(tǒng)支持。core文件夾是LWIP內(nèi)核源碼,include文件夾里面是LWIP使用到的頭文件,netif文件夾里面是與網(wǎng)絡(luò)底層接口有關(guān)的文件。

24.5.3 添加LWIP源代碼文件

(1)將lwip-2.1.2\\src目錄下的5個文件夾復(fù)制到工程文件夾中新建的LWIP文件夾中,刪除apps文件夾核include/lwip/apps文件夾。

(2)在LWIP文件夾中新建app和arch兩個文件夾。

(3)在app文件夾中新建comm,tcp_client,tcp_server和udp_demo文件夾,最終文件結(jié)構(gòu)如下圖所示。

圖片

(4)在app/comm目錄下創(chuàng)建comm.c,comm.h,lwipopts.h三個文件。

(5)在arch目錄下創(chuàng)建cc.h,cpu.h,perf.h,sys_arch.c和sys_arch.h五個文件。

(6)在include/netif目錄下創(chuàng)建ethernetif.h文件。

(7)將之前的DM9000驅(qū)動,LCD驅(qū)動和內(nèi)存管理驅(qū)動程序?qū)牍こ讨小?/p>

(8)將下列文件添加到項目LWIP-NETIF,LWIP-CORE,LWIP-API,LWIP-APP,LWIP-ARCH中。

項目目錄 文件
LWIP-NETIF etharp.c
LWIP-CORE autoip.c
ip.c ip_addr.c
dns.c init.c
netif.c pbuf.c
tcp_in.c tcp_out.c
LWIP-API api_lib.c
netifapi.c sockets.c
LWIP-APP comm.c
LWIP-ARCH sys_arch.c

注:將lwip/core目錄下的sys.c文件與lwip/include/lwip目錄下的sys.h重命名為lwip_sys.c和lwip_sys.h,以免與SYSTEM目錄下的sys.c重名,產(chǎn)生編譯錯誤。

24.5.4 arch目錄下源碼文件的修改

(1)arch/cc.h文件代碼(該文件主要完成協(xié)議使用的數(shù)據(jù)類型的定義)

#ifndef _CC_H_
#define _CC_H_
#include "cpu.h"
#include "stdio.h"
//定義與平臺無關(guān)的數(shù)據(jù)類型
typedef unsigned   char    u8_t;                    //無符號8位整數(shù)
typedef signed     char    s8_t;                    //有符號8位整數(shù)
typedef unsigned   short   u16_t;                    //無符號16位整數(shù)
typedef signed     short   s16_t;                    //有符號16位整數(shù)
typedef unsigned   long    u32_t;                    //無符號32位整數(shù)
typedef signed     long    s32_t;                    //有符號32位整數(shù)
typedef u32_t mem_ptr_t ;                        //內(nèi)存地址型數(shù)據(jù)
typedef int sys_prot_t ;                          //臨界保護(hù)型數(shù)據(jù)
#if OS_CRITICAL_METHOD == 1
#define SYS_ARCH_DECL_PROTECT(lev)
#define SYS_ARCH_PROTECT(lev)    CPU_INT_DIS()
#define SYS_ARCH_UNPROTECT(lev)    CPU_INT_EN()
#endif
//method 3 is used in this port
#if OS_CRITICAL_METHOD == 3
#define SYS_ARCH_DECL_PROTECT(lev)  u32_t lev
#define SYS_ARCH_PROTECT(lev)    lev = OS_CPU_SR_Save()
#define SYS_ARCH_UNPROTECT(lev)    OS_CPU_SR_Restore(lev)
#endif
//根據(jù)不同的編譯器定義一些符號
#if defined (__ICCARM__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT 
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#define PACK_STRUCT_USE_INCLUDES
#elif defined (__CC_ARM)
#define PACK_STRUCT_BEGIN __packed
#define PACK_STRUCT_STRUCT 
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#elif defined (__GNUC__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#elif defined (__TASKING__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#endif
//LWIP用printf調(diào)試時使用的一些數(shù)據(jù)類型
#define U16_F "4d"
#define S16_F "4d"
#define X16_F "4x"
#define U32_F "8ld"
#define S32_F "8ld"
#define X32_F "8lx"
//宏定義
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) \\
    do \\
    {   printf("Assertion \"%s\" failed at line %d in %s\\r\\n", x, __LINE__, __FILE__); \\
    } while(0)
#endif
#ifndef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#endif
#endif

(2)arch/cpu.h文件代碼(負(fù)責(zé)定義CPU的大端小端模式)

#ifndef _CPU_H_
#define _CPU_H_
#define BYTE_ORDER LITTLE_ENDIAN                //小端模式
#endif

(3)arch/perf.h文件代碼(用于系統(tǒng)測量與統(tǒng)計)

#ifndef _PERF_H_
#define _PERF_H_
#define PERF_START                        //空定義
#define PERF_STOP(x)                        //空定義
#endif

(4)arch/sys_arch.h文件代碼(為了與操作系統(tǒng)共存使用的獲取時間的函數(shù),用于為LWIP提供時鐘)

#ifndef _ARCH_SYS_ARCH_H_
#define _ARCH_SYS_ARCH_H_
#include "cc.h"
u32_t sys_now( void ) ;
#endif

(5)arch/sys_arch.c文件代碼

#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/lwip_sys.h"
#include "lwip/mem.h"
#include "tim.h"
//為LWIP提供計時
extern uint32_t lwip_localtime;//lwip本地時間計數(shù)器,單位:ms
u32_t sys_now()
{
  return lwip_localtime ;
}

24.5.5 app/comm目錄下源碼文件的修改

(1)app/comm.c文件代碼

#include "lwip/tcpip.h" 
#include "malloc.h"
#include "delay.h"
#include "usart1.h"
__lwip_dev lwipdev ;                          //lwip控制結(jié)構(gòu)體 
struct netif lwip_netif ;                          //定義一個全局的網(wǎng)絡(luò)接口
extern u32 memp_get_memorysize( void ) ;                //在memp.c里面定義
extern u8_t *memp_memory ;                      //在memp.c里面定義
extern u8_t *ram_heap ;                        //在mem.c里面定義
u32 TCPTimer=0 ;                            //TCP查詢計時器
u32 ARPTimer=0 ;                            //ARP查詢計時器
u32 lwip_localtime ;                          //lwip本地時間計數(shù)器,單位:ms
#if LWIP_DHCP
u32 DHCPfineTimer=0 ;                        //DHCP精細(xì)處理計時器
u32 DHCPcoarseTimer=0 ;                        //DHCP粗糙處理計時器
#endif
u8 lwip_comm_mem_malloc()
{
  u32 mempsize ;
  u32 ramheapsize ;
  mempsize = memp_get_memorysize() ;                //得到memp_memory數(shù)組大小
  memp_memory = mymalloc( SRAMIN, mempsize ) ;          //為memp_memory申請內(nèi)存
//得到ram heap大小
  ramheapsize = LWIP_MEM_ALIGN_SIZE( MEM_SIZE )+2*LWIP_MEM_ALIGN_SIZE( 4*3 )+MEM_ALIGNMENT ; 
  ram_heap = mymalloc( SRAMIN, ramheapsize ) ;            //為ram_heap申請內(nèi)存
  //有申請失敗的
  if( !memp_memory||!ram_heap )
  {
    lwip_comm_mem_free() ;
    return 1 ;
  }
  return 0 ;
}
void lwip_comm_mem_free()
{   
  myfree( SRAMIN, memp_memory ) ;
  myfree( SRAMIN, ram_heap ) ;
}
void lwip_comm_default_ip_set( __lwip_dev *lwipx )
{
  //默認(rèn)遠(yuǎn)端IP為:192.168.1.100
  lwipx->remoteip[ 0 ] = 192 ;  
  lwipx->remoteip[ 1 ] = 168 ;
  lwipx->remoteip[ 2 ] = 1 ;
  lwipx->remoteip[ 3 ] = 104 ;
  //MAC地址設(shè)置(高三字節(jié)固定為:2.0.0,低三字節(jié)用STM32唯一ID)
  lwipx->mac[ 0 ] = dm9000cfg.mac_addr[ 0 ] ;
  lwipx->mac[ 1 ] = dm9000cfg.mac_addr[ 1 ] ;
  lwipx->mac[ 2 ] = dm9000cfg.mac_addr[ 2 ] ;
  lwipx->mac[ 3 ] = dm9000cfg.mac_addr[ 3 ] ;
  lwipx->mac[ 4 ] = dm9000cfg.mac_addr[ 4 ] ;
  lwipx->mac[ 5 ] = dm9000cfg.mac_addr[ 5 ] ; 
  //默認(rèn)本地IP為:192.168.1.30
  lwipx->ip[ 0 ] = 192 ;  
  lwipx->ip[ 1 ] = 168 ;
  lwipx->ip[ 2 ] = 1 ;
  lwipx->ip[ 3 ] = 30 ;
  //默認(rèn)子網(wǎng)掩碼:255.255.255.0
  lwipx->netmask[ 0 ] = 255 ;  
  lwipx->netmask[ 1 ] = 255 ;
  lwipx->netmask[ 2 ] = 255 ;
  lwipx->netmask[ 3 ] = 0 ;
  //默認(rèn)網(wǎng)關(guān):192.168.1.1
  lwipx->gateway[ 0 ] = 192 ;
  lwipx->gateway[ 1 ] = 168 ;
  lwipx->gateway[ 2 ] = 1 ;
  lwipx->gateway[ 3 ] = 1 ;
  lwipx->dhcpstatus = 0 ;      //沒有DHCP
}
u8 lwip_comm_init()
{
  struct netif *Netif_Init_Flag ;      //調(diào)用netif_add()函數(shù)時的返回值,用于判斷網(wǎng)絡(luò)初始化是否成功
  struct ip_addr ipaddr ;        //ip地址
  struct ip_addr netmask ;      //子網(wǎng)掩碼
  struct ip_addr gw ;          //默認(rèn)網(wǎng)關(guān)
  //內(nèi)存申請失敗
  if( lwip_comm_mem_malloc() )
    return 1 ;
  //初始化DM9000AEP
  if( DM9000_Init() )
    return 2 ;
  lwip_init() ;            //初始化LWIP內(nèi)核
  lwip_comm_default_ip_set( &lwipdev ) ; //設(shè)置默認(rèn)IP等信息
//使用動態(tài)IP
#if LWIP_DHCP
  ipaddr.addr = 0 ;
  netmask.addr = 0 ;
  gw.addr = 0 ;
//使用靜態(tài)IP
#else
  IP4_ADDR( &ipaddr, lwipdev.ip[ 0 ], lwipdev.ip[ 1 ], lwipdev.ip[ 2 ], lwipdev.ip[ 3 ] ) ;
  IP4_ADDR( &netmask, lwipdev.netmask[ 0 ], lwipdev.netmask[1] , lwipdev.netmask[ 2 ], lwipdev.netmask[ 3 ] ) ;
  IP4_ADDR( &gw, lwipdev.gateway[ 0 ], lwipdev.gateway[ 1 ], lwipdev.gateway[ 2 ], lwipdev.gateway[ 3 ] );
#endif
  //向網(wǎng)卡列表中添加一個網(wǎng)口
  Netif_Init_Flag = netif_add( &lwip_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input ) ; 
//如果使用DHCP的話
#if LWIP_DHCP
  lwipdev.dhcpstatus = 0 ;        //DHCP標(biāo)記為0
  dhcp_start( &lwip_netif ) ;        //開啟DHCP服務(wù)
#endif
  //網(wǎng)卡添加失敗
  if( Netif_Init_Flag==NULL )
    return 3 ;
  //網(wǎng)口添加成功后,設(shè)置netif為默認(rèn)值,并且打開netif網(wǎng)口
  else
  {
    netif_set_default( &lwip_netif ) ;    //設(shè)置netif為默認(rèn)網(wǎng)口
    netif_set_up( &lwip_netif ) ;      //打開netif網(wǎng)口
  }
  return 0 ;                //操作OK
}
void lwip_pkt_handle()
{
  ethernetif_input( &lwip_netif ) ;      //從網(wǎng)絡(luò)緩沖區(qū)中讀取接收到的數(shù)據(jù)包并將其發(fā)送給LWIP處理
}
void lwip_periodic_handle()
{
#if LWIP_TCP
  //每250ms調(diào)用一次tcp_tmr()函數(shù)
  if( lwip_localtime-TCPTimer>=TCP_TMR_INTERVAL )
  {
    TCPTimer =  lwip_localtime ;
    tcp_tmr() ;
  }
#endif
  //ARP每5s周期性調(diào)用一次
  if( ( lwip_localtime-ARPTimer )>=ARP_TMR_INTERVAL )
  {
    ARPTimer = lwip_localtime ;
    etharp_tmr() ;
  }
//如果使用DHCP的話
#if LWIP_DHCP
  //每500ms調(diào)用一次dhcp_fine_tmr()
  if( lwip_localtime-DHCPfineTimer>=DHCP_FINE_TIMER_MSECS )
  {
    DHCPfineTimer = lwip_localtime ;
    dhcp_fine_tmr() ;
    if( ( lwipdev.dhcpstatus!=2 )&&( lwipdev.dhcpstatus!=0xFF ) )
      lwip_dhcp_process_handle() ;                                //DHCP處理
  }
  //每60s執(zhí)行一次DHCP粗糙處理
  if( lwip_localtime-DHCPcoarseTimer>=DHCP_COARSE_TIMER_MSECS )
  {
    DHCPcoarseTimer = lwip_localtime ;
    dhcp_coarse_tmr() ;
  }
#endif
}
//如果使能了DHCP
#if LWIP_DHCP
void lwip_dhcp_process_handle()
{
  u32 ip=0, netmask=0, gw=0 ;
  switch( lwipdev.dhcpstatus )
  {
    //開啟DHCP
    case 0:
      dhcp_start( &lwip_netif ) ;
      lwipdev.dhcpstatus = 1 ;            //等待通過DHCP獲取到的地址
      break ;
    //等待獲取到IP地址
    case 1:
    {
      ip = lwip_netif.ip_addr.addr ;          //讀取新IP地址
      netmask = lwip_netif.netmask.addr ;        //讀取子網(wǎng)掩碼
      gw = lwip_netif.gw.addr ;            //讀取默認(rèn)網(wǎng)關(guān) 
      //正確獲取到IP地址的時候
      if( ip!=0 )
      {
        lwipdev.dhcpstatus = 2 ;          //DHCP成功
        //解析出通過DHCP獲取到的IP地址
        lwipdev.ip[ 3 ] = ( uint8_t )( ip>>24 ) ; 
        lwipdev.ip[ 2 ] = ( uint8_t )( ip>>16 ) ;
        lwipdev.ip[ 1 ] = ( uint8_t )( ip>>8 ) ;
        lwipdev.ip[ 0 ] = ( uint8_t )( ip ) ;
        //解析通過DHCP獲取到的子網(wǎng)掩碼地址
        lwipdev.netmask[ 3 ] = ( uint8_t )( netmask>>24 ) ;
        lwipdev.netmask[ 2 ] = ( uint8_t )( netmask>>16 ) ;
        lwipdev.netmask[ 1 ] = ( uint8_t )( netmask>>8 ) ;
        lwipdev.netmask[ 0 ] = ( uint8_t )( netmask ) ;
        //解析出通過DHCP獲取到的默認(rèn)網(wǎng)關(guān)
        lwipdev.gateway[ 3 ] = ( uint8_t )( gw>>24 ) ;
        lwipdev.gateway[ 2 ] = ( uint8_t )( gw>>16 ) ;
        lwipdev.gateway[ 1 ] = ( uint8_t )( gw>>8 ) ;
        lwipdev.gateway[ 0 ] = ( uint8_t )( gw ) ;
      }
      //通過DHCP服務(wù)獲取IP地址失敗,且超過最大嘗試次數(shù)
      else if( lwip_netif.dhcp->tries>LWIP_MAX_DHCP_TRIES )
      {
        lwipdev.dhcpstatus = 0xFF ;          //DHCP超時失敗
        //使用靜態(tài)IP地址
        IP4_ADDR( &( lwip_netif.ip_addr ), lwipdev.ip[ 0 ], lwipdev.ip[ 1 ], lwipdev.ip[ 2 ], lwipdev.ip[ 3 ] ) ;
        IP4_ADDR( &( lwip_netif.netmask ), lwipdev.netmask[ 0 ], lwipdev.netmask[ 1 ], lwipdev.netmask[ 2 ], lwipdev.netmask[ 3 ] ) ;
        IP4_ADDR( &( lwip_netif.gw ), lwipdev.gateway[ 0 ], lwipdev.gateway[ 1 ], lwipdev.gateway[ 2 ], lwipdev.gateway[ 3 ] ) ;
      }
    }
    break;
    default :
    break;
  }
}
#endif

(2)app/comm.h文件代碼

#ifndef _COMM_H_
#define _COMM_H_
#include "dm9000.h"
#define LWIP_MAX_DHCP_TRIES  4            //DHCP服務(wù)器最大重試次數(shù)
//lwip控制結(jié)構(gòu)體
typedef struct  
{
  u8 mac[ 6 ] ;                    //MAC地址
  u8 remoteip[ 4 ] ;                  //遠(yuǎn)端主機(jī)IP地址 
  u8 ip[ 4 ] ;                    //本機(jī)IP地址
  u8 netmask[ 4 ] ;                  //子網(wǎng)掩碼
  u8 gateway[ 4 ] ;                  //默認(rèn)網(wǎng)關(guān)的IP地址
  vu8 dhcpstatus ;                  //dhcp狀態(tài)
                          //0,未獲取DHCP地址
                          //1,進(jìn)入DHCP獲取狀態(tài)
                          //2,成功獲取DHCP地址
                          //0XFF,獲取失敗
}__lwip_dev ;
extern __lwip_dev lwipdev ;                //lwip控制結(jié)構(gòu)體
void lwip_pkt_handle( void ) ;
void lwip_periodic_handle( void ) ;
void lwip_comm_default_ip_set( __lwip_dev *lwipx ) ;
u8 lwip_comm_mem_malloc( void ) ;
void lwip_comm_mem_free( void ) ;
u8 lwip_comm_init( void ) ;
void lwip_dhcp_process_handle( void ) ;
#endif

注:函數(shù)中用到了未定義的數(shù)據(jù)類型,需要在sys.h中添加該類型的定義typedef volatile uint8_t vu8。

(3)app/lwipopts文件代碼

#ifndef _LWIPOPTS_H_
#define _LWIPOPTS_H_
#define SYS_LIGHTWEIGHT_PROT  0
//NO_SYS==1:不使用操作系統(tǒng)
#define NO_SYS          1      //不使用UCOS操作系統(tǒng)
#define MEM_ALIGNMENT      4      //使用4字節(jié)對齊模式
//heap內(nèi)存的大小,如果在應(yīng)用中有大量數(shù)據(jù)發(fā)送的話這個值最好設(shè)置大一點(diǎn)
#define MEM_SIZE        10*1024    //內(nèi)存堆大小
//memp結(jié)構(gòu)的pbuf數(shù)量,如果應(yīng)用從ROM或者靜態(tài)存儲區(qū)發(fā)送大量數(shù)據(jù)時,這個值應(yīng)該設(shè)置大一點(diǎn)
#define MEMP_NUM_PBUF      10
#define MEMP_NUM_UDP_PCB    6      //UDP協(xié)議控制塊(PCB)數(shù)量.每個活動UDP"連接"需要一個PCB
#define MEMP_NUM_TCP_PCB    10      //同時建立激活的TCP數(shù)量
#define MEMP_NUM_TCP_PCB_LISTEN  6    //能夠監(jiān)聽的TCP連接數(shù)量
#define MEMP_NUM_TCP_SEG    20      //最多同時在隊列中的TCP段數(shù)量
#define MEMP_NUM_SYS_TIMEOUT  5      //能夠同時激活的timeout個數(shù)
//Pbuf選項
//PBUF_POOL_SIZE:pbuf內(nèi)存池個數(shù)
#define PBUF_POOL_SIZE    10
//PBUF_POOL_BUFSIZE:每個pbuf內(nèi)存池大小
#define PBUF_POOL_BUFSIZE  1500
//TCP選項
#define LWIP_TCP      1          //為1是使用TCP
#define TCP_TTL        255        //生存時間
//當(dāng)TCP的數(shù)據(jù)段超出隊列時的控制位,當(dāng)設(shè)備的內(nèi)存過小的時候此項應(yīng)為0
#define TCP_QUEUE_OOSEQ    0
//最大TCP分段
#define TCP_MSS        ( 1500-40 )    //TCP_MSS = (MTU - IP報頭大小 - TCP報頭大小
//TCP發(fā)送緩沖區(qū)大小(bytes)
#define TCP_SND_BUF      ( 4*TCP_MSS )
//TCP_SND_QUEUELEN: TCP發(fā)送緩沖區(qū)大小(pbuf).這個值最小為(2 * TCP_SND_BUF/TCP_MSS) 
#define TCP_SND_QUEUELEN  ( 4* TCP_SND_BUF/TCP_MSS )
//TCP發(fā)送窗口
#define TCP_WND        ( 2*TCP_MSS )
//ICMP選項
#define LWIP_ICMP      1        //使用ICMP協(xié)議
//DHCP選項
//當(dāng)使用DHCP時此位應(yīng)該為1,LwIP 0.5.1版本中沒有DHCP服務(wù)
#define LWIP_DHCP      1
//UDP選項
#define LWIP_UDP      1        //使用UDP服務(wù)
#define UDP_TTL        255        //UDP數(shù)據(jù)包生存時間
//靜態(tài)選項
#define LWIP_STATS      0
#define LWIP_PROVIDE_ERRNO  1
//SequentialAPI選項
//LWIP_NETCONN==1:使能NETCON函數(shù)(要求使用api_lib.c)
#define LWIP_NETCONN    0
//Socket API選項
//LWIP_SOCKET==1:使能Socket API(要求使用sockets.c)
#define LWIP_SOCKET      0
#define LWIP_COMPAT_MUTEX  1
#define LWIP_SO_RCVTIMEO  1        //通過定義可以避免阻塞線程
//Lwip調(diào)試選項
//#define LWIP_DEBUG  1            //開啟DEBUG選項
#define ICMP_DEBUG    LWIP_DBG_OFF    //開啟/關(guān)閉ICMPdebug
#endif

24.5.6 include/netif/ethernetif.h文件修改

#ifndef _ETHERNETIF_H_
#define _ETHERNETIF_H_
#include "lwip/err.h"
#include "lwip/netif.h"
//網(wǎng)卡的名字
#define IFNAME0 'e'
#define IFNAME1 'n'
err_t ethernetif_init( struct netif *netif ) ;
err_t ethernetif_input( struct netif *netif ) ;
#endif

24.5.7 netif/ethernetif.c文件修改

#include "netif/ethernetif.h"
#include "dm9000.h"
#include "comm.h"
#include "malloc.h"
#include "netif/etharp.h"
#include "string.h"
static err_t low_level_init( struct netif *netif )
{
  netif->hwaddr_len = ETHARP_HWADDR_LEN ;        //設(shè)置MAC地址長度,為6個字節(jié)
  //初始化MAC地址,不能與網(wǎng)絡(luò)中其他設(shè)備MAC地址重復(fù)
  netif->hwaddr[ 0 ] = lwipdev.mac[ 0 ] ;
  netif->hwaddr[ 1 ] = lwipdev.mac[ 1 ] ;
  netif->hwaddr[ 2 ] = lwipdev.mac[ 2 ] ;
  netif->hwaddr[ 3 ] = lwipdev.mac[ 3 ] ;
  netif->hwaddr[ 4 ] = lwipdev.mac[ 4 ] ;
  netif->hwaddr[ 5 ] = lwipdev.mac[ 5 ] ;
  netif->mtu = 1500 ;                  //最大允許傳輸單元,允許該網(wǎng)卡廣播和ARP功能
  netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP ;
  return ERR_OK ;
}
static err_t low_level_output( struct netif *netif, struct pbuf *p )
{
  DM9000_SendPacket( p ) ;
  return ERR_OK ;
}
static struct pbuf *low_level_input( struct netif *netif )
{
  struct pbuf *p ;
  p = DM9000_Receive_Packet() ;
  return p ;
}
err_t ethernetif_input( struct netif *netif )
{
  err_t err ;
  struct pbuf *p ;
  p = low_level_input( netif ) ;                    //調(diào)用low_level_input函數(shù)接收數(shù)據(jù)
  if( p==NULL )
    return ERR_MEM ;
  err = netif->input( p, netif );                                    //調(diào)用netif結(jié)構(gòu)體中的input字段(一個函數(shù))來處理數(shù)據(jù)包
  if( err!=ERR_OK )
  {
    LWIP_DEBUGF( NETIF_DEBUG, ( "ethernetif_input: IP input error\\n" ) ) ;
    pbuf_free( p ) ;
    p = NULL ;
  }
  return err ;
}
err_t ethernetif_init( struct netif *netif )
{
  LWIP_ASSERT( "netif!=NULL", ( netif!=NULL ) ) ;
//LWIP_NETIF_HOSTNAME
#if LWIP_NETIF_HOSTNAME
  netif->hostname = "lwip" ;                    //初始化名稱
#endif
  netif->name[ 0 ] = IFNAME0 ;                  //初始化變量netif的name字段
  netif->name[ 1 ] = IFNAME1 ;                  //在文件外定義這里不用關(guān)心具體值
  netif->output = etharp_output ;                  //IP層發(fā)送數(shù)據(jù)包函數(shù)
  netif->linkoutput = low_level_output ;              //ARP模塊發(fā)送數(shù)據(jù)包函數(shù)
  low_level_init( netif ) ;                      //底層硬件初始化函數(shù)
  return ERR_OK ;
}

24.5.8 其他文件修改

(1)頭文件修改:主要是將lwip/sys.h修改為lwip/lwip_sys.h,因為我們在移植的時候?qū)wip/core/sys.c和lwip/include/lwip目錄下的一個文件名稱從sys改為了lwip_sys,所以導(dǎo)致程序引用的頭文件也需要修改,需要修改的頭文件有:timers.c,init.c,lwip_sys.c,mem.c,pbuf.c和memp.c。

(2)memp.c文件修改

①修改memp_memory的定義,之前的定義是位于170行的這么幾行代碼。

static u8_t memp_memory[MEM_ALIGNMENT - 1

#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )

#include "lwip/memp_std.h"

];

我們將這段代碼屏蔽掉,重新添加定義u8_t *memp_memory;

②添加memp_get_memorysize函數(shù)

在333行插入以下函數(shù)代碼

u32_t memp_get_memorysize()

{

u32_t length=0;

   length=(

                 MEM_ALIGNMENT-1 //全局型數(shù)組 為所有POOL分配的內(nèi)存空間

                 //MEMP_SIZE表示需要在每個POOL頭部預(yù)留的空間  MEMP_SIZE = 0

                 #define LWIP_MEMPOOL(name,num,size,desc)+((num)*(MEMP_SIZE+MEMP_ALIGN_SIZE(size)))

                 #include "lwip/memp_std.h"

                 );

   return length;

}

24.6 主函數(shù)編寫

經(jīng)過上面的步驟,我們已經(jīng)成功移植了LWIP 1.4.1版本,現(xiàn)在我們通過編寫主函數(shù)來初始化LWIP,讓LWIP跑起來。

(1)添加定時器驅(qū)動,我們這里采用通用定時器3來完成LWIP的定時功能。

在tim.c文件中添加以下代碼

#include "tim.h"
extern u32 lwip_localtime;                    //lwip本地時間計數(shù)器,單位:ms
void TIM3_IRQHandler()
{
  //溢出中斷
  if( TIM3->SR&0x0001 )
    lwip_localtime +=10 ;                  //加10
  TIM3->SR &= ~( 1<<0 ) ;                  //清除中斷標(biāo)志位
}
void TIM3_Init( u16 arr, u16 psc )
{
  RCC->APB1ENR |= 1<<1 ;                  //TIM3時鐘使能
   TIM3->ARR = arr ;                    //設(shè)定計數(shù)器自動重裝值//剛好1ms
  TIM3->PSC = psc ;                    //預(yù)分頻器7200,得到10Khz的計數(shù)時鐘
  TIM3->DIER |= 1<<0 ;                                        //允許更新中斷
  TIM3->CR1 |= 0x01 ;                    //使能定時器3
    NVIC_Init( 1, 3, TIM3_IRQn, 2 ) ;                //組2
}

在tim.h文件中添加以下代碼

#ifndef _TIM_H_
#define _TIM_H_
#include "sys.h"
void TIM3_Init( u16 arr, u16 psc ) ;                //定時器3初始化
#endif

(2)主函數(shù)添加以下代碼

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "tim.h"
#include "lcd.h"
#include "malloc.h"
#include "dm9000.h"
#include "lwip/netif.h"
#include "comm.h"
#include "lwipopts.h"
int main()
{
  u8 buf[ 30 ];
   STM32_Clock_Init( 9 ) ;                                        //系統(tǒng)時鐘設(shè)置
  SysTick_Init( 72 ) ;                          //延時初始化
  USART1_Init( 72, 115200 ) ;                      //串口初始化為115200
  LCD_Init() ;                            //初始化LCD
  TIM3_Init( 1000, 719 ) ;                        //定時器3頻率為100hz
  my_mem_init( SRAMIN ) ;                      //初始化內(nèi)部內(nèi)存池
  while( lwip_comm_init() ) ;                      //lwip初始化
  //等待DHCP獲取成功/超時溢出
  while( ( lwipdev.dhcpstatus!=2 )&&( lwipdev.dhcpstatus!=0xFF ) )
  {
    lwip_periodic_handle() ;                    //LWIP內(nèi)核需要定時處理的函數(shù)
    lwip_pkt_handle() ;
  }
  POINT_COLOR=RED;
  LCD_ShowString( 30, 110, "LWIP Init Successed" ) ;
  //打印動態(tài)IP地址
  if( lwipdev.dhcpstatus==2 )
    sprintf( ( char* )buf, "DHCP IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  //打印靜態(tài)IP地址
  else
    sprintf( ( char* )buf, "Static IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  LCD_ShowString( 30, 130, buf ) ; 
  //得到網(wǎng)速
  if( ( DM9000_Get_SpeedAndDuplex()&0x02 )==0x02 )
    LCD_ShowString( 30, 150, "Ethernet Speed:10M" ) ;
  else
    LCD_ShowString( 30, 150, "Ethernet Speed:100M" ) ;
   while( 1 )
  {
    lwip_periodic_handle() ;
    lwip_pkt_handle() ;
    delay_ms( 2 ) ;
  }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 存儲器
    +關(guān)注

    關(guān)注

    38

    文章

    7403

    瀏覽量

    163399
  • DM9000
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    16860
  • 以太網(wǎng)控制器
    +關(guān)注

    關(guān)注

    0

    文章

    37

    瀏覽量

    12671
收藏 人收藏

    評論

    相關(guān)推薦

    求labview和Linux網(wǎng)絡(luò)通信實

    求labview和Linux網(wǎng)絡(luò)通信實
    發(fā)表于 10-13 12:48

    線網(wǎng)絡(luò)通信新手求助!

    各位大神,我是剛步入無線網(wǎng)絡(luò)通信行業(yè)的新手,想問問大家,研究無線網(wǎng)絡(luò)通信方向應(yīng)該學(xué)哪些東西?大家有沒有推薦的書什么的,希望得到大神們的指點(diǎn),謝謝!??!
    發(fā)表于 12-14 18:07

    stm32+lwip網(wǎng)絡(luò)通信

    stm32+lwip網(wǎng)絡(luò)通信 在向上位機(jī)發(fā)送送數(shù)據(jù)時,發(fā)送的數(shù)據(jù)必須是常量,但是我要把AD轉(zhuǎn)換的數(shù)據(jù)發(fā)送給上位機(jī)應(yīng)該怎么辦?求各路大神指點(diǎn)一二,急需,謝謝?。?!
    發(fā)表于 10-28 21:26

    為什么UDP網(wǎng)絡(luò)通信會不穩(wěn)定?

    我的程序中嵌套了很多while(1)循環(huán), 在每個循環(huán)的頭部 加入LWIP_Polling(),然后按鍵通過網(wǎng)絡(luò)發(fā)送參數(shù) ,但是發(fā)送不了。感覺103的網(wǎng)絡(luò)通信不太好用,以前用過107,
    發(fā)表于 08-07 01:23

    為什么網(wǎng)絡(luò)通信實驗用TCP客戶端模式時連接不上?

    戰(zhàn)艦V3上的實驗50 網(wǎng)絡(luò)通信實驗,當(dāng)用TCP服務(wù)器模式時,通信正常,用TCP客戶端模式時連接不上,為何?是否有更新的網(wǎng)絡(luò)通信實驗代碼?請?zhí)峁?/div>
    發(fā)表于 08-16 04:35

    如何才能讓網(wǎng)絡(luò)通信實驗支持10個UDP鏈接?

    大家好,我在使用探索者STM32F4開發(fā)板,寄存器例程,實驗55 網(wǎng)絡(luò)通信實驗。我修改了例程,想創(chuàng)建10個UDP端口監(jiān)聽,udppcb=udp_new()這里最多只能創(chuàng)建5個,5個之后都是返回失敗。請問應(yīng)該修改那個參數(shù),可以創(chuàng)建10個UDP監(jiān)聽端口。
    發(fā)表于 08-27 22:48

    為什么網(wǎng)絡(luò)通信實驗網(wǎng)絡(luò)助手上接受到的先是456個字節(jié)?

    網(wǎng)絡(luò)通信實驗里將ARMF407配置成sever,通過電腦上網(wǎng)絡(luò)助手接受ARM發(fā)送到數(shù)據(jù),將tcp_sever_sendbuf[1000]改成一個1000的大數(shù)組并賦值,但是在網(wǎng)絡(luò)助手上接受到的先是456個字節(jié)然后再是544個字
    發(fā)表于 09-02 02:54

    請問誰有F407網(wǎng)絡(luò)通信實驗的視頻嗎?

    請問有沒有F407網(wǎng)絡(luò)通信實驗的視頻啊,能方便給個鏈接或者地址嗎,謝謝了,急用嘞
    發(fā)表于 09-23 01:49

    如何把stm32f407網(wǎng)絡(luò)通信實驗調(diào)通?

    最近在做網(wǎng)絡(luò)通信實驗,沒有調(diào)通,有沒有大神指點(diǎn)一下
    發(fā)表于 10-30 04:35

    請問探索者網(wǎng)絡(luò)通信實驗的控制網(wǎng)頁該怎么寫呢?

    原子哥雖然有比較詳細(xì)的講解了網(wǎng)絡(luò)通信實驗,但是對于那個控制網(wǎng)頁怎么寫的卻沒有過多的涉及,請問有誰會寫這種控制網(wǎng)頁的,誠心求教!
    發(fā)表于 11-06 04:35

    stm32f767網(wǎng)絡(luò)通信實驗移植iar少了幾個頭文件

    原子哥,我用iar移植767網(wǎng)絡(luò)通信實驗,參考代碼是標(biāo)準(zhǔn)例程~hal庫版本,提示少了幾個頭文件,像ethernetif等我手動添加進(jìn)去了,但是lwip_check.h中調(diào)用的config.h頭文件
    發(fā)表于 03-24 23:54

    阿波羅STM32F767網(wǎng)絡(luò)通信實驗直接用網(wǎng)線連接電腦通信不成功

    STM32F767網(wǎng)絡(luò)通信實驗,直接用網(wǎng)線連接電腦,所有測試通信失敗,但是用路由器所有通信正常。已關(guān)閉防火墻
    發(fā)表于 04-07 04:36

    基于原子STM32F4的攝像頭與網(wǎng)絡(luò)通信實驗

    應(yīng)單片機(jī)課設(shè)要求,做了一個攝像頭拍照網(wǎng)絡(luò)通信C/S實時LCD顯示。該工程基于原子STM32F4的攝像頭與網(wǎng)絡(luò)通信實驗,在此基礎(chǔ)上,將其整合。1.預(yù)期功能:攝像頭拍取的內(nèi)容實時傳輸至LCD進(jìn)行顯示通過
    發(fā)表于 08-03 06:04

    通過演示實驗深化對網(wǎng)絡(luò)通信過程的理解

    通過演示實驗深化對網(wǎng)絡(luò)通信過程的理解,網(wǎng)絡(luò)通信的技術(shù)資料,很好很實用。
    發(fā)表于 03-28 10:39 ?17次下載

    從入門到精通-西門子工業(yè)網(wǎng)絡(luò)通信實戰(zhàn)

    從入門到精通-西門子工業(yè)網(wǎng)絡(luò)通信實戰(zhàn)教材免費(fèi)下載。
    發(fā)表于 04-21 14:52 ?42次下載