驅(qū)動(dòng)網(wǎng)卡芯片DM調(diào)試過程及其具體的單片機(jī)程序_第1頁
驅(qū)動(dòng)網(wǎng)卡芯片DM調(diào)試過程及其具體的單片機(jī)程序_第2頁
驅(qū)動(dòng)網(wǎng)卡芯片DM調(diào)試過程及其具體的單片機(jī)程序_第3頁
驅(qū)動(dòng)網(wǎng)卡芯片DM調(diào)試過程及其具體的單片機(jī)程序_第4頁
驅(qū)動(dòng)網(wǎng)卡芯片DM調(diào)試過程及其具體的單片機(jī)程序_第5頁
已閱讀5頁,還剩15頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、驅(qū)動(dòng)網(wǎng)卡芯片DM9000A的過程及具體驅(qū)動(dòng)程序     一、電路連接     DM9000E網(wǎng)卡芯片支持8位、16位、32位模式的處理器,通過芯片引腳EEDO(65腳)和WAKEUP(79腳)的復(fù)位值設(shè)置支持的處理器類型,如16位處理器只需將這兩個(gè)引腳接低電平即可,其中WAKEUP內(nèi)部有60K下拉電阻,因此可懸空該引腳,或作為網(wǎng)卡芯片喚醒輸出用。其它型號(hào)請(qǐng)參考相應(yīng)的數(shù)據(jù)手冊(cè)。圖1 DM9000引腳    如圖所示,對(duì)處理器驅(qū)動(dòng)網(wǎng)卡芯片來說,我們比較關(guān)心的有以下幾個(gè)引腳:IOR、IOW、

2、AEN、CMD(SA2)、INT、RST,以及數(shù)據(jù)引腳SD0-SD15-SD31和地址引腳SA4-SA9。其中,地址引腳配合AEN引腳來選通該網(wǎng)卡芯片,對(duì)于大多數(shù)的應(yīng)用來說沒有意義,因?yàn)樵谖覀兊膽?yīng)用中一般只用一個(gè)網(wǎng)卡芯片,而這些地址引腳主要用于在多網(wǎng)卡芯片環(huán)境下選擇其中之一。DM9000工作的默認(rèn)基地址為0x300,這里我們按照默認(rèn)地址選擇,將SA9、SA8接高電平,SA7-DA4接低電平。多網(wǎng)卡環(huán)境可以根據(jù)TXD0-TXD3配置SA4-SA7來選擇不同的網(wǎng)卡,這里不做介紹,有興趣的朋友請(qǐng)參考應(yīng)用手冊(cè)和數(shù)據(jù)手冊(cè)。數(shù)據(jù)引腳SD0-SD31則根據(jù)前面所講的配置處理器模式與處理器的數(shù)據(jù)總線進(jìn)行選擇連

3、接即可,沒用到的引腳懸空。那么,除了地址、數(shù)據(jù)引腳外,剩下的與處理器有關(guān)引腳對(duì)我們來說及其重要了,而與處理器無關(guān)的引腳,只需按照應(yīng)用手冊(cè)連接即可。    IOR和IOW是DM9000的讀寫選擇引腳,低電平有效,即低電平時(shí)進(jìn)行讀(IOR)寫(IOW)操作;AEN是芯片選通引腳,低電平有效,該引腳為低時(shí)才能進(jìn)行讀寫操作;CMD的命令/數(shù)據(jù)切換引腳,低電平時(shí)讀寫命令操作,高電平時(shí)讀寫數(shù)據(jù)操作。 圖2 讀時(shí)序圖3 寫時(shí)序    這些引腳接口和其它單片機(jī)外圍器件的引腳接口基本相同,其使用也一樣。對(duì)于有總線接口的單片機(jī)來說,如51系列,ARM等直

4、接連接即可。對(duì)于沒有總線接口的來說,如AVR mega32等可以直接用I/O引腳模擬總線時(shí)序進(jìn)行連接。連接時(shí)要參考讀寫時(shí)序,如上圖所示。具體連接電路,有時(shí)間我再畫出來,暫時(shí)先略了。    二、編寫驅(qū)動(dòng)程序    在這,我使用C語言編寫驅(qū)動(dòng)程序,這需要非常注意一點(diǎn),即處理器所用的C編譯器使用“大端格式”還是“小端格式”,這可以在相應(yīng)處理器的C編譯器說明上找到。一般比較常見的是小端格式。而對(duì)于8位處理器來說,在編寫驅(qū)動(dòng)程序時(shí),可以不考慮,但是在編寫網(wǎng)絡(luò)協(xié)議的時(shí)候,一定好考慮,因?yàn)榫W(wǎng)絡(luò)協(xié)議的格式是大端格式,而大部分編譯器或者我們習(xí)慣的是小端

5、格式,這一點(diǎn)需要注意。    在DM9000中,只有兩個(gè)可以直接被處理器訪問的寄存器,這里命名為CMD端口和DATA端口。事實(shí)上,DM9000中有許多控制和狀態(tài)寄存器(這些寄存器在上一篇文章中有詳細(xì)的使用說明),但它們都不能直接被處理器訪問,訪問這些控制、狀態(tài)寄存器的方法是:(1)、將寄存器的地址寫到CMD端口;(2)、從DATA端口讀寫寄存器中的數(shù)據(jù);    1、讀、寫寄存器    其實(shí),INDEX端口和DATA端口的就是由芯片上的CMD引腳來區(qū)分的。低電平為INDEX端口,高電平為DATA端口。所以,

6、要想實(shí)現(xiàn)讀寫寄存器,就必須先控制好CMD引腳。    若使用總線接口連接DM9000的話,假設(shè)總線連接后芯片的基地址為0x800300(24根地址總線),只需如下方法:#define DM_ADD (*(volatile unsigned int *) 0x8000300)#define DM_CMD (*(volatile unsigned int *) 0x8000304)/向DM9000寄存器寫數(shù)據(jù)void dm9000_reg_write(unsigned char reg, unsigned char data)    ud

7、elay(20);/之前定義的微妙級(jí)延時(shí)函數(shù),這里延時(shí)20us    DM_ADD = reg;/將寄存器地址寫到INDEX端口    udelay(20);    DM_CMD = data;/將數(shù)據(jù)寫到DATA端口,即寫進(jìn)寄存器/從DM9000寄存器讀數(shù)據(jù)unsigned int dm9000_reg_read(unsigned char reg)    udelay(20);    DM_ADD = reg;  

8、0; udelay(20);    return DM_CMD;/將數(shù)據(jù)從寄存器中讀出    只得注意的是前面的兩個(gè)宏定義DM_ADD和DM_CMD,定義的內(nèi)容表示指向無符號(hào)整形變量的指針,在這里0x800300是DM9000命令端口的地址,對(duì)它的賦值操作就相當(dāng)于把數(shù)據(jù)寫到該地址中,即把數(shù)據(jù)寫到DM9000的命令端口中。讀的道理也一樣。這是一種很常見的宏定義,一般在處理器中定義通用寄存器也是這樣定義的。    若沒有總線接口的話,可以使用IO口模擬總線時(shí)序的方法實(shí)現(xiàn)寄存器的讀寫。這里只說明實(shí)現(xiàn)步驟。首先將

9、處理器的I/O端口與DM9000的IOR等引腳直接相連(電平匹配的情況下),又假設(shè)已經(jīng)有宏定義“IOR”I/O端口控制DM9000的IOR引腳,其它端口控制DM9000引腳的命名相同,“PIO1”(根據(jù)處理器情況,可以是8位、16位或32位的I/O端口組成)控制數(shù)據(jù)端口。這樣宏命名更直觀些。寫寄存器的函數(shù)如下:void dm9000_reg_write(unsigned char reg, unsigned char data)PIO1 = reg;AEN = 0;CMD = 0;IOR = 1;IOW = 0;udelay(1);AEN = 1;IOW = 1;udelay(20);PIO1

10、 = data;AEN = 0;CMD = 0;IOR = 1;IOW = 0;udelay(1);AEN = 1;IOW = 1;    讀寄存器的寫法類似,這里就略一下了。這一過程看上去有些復(fù)雜,呵呵,其實(shí)執(zhí)行起來也蠻有效率的,執(zhí)行時(shí)間差不多。這種模擬總線時(shí)序的方式實(shí)際并不復(fù)雜,只是把總線方式下自動(dòng)執(zhí)行的過程手動(dòng)的執(zhí)行了一遍而已。    在DM9000中,還有一些PHY寄存器,也稱之為介質(zhì)無關(guān)接口MII(Media Independent Interface)寄存器。對(duì)這些寄存器的操作會(huì)影響網(wǎng)卡芯片的初始化和網(wǎng)絡(luò)連接,這里不對(duì)其進(jìn)

11、行操作,所以對(duì)這些寄存器的訪問方法這里也略了(在上篇文章中有介紹)。操作不當(dāng)反而使網(wǎng)卡不能連接到網(wǎng)絡(luò)。    至此,我們已經(jīng)寫好了兩個(gè)最基本的函數(shù):dm9000_reg_write()和dm9000_reg_read(),以及前面的宏定義DM_ADD和DM_CMD。下面將一直用到。    2、初始化DM9000網(wǎng)卡芯片。    初始化DM9000網(wǎng)卡芯片的過程,實(shí)質(zhì)上就是填寫、設(shè)置DM9000的控制寄存器的過程,這里以程序?yàn)槔M(jìn)行說明。其中寄存器的名稱宏定義在DM9000.H中已定義好。注:一下函數(shù)中un

12、signed char為一個(gè)字節(jié)unsigned int為兩個(gè)字節(jié)/DM9000初始化void DM9000_init(void)    unsigned int i;    IO0DIR |= 1 << 8;    IO1CLR |= 1 << 8;    udelay(500000);    IO2SET |= 1 << 8;    udelay(500000); &

13、#160;  IO1CLR |= 1 << 8;    udelay(500000);/*以上部分是利用一個(gè)IO口控制DM9000的RST引腳,使其復(fù)位。這一步可以省略,可以用下面的軟件復(fù)位代替*/    dm9000_reg_write(GPCR, 0x01);/設(shè)置 GPCR(1EH) bit0=1,使DM9000的GPIO3為輸出。    dm9000_reg_write(GPR, 0x00);/GPR bit0=0 使DM9000的GPIO3輸出為低以激活內(nèi)部PHY。

14、0;   udelay(5000);/延時(shí)2ms以上等待PHY上電。    dm9000_reg_write(NCR, 0x03);/軟件復(fù)位    udelay(30);/延時(shí)20us以上等待軟件復(fù)位完成    dm9000_reg_write(NCR, 0x00);/復(fù)位完成,設(shè)置正常工作模式。    dm9000_reg_write(NCR, 0x03);/第二次軟件復(fù)位,為了確保軟件復(fù)位完全成功。此步驟是必要的。   

15、 udelay(30);    dm9000_reg_write(NCR, 0x00);/*以上完成了DM9000的復(fù)位操作*/    dm9000_reg_write(NSR, 0x2c);/清除各種狀態(tài)標(biāo)志位    dm9000_reg_write(ISR, 0x3f);/清除所有中斷標(biāo)志位/*以上清除標(biāo)志位*/    dm9000_reg_write(RCR, 0x39);/接收控制    dm9000_reg_write(TCR, 0x0

16、0);/發(fā)送控制    dm9000_reg_write(BPTR, 0x3f);    dm9000_reg_write(FCTR, 0x3a);    dm9000_reg_write(RTFCR, 0xff);    dm9000_reg_write(SMCR, 0x00);/*以上是功能控制,具體功能參考上一篇文章中的說明,或參考數(shù)據(jù)手冊(cè)的介紹*/    for(i=0; i<6; i+)   

17、0;    dm9000_reg_write(PAR + i, mac_addri);/mac_addr自己定義一下吧,6個(gè)字節(jié)的MAC地址/*以上存儲(chǔ)MAC地址(網(wǎng)卡物理地址)到芯片中去,這里沒有用EEPROM,所以需要自己寫進(jìn)去*/*關(guān)于MAC地址的說明,要參考網(wǎng)絡(luò)相關(guān)書籍或資料*/    dm9000_reg_write(NSR, 0x2c);    dm9000_reg_write(ISR, 0x3f);/*為了保險(xiǎn),上面有清除了一次標(biāo)志位*/    dm9000_r

18、eg_write(IMR, 0x81);/*中斷使能(或者說中斷屏蔽),即開啟我們想要的中斷,關(guān)閉不想要的,這里只開啟的一個(gè)接收中斷*/*以上所有寄存器的具體含義參考上一篇文章,或參考數(shù)據(jù)手冊(cè)*/    這樣就對(duì)DM9000初始化完成了,怎么樣,挺簡(jiǎn)單的吧。    3、發(fā)送、接收數(shù)據(jù)包    同樣,以程序?yàn)槔?,通過注釋說明。/發(fā)送數(shù)據(jù)包/參數(shù):datas為要發(fā)送的數(shù)據(jù)緩沖區(qū)(以字節(jié)為單位),length為要發(fā)送的數(shù)據(jù)長(zhǎng)度(兩個(gè)字節(jié))。void sendpacket(unsigned char *datas

19、, unsigned int length)    unsigned int len, i;        dm9000_reg_write(IMR, 0x80);/先禁止網(wǎng)卡中斷,防止在發(fā)送數(shù)據(jù)時(shí)被中斷干擾        len = length;    dm9000_reg_write(TXPLH, (len>>8) & 0x0ff);    dm9000_reg

20、_write(TXPLL, len & 0x0ff);/*這兩句是將要發(fā)送數(shù)據(jù)的長(zhǎng)度告訴DM9000的寄存器*/    DM_ADD = MWCMD;/這里的寫法是針對(duì)有總線接口的處理器,沒有總線接口的處理器要注意加上時(shí)序。    for(i=0; i<len; i+=2)/16 bit mode            udelay(20);       

21、; DM_CMD = datasi | (datasi+1<<8);    /*上面是將要發(fā)送的數(shù)據(jù)寫到DM9000的內(nèi)部SRAM中的寫FIFO中,注意沒有總線接口的處理器要加上適當(dāng)?shù)臅r(shí)序*/*只需要向這個(gè)寄存器中寫數(shù)據(jù)即可,MWCMD是DM9000內(nèi)部SRAM的DMA指針,根據(jù)處理器模式,寫后自動(dòng)增加*/    dm9000_reg_write(TCR, 0x01);/發(fā)送數(shù)據(jù)到以太網(wǎng)上    while(dm9000_reg_read(NSR) & 0x0c) = 0);/等待數(shù)據(jù)

22、發(fā)送完成    udelay(20);    dm9000_reg_write(NSR, 0x2c);/清除狀態(tài)寄存器,由于發(fā)送數(shù)據(jù)沒有設(shè)置中斷,因此不必處理中斷標(biāo)志位    dm9000_reg_write(IMR, 0x81);/DM9000網(wǎng)卡的接收中斷使能    以上是發(fā)送數(shù)據(jù)包,過程很簡(jiǎn)單。而接收數(shù)據(jù)包確需要些說明了。DM9000從網(wǎng)絡(luò)中接到一個(gè)數(shù)據(jù)包后,會(huì)在數(shù)據(jù)包前面加上4個(gè)字節(jié),分別為“01H”、“status”(同RSR寄存器的值)、“LENL”(數(shù)據(jù)包長(zhǎng)度低

23、8位)、“LENH”(數(shù)據(jù)包長(zhǎng)度高8位)。所以首先要讀取這4個(gè)字節(jié)來確定數(shù)據(jù)包的狀態(tài),第一個(gè)字節(jié)“01H”表示接下來的是有效數(shù)據(jù)包,若為“00H”則表示沒有數(shù)據(jù)包,若為其它值則表示網(wǎng)卡沒有正確初始化,需要從新初始化。    如果接收到的數(shù)據(jù)包長(zhǎng)度小于60字節(jié),則DM9000會(huì)自動(dòng)為不足的字節(jié)補(bǔ)上0,使其達(dá)到60字節(jié)。同時(shí),在接收到的數(shù)據(jù)包后DM9000還會(huì)自動(dòng)添加4個(gè)CRC校驗(yàn)字節(jié)??梢圆挥杼幚?。于是,接收到的數(shù)據(jù)包的最小長(zhǎng)度也會(huì)是64字節(jié)。當(dāng)然,可以根據(jù)TCP/IP協(xié)議從首部字節(jié)中出有效字節(jié)數(shù),這部分在后面講解。下面為接收數(shù)據(jù)包的函數(shù)。/接收數(shù)據(jù)包/參數(shù):dat

24、as為接收到是數(shù)據(jù)存儲(chǔ)位置(以字節(jié)為單位)/返回值:接收成功返回?cái)?shù)據(jù)包類型,不成功返回0unsigned int receivepacket(unsigned char *datas)    unsigned int i, tem;    unsigned int status, len;    unsigned char ready;    ready = 0;/希望讀取到“01H”    status = 0;/數(shù)據(jù)包狀態(tài) 

25、0;   len = 0; /數(shù)據(jù)包長(zhǎng)度/*以上為有效數(shù)據(jù)包前的4個(gè)狀態(tài)字節(jié)*/    if(dm9000_reg_read(ISR) & 0x01)            dm9000_reg_write(ISR, 0x01);    /*清除接收中斷標(biāo)志位*/*/*這個(gè)地方遇到了問題,下面的黑色字體語句應(yīng)該替換成成紅色字體,也就是說MRCMDX寄存器如果第一次讀不到數(shù)據(jù),還要讀一次才能確定完全沒有數(shù)據(jù)。在

26、做 PING 實(shí)驗(yàn)時(shí)證明:每個(gè)數(shù)據(jù)包都是通過第二次的讀取MRCMDX寄存器操作而獲知為有效數(shù)據(jù)包的,對(duì)初始化的寄存器做了多次修改依然是此結(jié)果,但是用如下方法來實(shí)現(xiàn),絕不會(huì)漏掉數(shù)據(jù)包。*/    ready = dm9000_reg_read(MRCMDX); / 第一次讀取,一般讀取到的是 00H    if(ready & 0x0ff) != 0x01)            ready = dm9000_reg_r

27、ead(MRCMDX); / 第二次讀取,總能獲取到數(shù)據(jù)        if(ready & 0x01) != 0x01)                     if(ready & 0x01) != 0x00) /若第二次讀取到的不是 01H 或 00H ,則表示沒有初始化成功   

28、60;                         dm9000_reg_write(IMR, 0x80);/屏幕網(wǎng)卡中斷                 DM9000_init();/重新初始化 

29、;                dm9000_reg_write(IMR, 0x81);/打開網(wǎng)卡中斷                        retrun 0;     

30、        /* ready = dm9000_reg_read(MRCMDX); / read a byte without pointer increment    if(!(ready & 0x01)              return 0;    */*/*以上表示若接收到的第一個(gè)字節(jié)不是“01H”,則表示沒有數(shù)據(jù)包,返回0*/ &#

31、160;  status = dm9000_reg_read(MRCMD);    udelay(20);    len = DM_CMD;    if(!(status & 0xbf00) && (len < 1522)            for(i=0; i<len; i+=2)/ 16 bit mode    &

32、#160;               udelay(20);            tem = DM_CMD;            datasi = tem & 0x0ff;     &#

33、160;      datasi + 1 = (tem >> 8) & 0x0ff;                else            return 0;    /*以上接收數(shù)據(jù)包,注意的地方與發(fā)送數(shù)據(jù)包的地方相同*/    

34、if(len > 1000) return 0;    if( (HON( ETHBUF->type ) != ETHTYPE_ARP) &&        (HON( ETHBUF->type ) != ETHTYPE_IP) )            return 0;        packet_l

35、en = len;/*以上對(duì)接收到的數(shù)據(jù)包作一些必要的限制,去除大數(shù)據(jù)包,去除非ARP或IP的數(shù)據(jù)包*/              return HON( ETHBUF->type ); /返回?cái)?shù)據(jù)包的類型,這里只選擇是ARP或IP兩種類型    注意:上面的函數(shù)用到了一些宏定義,已經(jīng)在頭文件中定義過,這里說明一下:其中uint16定義為兩個(gè)字節(jié)的變量,根據(jù)C編譯器進(jìn)行定義。unsigned char Buffer1000;/定義了一個(gè)1000字節(jié)的

36、接收發(fā)送緩沖區(qū)uint16 packet_len;/接收、發(fā)送數(shù)據(jù)包的長(zhǎng)度,以字節(jié)為單位。struct eth_hdr /以太網(wǎng)頭部結(jié)構(gòu),為了以后使用方便unsigned char d_mac6;   /目的地址unsigned char s_mac6;   /源地址uint16 type;     /協(xié)議類型;struct arp_hdr /以太網(wǎng)頭部+ARP首部結(jié)構(gòu)struct eth_hdr ethhdr;    /以太網(wǎng)首部uint16 hwtype;  &

37、#160;  /硬件類型(1表示傳輸?shù)氖且蕴W(wǎng)MAC地址)uint16 protocol;    /協(xié)議類型(0x0800表示傳輸?shù)氖荌P地址)unsigned char hwlen;     /硬件地址長(zhǎng)度(6)unsigned char protolen;    /協(xié)議地址長(zhǎng)度(4)uint16 opcode;     /操作(1表示ARP請(qǐng)求,2表示ARP應(yīng)答)unsigned char smac6;    /

38、發(fā)送端MAC地址unsigned char sipaddr4;    /發(fā)送端IP地址unsigned char dmac6;    /目的端MAC地址unsigned char dipaddr4;    /目的端IP地址;struct ip_hdr /以太網(wǎng)頭部+IP首部結(jié)構(gòu)struct eth_hdr ethhdr;    /以太網(wǎng)首部unsigned char vhl,      /4位版本號(hào)4位首部長(zhǎng)度(0x45)&#

39、160;          tos;     /服務(wù)類型(0)   uint16 len,      /整個(gè)IP數(shù)據(jù)報(bào)總字節(jié)長(zhǎng)度         ipid,           /IP標(biāo)識(shí)  

40、0;      ipoffset;     /3位標(biāo)識(shí)13位偏移unsigned char ttl,             /生存時(shí)間(32或64)          proto;         /協(xié)議(1表示ICM

41、P,2表示IGMP,6表示TCP,17表示UDP)uint16 ipchksum;    /首部校驗(yàn)和unsigned char srcipaddr4,    /源IP             destipaddr4;   /目的IP;    以上定義的三種首部結(jié)構(gòu),是根據(jù)TCP/IP協(xié)議的相關(guān)規(guī)范定義的,后面會(huì)對(duì)ARP協(xié)議進(jìn)行詳細(xì)講解。【上半部分完】 &#

42、160; 4、驗(yàn)證初始化中的各個(gè)函數(shù)。    下面我們來看一下,上面所寫的初始化函數(shù)是否可用。以上我們寫好了三個(gè)函數(shù),分別為DM9000_init(),sendpacket()和receivepacket(),保存并命名為dm9000.c。既然我們要進(jìn)行調(diào)試,當(dāng)然要有結(jié)果輸出,根據(jù)自己的處理器的情況寫一個(gè)串口程序,這些函數(shù)是學(xué)某個(gè)單片機(jī)的基礎(chǔ),這里不做詳細(xì)介紹,用到是時(shí)候會(huì)在函數(shù)里注釋一下。    接下來我們來寫個(gè)主函數(shù),新建C文件,命名為mian.c,填寫如下函數(shù):void main(void)   

43、unsigned int i;    unsigned char c;    uart0_init();/初始化串口,調(diào)試時(shí)用到    DM9000_init();/初始化網(wǎng)卡    print_regs();/*通過串口,將DM9000中的寄存器打印出來,顯示在超級(jí)終端上。此函數(shù)根據(jù)自己的處理器進(jìn)行修改,功能僅僅是讀DM9000寄存器dm9000_reg_read(),再通過串口打印出來而已*/    函數(shù)寫好,保存文件,連接硬件,連接網(wǎng)線到電

44、腦上或局域網(wǎng)上,運(yùn)行結(jié)果如下圖所示: 圖4 顯示寄存器值    這里首先檢查,各個(gè)控制寄存器是否是自己寫進(jìn)去的值,在檢查狀態(tài)寄存器是否正確,其中主要要看NSR寄存器的bit5是否為“1”,該位表示是否連接成功。本例中NSR的值為40H,括號(hào)里的數(shù)為對(duì)應(yīng)的十進(jìn)制數(shù)。    下面我們將主函數(shù)改進(jìn)一下,增加個(gè)中斷接收函數(shù),查看是否能接收到數(shù)據(jù)。void main(void)    unsigned int i;    unsigned char c;  

45、0; uart0_init();/初始化串口,調(diào)試時(shí)用到    DM9000_init();/初始化網(wǎng)卡/*/*這一部分要根據(jù)自己的處理器情況,將DM9000的INT引腳連接到處理器的外部中斷上,打開中斷*/*/    sendpacket(60);/*我事先已經(jīng)在Buffer中存儲(chǔ)了ARP請(qǐng)求數(shù)據(jù)包,這里就直接發(fā)送了,以便接收ARP應(yīng)答包。大家可以先參考后面講的ARP協(xié)議,根據(jù)自己機(jī)器的情況,將數(shù)據(jù)事先存到Buffer中*/    while(1);/等待中斷void int_issue(void) /

46、中斷處理函數(shù),需要根據(jù)自己的處理器進(jìn)行設(shè)置    unsigned int i;    i = receivepacket(Buffer);/將數(shù)據(jù)讀取到Buffer中。int_again :     if(i = 0)            return;         else      &#

47、160;       print_buffer();/將接收到的所有數(shù)據(jù)打印出來         while(1);/停止在這里等待觀察,注意:實(shí)際應(yīng)用中是不允許停止在中斷中的。     /*/*這里加上這一段,目的是判斷中斷期間是否接收到其它數(shù)據(jù)包。有則加以處理。不加也完全可以*/* 根據(jù)自己的處理器,判斷處理器是否還處在中斷狀態(tài),若是則進(jìn)行如下操作,不是則跳過該段。*/    i =

48、 receivepacket(Buffer);    if(i != 0)            goto int_again;    /*/    編譯調(diào)試,運(yùn)行結(jié)果如下: 圖5 接收數(shù)據(jù)包中的數(shù)據(jù)    這是一個(gè)ARP應(yīng)答包,包含了我電腦上的MAC地址和局域網(wǎng)內(nèi)的IP地址。    如果一些順利,到這里對(duì)DM9000網(wǎng)卡芯片的初始化工作就完成了。

49、如果出現(xiàn)問題,出現(xiàn)問題首先要檢查寄存器的值是否正確??梢詫M9000中的寄存器打印出來,查看到底是哪里的問題。如果打印出的值很混亂,在確保串口程序無誤的前提下,查看硬件連接,以及寄存器讀寫時(shí)序是否正確,重復(fù)調(diào)試幾次查找原因。    三、ARP協(xié)議的實(shí)現(xiàn)    1、ARP協(xié)議原理簡(jiǎn)述    ARP協(xié)議(Address Resolution Protocol 地址解析協(xié)議),在局域網(wǎng)中,網(wǎng)絡(luò)中實(shí)際傳輸?shù)氖恰皫保瑤锩嬗心繕?biāo)主機(jī)的MAC地址。在以太網(wǎng)中,一個(gè)注意要和另一個(gè)主機(jī)進(jìn)行直接通信,必須要知道目標(biāo)主機(jī)

50、的MAC地址。這個(gè)MAC地址就是標(biāo)識(shí)我們的網(wǎng)卡芯片唯一性的地址。但這個(gè)目標(biāo)MAC地址是如何獲得的呢?這就用到了我們這里講到的地址解析協(xié)議。所有“地址解析”,就是主機(jī)在發(fā)送幀前將目標(biāo)IP地址轉(zhuǎn)換成MAC地址的過程。ARP協(xié)議的基本功能就是通過目標(biāo)設(shè)備的IP地址,查詢目標(biāo)設(shè)備的MAC地址,以保證通信的順利進(jìn)行。所以在第一次通信前,我們知道目標(biāo)機(jī)的IP地址,想要獲知目標(biāo)機(jī)的MAC地址,就要發(fā)送ARP報(bào)文(即ARP數(shù)據(jù)包)。它的傳輸過程簡(jiǎn)單的說就是:我知道目標(biāo)機(jī)的IP地址,那么我就向網(wǎng)絡(luò)中所有的機(jī)器發(fā)送一個(gè)ARP請(qǐng)求,請(qǐng)求中有目標(biāo)機(jī)的IP地址,請(qǐng)求的意思是目標(biāo)機(jī)要是收到了此請(qǐng)求,就把你的MAC地址告訴

51、我。如果目標(biāo)機(jī)不存在,那么此請(qǐng)求自然不會(huì)有人回應(yīng)。若目標(biāo)機(jī)接收到了此請(qǐng)求,它就會(huì)發(fā)送一個(gè)ARP應(yīng)答,這個(gè)應(yīng)答是明確發(fā)給請(qǐng)求者的,應(yīng)答中有MAC地址。我接到了這個(gè)應(yīng)答,我就知道了目標(biāo)機(jī)的MAC地址,就可以進(jìn)行以后的通信了。因?yàn)槊看瓮ㄐ哦家玫組AC地址。    ARP報(bào)文被封裝在以太網(wǎng)幀頭部中傳輸,如圖為ARP請(qǐng)求報(bào)文的頭部格式。 圖6 用于以太網(wǎng)的ARP請(qǐng)求或應(yīng)答分組格式    注意,以太網(wǎng)的傳輸存儲(chǔ)是“大端格式”,即先發(fā)送高字節(jié)后發(fā)送低字節(jié)。例如,兩個(gè)字節(jié)的數(shù)據(jù),先發(fā)送高8位后發(fā)送低8位。所以接收數(shù)據(jù)的時(shí)候要注意存儲(chǔ)順序。 

52、;   整個(gè)報(bào)文分成兩部分,以太網(wǎng)首部和ARP請(qǐng)求/應(yīng)答。下面挑重點(diǎn)講述?!耙蕴W(wǎng)目的地址”字段:若是發(fā)送ARP請(qǐng)求,應(yīng)填寫廣播類型的MAC地址FF-FF-FF-FF-FF-FF,意思是讓網(wǎng)絡(luò)上的所有機(jī)器接收到;“幀類型”字段:填寫08-06表示次報(bào)文是ARP協(xié)議;“硬件類型”字段:填寫00-01表示以太網(wǎng)地址,即MAC地址;“協(xié)議類型”字段:填寫08-00表示IP,即通過IP地址查詢MAC地址;“硬件地址長(zhǎng)度”字段:MAC地址長(zhǎng)度為6(以字節(jié)為單位);“協(xié)議地址長(zhǎng)度”字段:IP地址長(zhǎng)度為4(以字節(jié)為單位);“操作類型”字段:ARP數(shù)據(jù)包類型,0表示ARP請(qǐng)求,1表示ARP

53、應(yīng)答;“目的以太網(wǎng)地址”字段:若是發(fā)送ARP請(qǐng)求,這里是需要目標(biāo)機(jī)填充的。    2、ARP的處理程序    ARP協(xié)議原理很簡(jiǎn)單,下面我們來編寫ARP協(xié)議的處理函數(shù)。新建文件命名為arp.c,填寫如下函數(shù):unsigned char mac_addr6 = *,*,*,*,*,*;unsigned char ip_addr4 = 192, 168, *, * ;unsigned char host_ip_addr4 = 192, 168, *, * ;unsigned char host_mac_addr6= 0xff, 0xff,

54、 0xff, 0xff, 0xff, 0xff ; unsigned char Buffer1000;uint16 packet_len;/*這些全局變量,在前面將的文件中有些已經(jīng)有過定義,這里要注意在前面加上“extern”關(guān)鍵字?!?”應(yīng)該根據(jù)自己的機(jī)器修改*/#define HON(n) (uint16)(n) & 0xff) << 8) | (n) & 0xff00) >> 8)/*此宏定義是將小端格式存儲(chǔ)的字(兩個(gè)字節(jié))轉(zhuǎn)換成大端格式存儲(chǔ)*/void arp_request(void) /發(fā)送ARP請(qǐng)求數(shù)據(jù)包/以太網(wǎng)首部memcpy(ARPBU

55、F->ethhdr.d_mac, host_mac_addr, 6);/*字符串拷貝函數(shù),文件要包含<string.h>頭文件。參數(shù)依次是,拷貝目標(biāo)指針,拷貝數(shù)據(jù)源指針,拷貝字符數(shù)*/memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);ARPBUF->ethhdr.type = HON( 0x0806 );/*小端格式的編譯器,可以用HON()宏來轉(zhuǎn)換成大端格式,如果你的編譯器是大端格式,直接填寫0x0806即可*/*就是簡(jiǎn)單的按照協(xié)議格式填充,以下同*/ARP首部ARPBUF->hwtype = HON( 1 );ARPBU

56、F->protocol = HON( 0x0800 );ARPBUF->hwlen = 6;ARPBUF->protolen = 4;ARPBUF->opcode = HON( 0 );memcpy(ARPBUF->smac, mac_addr, 6);memcpy(ARPBUF->sipaddr, ip_addr, 4);memcpy(ARPBUF->dipaddr, host_ip_addr, 4);packet_len = 42;/14+28=42sendpacket( Buffer, packet_len );注釋:ARPBUF的宏定義和ARP

57、首部結(jié)構(gòu),在前面已經(jīng)講過。同時(shí)注意執(zhí)行該函數(shù)時(shí)中斷的處理。這里沒作處理。    看上去很easy吧,下面函數(shù)實(shí)現(xiàn)接收ARP請(qǐng)求或接收ARP應(yīng)答的處理。unsigned char arp_process(void)/ARP接收函數(shù),成功返回1,否則返回0/簡(jiǎn)單判斷ARP數(shù)據(jù)包有無損壞,有損壞則丟棄,不予處理if( packet_len < 28 )/ARP數(shù)據(jù)長(zhǎng)度為28字節(jié)為無效數(shù)據(jù)return 0;switch ( HON( ARPBUF->opcode ) )   case 0    : /處理ARP

58、請(qǐng)求         if( ARPBUF->dipaddr0 = ip_addr0 &&             ARPBUF->dipaddr1 = ip_addr1 &&             ARPBUF->dipadd

59、r2 = ip_addr2 &&             ARPBUF->dipaddr3 = ip_addr3 )/判斷是否是自己的IP,是否向自己詢問MAC地址。                      ARPBUF->opcode = HON(

60、 2 );/設(shè)置為ARP應(yīng)答             memcpy(ARPBUF->dmac, ARPBUF->smac, 6);             memcpy(ARPBUF->ethhdr.d_mac, ARPBUF->smac, 6);       &#

61、160;     memcpy(ARPBUF->smac, mac_addr, 6);             memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);             memcpy(ARPBUF->dipaddr, ARPBUF->sipad

62、dr, 4);             memcpy(ARPBUF->sipaddr, ip_addr, 4);             ARPBUF->ethhdr.type = HON( 0x0806 );           

63、60; packet_len = 42;             sendpacket( Buffer, packet_len );/發(fā)送ARP數(shù)據(jù)包             return 1;                  else                     

溫馨提示

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

評(píng)論

0/150

提交評(píng)論