找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6784|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

以太網(wǎng)控制器ENC28J60原理

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:185391 發(fā)表于 2017-4-1 15:56 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
NC28j60是帶有行業(yè)標(biāo)準(zhǔn)串行外設(shè)接口(serial peripheral interface spi)的獨(dú)立以太網(wǎng)控制器
它符合IEEE 802.3的全部規(guī)范,采用了一系列包過濾機(jī)制以對傳入數(shù)據(jù)包進(jìn)行限制;
它還提供了一個(gè)內(nèi)部DMA模塊,以實(shí)現(xiàn)快速數(shù)據(jù)吞吐和硬件支持的IP校驗(yàn)和計(jì)算。與主控制器的通信通過兩個(gè)中斷引腳和SPI 實(shí)現(xiàn),數(shù)據(jù)傳輸速率高達(dá)10 Mb/s。兩個(gè)專用的引腳用于連接LED,進(jìn)行網(wǎng)絡(luò)活動(dòng)狀態(tài)指示。
    1、支持全雙工和半雙工模式。
    2SPI接口可達(dá)10Mbps。
    3、可配置的接收和發(fā)送緩沖區(qū)大小。
4、TTL電平輸入。


ENC28J60在發(fā)送或接收數(shù)據(jù)包時(shí)由以下幾點(diǎn)值得關(guān)注:
首先,ENC28J60具有一個(gè)接收過濾器可以丟棄或接收具有組播、廣播或單播目標(biāo)地址的數(shù)據(jù)包。
其次,在數(shù)據(jù)字段處:
以太網(wǎng)數(shù)據(jù)字段的長度可以在0-1500字節(jié)之間變換,超過這一范圍的數(shù)據(jù)包是違反以太網(wǎng)標(biāo)準(zhǔn)的,這些包將會被大多數(shù)以太網(wǎng)節(jié)點(diǎn)丟棄。若設(shè)置ENC28J60的巨大幀使能位為1,可以發(fā)送和接收超大規(guī)格數(shù)據(jù)包。
在數(shù)據(jù)域中的填充字段是在數(shù)據(jù)字段小于46字節(jié)時(shí)起填充作用。ENC28J60在發(fā)送數(shù)據(jù)包時(shí),會自動(dòng)填充0。ENC28J60在接收時(shí)自動(dòng)拒絕小于18字節(jié)的數(shù)據(jù)包。數(shù)據(jù)填充亦可由主控芯片來配置。
最后,在CRC處:
ENC28J60在接收數(shù)據(jù)包時(shí)將檢查每個(gè)傳入數(shù)據(jù)包的CRC,通過檢測ERXFCON.CRCEN位來判斷輸入數(shù)據(jù)包的CRC是否正確。ENC28J60在發(fā)送數(shù)據(jù)包時(shí),將自動(dòng)生成一個(gè)有效的CRC并發(fā)送它。發(fā)送數(shù)據(jù)包的CRC亦可由主控芯片來提供。



ENC28J60存儲器構(gòu)成

    ENC28J60的存儲器分為三種:控制寄存器、以太網(wǎng)緩沖寄存器、PHY寄存器。
     控制寄存器用于進(jìn)行ENC28J60的配置、控制和狀態(tài)獲取,可通過SPI接口直接讀寫控制寄存器。

ENC28J60的控制寄存器通常分為ETH、MAC和MII三組寄存器,其中“E”開頭的為ETH組,“MA”開頭的寄存器屬于MAC組,“MI”開頭的屬于MII組。

     以太網(wǎng)緩沖寄存器包含一個(gè)供以太網(wǎng)控制器使用的發(fā)送和接收存儲空間,可通過SPI接口對該存儲空間的容量進(jìn)行編程,只可通過讀寫緩沖器的SPI指令來訪問以太網(wǎng)緩沖器。
    PHY寄存器用于進(jìn)行PHY模塊的配置、控制和狀態(tài)獲取,不可以通過SPI接口直接訪問這些寄存器,只可通過MAC中的MII訪問這些寄存器。


ENC28J60存儲器結(jié)構(gòu)圖如下:


ENC28J60的寄存器很多,操作這些寄存器需要一個(gè)良好的代碼組織工作。在AVRNET項(xiàng)目中,把ENC28J60的驅(qū)動(dòng)分解成ENC28J60.h文件和ENC28J60.c文件。H文件中主要描述ENC28J60寄存器的基本定義,而C文件主要實(shí)現(xiàn)了這些寄存器的操作。
控制寄存器被分布在4個(gè)不同的bank中,也就是說存在地址相同的寄存器,但是這些寄存器卻位于不同的分區(qū)中,在操作寄存器之前必須選中正確的bank。
雖然存在4個(gè)bank,但是有5個(gè)寄存器在4個(gè)bank的位置相同,它們是EIE、EIR、ESTATECON1、ECON2。不言而喻,這5個(gè)寄存器將會非常重要。
AVRNET項(xiàng)目中,寄存器被定義成8位長度,而這8位長度包含了三個(gè)部分,地址bit7(最高位)用以區(qū)分PHYMAC寄存器;地址bit6bit5用以區(qū)分BANK,2位空間正好區(qū)分4個(gè)BANK;地址的最后5位才是寄存器的地址。通過這種方式就可以區(qū)分所有的寄存器了。列舉了幾行代碼。由于頭文件很長,所以不全部列出。
// bank0 寄存器
#define ERDPTL           (0x00|0x00)
#define ERDPTH           (0x01|0x00)
#define EWRPTL           (0x02|0x00)
// bank1 寄存器
#define EHT0             (0x00|0x20)
#define EHT1             (0x01|0x20)
#define EHT2             (0x02|0x20)
// bank2 寄存器
#define MACON1          (0x00|0x40|0x80)
#define MACON2          (0x01|0x40|0x80)
#define MACON3          (0x02|0x40|0x80)
//bank3 寄存器
#define MAADR1          (0x00|0x60|0x80)
#define MAADR0          (0x01|0x60|0x80)
#define MAADR3          (0x02|0x60|0x80)
       例如ERDPTH為位于BANK0的以太網(wǎng)寄存器,第一個(gè)數(shù)字0x01代表BANK0中的地址,該地址為0x01,第二個(gè)數(shù)字0x00代表BANK編號,該編號為0,意味第0個(gè)BANK;EHT1為位于BANK1中的控制寄存器,第二個(gè)0x20代表BANK地址為1,請注意由于BANK編號被保存在bit6和bit5,所以此處為0x20,絕不是0x10;MACON2為位于bank2的以太網(wǎng)寄存器,第一個(gè)數(shù)字0x01代表在該BANK中的寄存器地址,第二個(gè)數(shù)字0x40代表BANK編號,而第三個(gè)數(shù)字0x80代表該寄存器為以太網(wǎng)寄存器或是PHY寄存器,這些寄存器的操作和控制寄存器有區(qū)別。
為了方便寄存器操作,h文件中還定義了寄存器地址操作的掩碼,簡單而言就是需要查看哪些位,不需要查看哪些位。
/* 寄存器地址掩碼 */
#defineADDR_MASK       0x1F
/* 存儲區(qū)域掩碼 */
#defineBANK_MASK       0x60
/* MAC和MII寄存器掩碼*/
#defineSPRD_MASK       0x80
       另外還有比較特殊的5個(gè)控制寄存器,EIE,EIR,ESTAT,ECON2和ECON1
/* 關(guān)鍵寄存器 */
#defineEIE                    0x1B
#defineEIR                    0x1C
#defineESTAT                  0x1D
#defineECON2                 0x1E
#defineECON1                 0x1F
2.2 寄存器操作命令
       寄存器操作命令也可稱為寄存器操作碼。為了實(shí)現(xiàn)寄存器的操作,ENC28J60定義了6+1個(gè)寄存器操作命令(操作碼)。操作相關(guān)寄存器至少有讀寄存器命令,寫寄存器命令;發(fā)送或接收以太網(wǎng)數(shù)據(jù)則必有寫緩沖區(qū)命令或讀緩沖區(qū)命令;為了加快操作,對于某些控制寄存器而言還可以有置位或者清零某位的命令;最后加上一個(gè)軟件復(fù)位命令,錦上添花。
1.  <font size="3">/* 讀控制寄存器 */
2.  #define ENC28J60_READ_CTRL_REG         0x00
3.  /* 讀緩沖區(qū) */
4.  #define ENC28J60_READ_BUF_MEM         0x3A
5.  /* 寫控制寄存器 */
6.  #define ENC28J60_WRITE_CTRL_REG         0x40
7.  /* 寫緩沖區(qū) */
8.  #define ENC28J60_WRITE_BUF_MEM         0x7A
9.  /* 位域置位 */
10. #define ENC28J60_BIT_FIELD_SET             0x80
11. /* 位域清零 */
12. #define ENC28J60_BIT_FIELD_CLR                   0xA0
13. /* 系統(tǒng)復(fù)位 */
14. #define ENC28J60_SOFT_RESET                      0xFF</font>
本帖最后由 xukai871105 于2013-2-10 19:34 編輯

1前言
嵌入式以太網(wǎng)開發(fā),可以分為兩個(gè)部分,一個(gè)是以太網(wǎng)收發(fā)芯片的使用,一個(gè)是嵌入式以太網(wǎng)協(xié)議棧的實(shí)現(xiàn)。以太網(wǎng)收發(fā)芯片的使用要比串口收發(fā)芯片的使用復(fù)雜的多,市面上流通比較廣泛的以太網(wǎng)收發(fā)芯片種類還不少,有SPI接口的ENC28J60,也有并口形式的RTL8019S,CS8900A等。嵌入式以太網(wǎng)協(xié)議棧有著名的uIP協(xié)議棧,Lwip協(xié)議棧,還有其他嵌入式高手開發(fā)的協(xié)議棧。無論是硬件還是軟件,都無法分出高下,適合項(xiàng)目需求的才是最好的。
1.1 寫作理由
        在前言的最后,再說明一下我寫作的理由。以前從淘寶上購買過ENC28J60,店家信誓旦旦地說能提供51 AVRLPC STM32等多個(gè)平臺的代碼,可以實(shí)現(xiàn)一個(gè)網(wǎng)頁控制LED。頭腦一熱買了回來,買回來才發(fā)現(xiàn),店家提供的資料零零散散,非常難懂,雖然不貴僅僅需要40多元,現(xiàn)在只需要20多元。但是總感覺有欺騙的嫌疑,這也可以映射出中國人做技術(shù)買賣的原則,產(chǎn)品多是實(shí)物而非服務(wù)。幾經(jīng)周轉(zhuǎn),發(fā)現(xiàn)原來這些ENC28J60的代碼都出自一個(gè)地方——AVRNET,源自老外的一個(gè)開源項(xiàng)目。把最原始的代碼拿來細(xì)細(xì)品味,以太網(wǎng)協(xié)議就不那么神秘了。在這里說一下ENC28J60的使用,熟悉了ENC28J60的驅(qū)動(dòng)可以分幾步走。第一步,通過ENC28J60移植uIP或者lwIP協(xié)議棧,實(shí)現(xiàn)TCP或是UDP通信,第二,順著AVRNET項(xiàng)目走,實(shí)現(xiàn)一個(gè)簡單的web服務(wù)器,運(yùn)行靜態(tài)或者動(dòng)態(tài)網(wǎng)頁。嵌入式以太網(wǎng)和計(jì)算機(jī)以太網(wǎng)開發(fā)不同,對于TCP通信而言沒有windwossocke用,對于網(wǎng)頁編程而言也沒有ISS或PHP,所示實(shí)現(xiàn)起來會比較麻煩,但是也非常有樂趣。
1.2 平臺說明
硬件平臺Atmega32 + proteus 7.10+WinPcap
編譯平臺 AVRStudio 6
        關(guān)于硬件平臺,由于AVRNET項(xiàng)目采用ATmega32,分析的時(shí)候也采用Atmega32。就ENC28J60而言,對于其他的平臺,例如STM32或是MSP而言只需要修改SPI操作即可。由于沒有硬件平臺,所以使用proteus仿真,注意仿真以太網(wǎng)是proteus需要安裝WinPcap。
        關(guān)于編譯平臺,AVRNET項(xiàng)目使用的是AVRStdui 4.XX。這個(gè)版本稍顯老舊,我就進(jìn)行了相關(guān)修改,在AVRStudio 6中重新編譯,并修正了幾個(gè)錯(cuò)誤。當(dāng)然其他的編譯平臺也適用。
        總結(jié)一句,平臺選用原則——“求同存異”。
1.3 資料準(zhǔn)備
        以太網(wǎng)開發(fā)是非常復(fù)雜的工作,在開始之前最好先大致瀏覽一些ENC28J60的使用手冊,MICROCHIP可以下載,中文版本閱讀非常方便。除此之外,需要認(rèn)真閱讀TCPIP相關(guān)知識,推薦一本圖書《嵌入式InternetTCP/IP基礎(chǔ)、實(shí)現(xiàn)和應(yīng)用》。
        嵌入式開發(fā)總是一個(gè)反復(fù)借鑒的過程。該部分代碼參考了AVRNET項(xiàng)目和奮斗開發(fā)板的相關(guān)范例。
2寄存器和寄存器操作
      ENC28J60的寄存器很多,操作這些寄存器需要一個(gè)良好的代碼組織工作。在AVRNET項(xiàng)目中,把ENC28J60的驅(qū)動(dòng)分解成ENC28J60.h文件和ENC28J60.c文件。H文件中主要描述ENC28J60寄存器的基本定義,而C文件主要實(shí)現(xiàn)了這些寄存器的操作。
2.1寄存器定義
首先分析一下ENC28J60頭文件。閱讀數(shù)據(jù)手冊之后,會發(fā)現(xiàn)ENC28J60寄存器數(shù)量較多,通過分析和整理,操作ENC28J60的寄存器需要注意以下3點(diǎn)。
(1)  共有三種不同形式的寄存器——控制寄存器,以太網(wǎng)寄存器PHY寄存器,不同的寄存器以不同的字母開頭,以E、 MA和MI加以區(qū)分。操作這三種不同的寄存器需要不同的組合命令。
(2)  寄存器被分布在4個(gè)不同的bank中,也就是說存在地址相同的寄存器,但是這些寄存器卻位于不同的分區(qū)中,在操作寄存器之前必須選中正確的bank。
(3)  雖然存在4個(gè)bank,但是有5個(gè)寄存器在4個(gè)bank的位置相同,它們是EIEEIR、ESTAT、ECON1ECON2。不言而喻,這5個(gè)寄存器將會非常重要。
AVRNET項(xiàng)目中,寄存器被定義成8位長度,而這8位長度包含了三個(gè)部分,地址bit7(最高位)用以區(qū)分PHYMAC寄存器;地址bit6bit5用以區(qū)分BANK,2位空間正好區(qū)分4個(gè)BANK;地址的最后5位才是寄存器的地址。通過這種方式就可以區(qū)分所有的寄存器了。列舉了幾行代碼。由于頭文件很長,所以不全部列出。
//bank0 寄存器
#define ERDPTL           (0x00|0x00)
#define ERDPTH           (0x01|0x00)
#define EWRPTL           (0x02|0x00)
//bank1 寄存器
#define EHT0             (0x00|0x20)
#define EHT1             (0x01|0x20)
#define EHT2             (0x02|0x20)
//bank2 寄存器
#define MACON1          (0x00|0x40|0x80)
#define MACON2          (0x01|0x40|0x80)
#define MACON3          (0x02|0x40|0x80)
//bank3 寄存器
#define MAADR1          (0x00|0x60|0x80)
#define MAADR0          (0x01|0x60|0x80)
#define MAADR3          (0x02|0x60|0x80)
      例如ERDPTH為位于BANK0的以太網(wǎng)寄存器,第一個(gè)數(shù)字0x01代表BANK0中的地址,該地址為0x01,第二個(gè)數(shù)字0x00代表BANK編號,該編號為0,意味第0個(gè)BANK;EHT1為位于BANK1中的控制寄存器,第二個(gè)0x20代表BANK地址為1,請注意由于BANK編號被保存在bit6和bit5,所以此處為0x20,絕不是0x10;MACON2為位于bank2的以太網(wǎng)寄存器,第一個(gè)數(shù)字0x01代表在該BANK中的寄存器地址,第二個(gè)數(shù)字0x40代表BANK編號,而第三個(gè)數(shù)字0x80代表該寄存器為以太網(wǎng)寄存器或是PHY寄存器,這些寄存器的操作和控制寄存器有區(qū)別。
      為了方便寄存器操作,h文件中還定義了寄存器地址操作的掩碼,簡單而言就是需要查看哪些位,不需要查看哪些位。
/* 寄存器地址掩碼 */
#defineADDR_MASK       0x1F
/* 存儲區(qū)域掩碼 */
#defineBANK_MASK       0x60
/* MAC和MII寄存器掩碼*/
#defineSPRD_MASK       0x80
      另外還有比較特殊的5個(gè)控制寄存器,EIE,EIR,ESTAT,ECON2和ECON1
/* 關(guān)鍵寄存器 */
#defineEIE                   0x1B
#defineEIR                   0x1C
#defineESTAT                  0x1D
#defineECON2                 0x1E
#defineECON1                 0x1F
2.2寄存器操作命令
      寄存器操作命令也可稱為寄存器操作碼。為了實(shí)現(xiàn)寄存器的操作,ENC28J60定義了6+1個(gè)寄存器操作命令(操作碼)。操作相關(guān)寄存器至少有讀寄存器命令,寫寄存器命令;發(fā)送或接收以太網(wǎng)數(shù)據(jù)則必有寫緩沖區(qū)命令或讀緩沖區(qū)命令;為了加快操作,對于某些控制寄存器而言還可以有置位或者清零某位的命令;最后加上一個(gè)軟件復(fù)位命令,錦上添花。
1.  <fontsize="3">/* 讀控制寄存器 */
2.  #define ENC28J60_READ_CTRL_REG         0x00
3.  /* 讀緩沖區(qū) */
4.  #defineENC28J60_READ_BUF_MEM          0x3A
5.  /* 寫控制寄存器 */
6.  #defineENC28J60_WRITE_CTRL_REG          0x40
7.  /* 寫緩沖區(qū) */
8.  #defineENC28J60_WRITE_BUF_MEM          0x7A
9.  /* 位域置位 */
10. #defineENC28J60_BIT_FIELD_SET             0x80
11. /* 位域清零 */
12. #defineENC28J60_BIT_FIELD_CLR                    0xA0
13. /* 系統(tǒng)復(fù)位 */
14. #defineENC28J60_SOFT_RESET                       0xFF</font>
復(fù)制代碼
2.3接收和發(fā)送緩沖區(qū)分配
      以太網(wǎng)數(shù)據(jù)的接收和發(fā)送離不開驅(qū)動(dòng)芯片內(nèi)部的RAM,也可稱之為硬件緩沖區(qū)。ENC28J60包括8K的硬件緩沖區(qū),該硬件緩沖區(qū)一部分被接收緩沖區(qū)使用,另一部分為發(fā)送緩沖區(qū)使用。操作ENC28J60的最終目的為操作該硬件緩沖區(qū)。執(zhí)行以太網(wǎng)發(fā)送命令時(shí),向發(fā)送緩沖區(qū)中填充數(shù)據(jù),并觸發(fā)相關(guān)寄存器發(fā)送以太網(wǎng)數(shù)據(jù);執(zhí)行以太網(wǎng)接收命令時(shí),通過查詢相關(guān)寄存器或者外部中斷的方式獲得以太網(wǎng)數(shù)據(jù)輸入事件,接著從接收緩沖區(qū)中讀取相關(guān)數(shù)據(jù)。
(1)  把緩沖區(qū)劃分為兩個(gè)部分。把8K的硬件緩沖區(qū)劃分為兩個(gè)部分至少需要四個(gè)參數(shù),接收緩沖區(qū)需要一個(gè)起始地址和一個(gè)結(jié)束地址加以描述,發(fā)送緩沖區(qū)也需要一個(gè)起始地址和一個(gè)結(jié)束地址加以描述。最理想的方式,兩個(gè)緩沖區(qū)完全占據(jù)了8K的硬件緩沖區(qū),完美地利用這一空間。由于ENC28J60的寄存器長度為8位,而硬件緩沖區(qū)的大小為8K,所以前面提到的4個(gè)地址需要8個(gè)寄存器才可以完全描述,需要把單個(gè)地址分為高8位和低8位。在AVRNET項(xiàng)目中,接收緩沖區(qū)較大,而發(fā)送緩沖區(qū)較小。在以太網(wǎng)協(xié)議中,最大的報(bào)文長度為1518字節(jié),而最小報(bào)文長度為60字節(jié)。發(fā)送緩沖區(qū)等于或略大于1518字節(jié),剩余的部分全部分配給接收緩沖區(qū)。接收緩沖區(qū)較大也是考慮到AVR的處理能力有限,若某個(gè)時(shí)間點(diǎn)收到多個(gè)以太網(wǎng)報(bào)文,可以先把報(bào)文閑置與硬件緩沖區(qū)中,待空閑時(shí)再從緩沖區(qū)中取出。
/* 接收緩沖區(qū)起始地址 */
#defineRXSTART_INIT               0x00
/* 接收緩沖區(qū)停止地址 */
#defineRXSTOP_INIT                (0x1FFF - 0x0600 - 1)
/* 發(fā)送緩沖區(qū)起始地址 發(fā)送緩沖區(qū)大小約1500字節(jié)*/
#defineTXSTART_INIT               (0x1FFF - 0x0600)
/* 發(fā)送緩沖區(qū)停止地址 */
#defineTXSTOP_INIT                0x1FFF
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image005.jpg

圖硬件緩沖區(qū)結(jié)構(gòu)
(2)  對于發(fā)送緩沖區(qū)而言,需要指定發(fā)送緩沖區(qū)寫指針,使用寫緩沖區(qū)命令操作該部分緩沖區(qū),寫指針的地址會不斷增長,若遇到結(jié)束地址會重新返回起始地址。對于接收緩沖區(qū)而言就稍微復(fù)雜一點(diǎn),每次讀取之前必須明確該次操作時(shí)的讀指針位置,根據(jù)前文的代碼,緩沖區(qū)讀指針的起始地址為0,在第一次讀操作發(fā)生之后需要立即設(shè)置下次讀操作的讀指針地址。ENC28J60讀緩沖區(qū)時(shí),讀取的數(shù)據(jù)并不全是以太網(wǎng)的數(shù)據(jù),在以太網(wǎng)數(shù)據(jù)之前還有下一個(gè)數(shù)據(jù)包的地址指針占兩個(gè)字節(jié),接收狀態(tài)向量占4個(gè)字節(jié),接著才是以太網(wǎng)數(shù)據(jù)包,該數(shù)據(jù)包包括目標(biāo)MAC地址,源MAC地址,數(shù)據(jù)包類型等等;最后為CRC校驗(yàn)和。在接收狀態(tài)向量的起始2個(gè)字節(jié)為該以太網(wǎng)數(shù)據(jù)包的長度,該參數(shù)也是非常有用的參數(shù)。
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image007.jpg

3 寄存器操作實(shí)現(xiàn)
     ENC28j60的寄存器操作分為2+2+2部分,分別為寫寄存器和讀寄存器部分,讀緩沖區(qū)和寫緩沖區(qū)部分,寫PHY寄存器和讀PHY寄存器部分。
3.1 讀寫寄存器
       讀或?qū)懠拇嫫鞯暮瘮?shù)如下
1.  <font size="3">unsignedchar enc28j60Read(unsigned char address)
2.  {
3.         /* 設(shè)定寄存器地址區(qū)域 */
4.        enc28j60SetBank(address);
5.         /* 讀取寄存器值 發(fā)送讀寄存器命令和地址 */
6.         returnenc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
7.  }
8.  void enc28j60Write(unsigned charaddress, unsigned char data)
9.  {
10.        /* 設(shè)定寄存器地址區(qū)域 */
11.       enc28j60SetBank(address);
12.        /* 寫寄存器值 發(fā)送寫寄存器命令和地址 */
13.       enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
14. }</font>
復(fù)制代碼
       讀寫寄存器的分為兩步,第一步為選定寄存器的BANK編號,第二步為使用寫命令或讀命令,操作指定地址的寄存器。在ENC28J60中,由ECON1中的某兩位保存BANK編號,ECON1是比較特殊的控制寄存器,在4個(gè)BANK中具有該寄存器且該寄存器的地址相同。Enc28j60Bank為全局變量,用于保存當(dāng)前的BANK編號,如果兩次操作控制寄存器在同一個(gè)BANK時(shí),該變量保持不變,若兩次操作的控制寄存器位于不同的BANK,那么BANK的值會變?yōu)樾碌腂ANK編號。
1.  <font size="3">voidenc28j60SetBank(unsigned char address)
2.  {
3.         /* 計(jì)算本次寄存器地址在存取區(qū)域的位置 */
4.         if((address& BANK_MASK) != Enc28j60Bank)
5.         {
6.      /* 清除ECON1的BSEL1 BSEL0 詳見數(shù)據(jù)手冊15頁 */
7.     enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
8.      /* 請注意寄存器地址的宏定義,bit6 bit5代碼寄存器存儲區(qū)域位置 */
9.     enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address &BANK_MASK)>>5);
10.     /* 重新確定當(dāng)前寄存器存儲區(qū)域 */
11.     Enc28j60Bank = (address& BANK_MASK);
12.        }
13. }</font>
復(fù)制代碼
1.  <font size="3">unsignedchar enc28j60ReadOp(unsigned char op, unsigned char address)
2.  {
3.         unsigned chardat = 0;
4.        
5.         /* CS拉低 使能ENC28J60 */
6.        ENC28J60_CSL();
7.         /* 操作碼和地址 */
8.         dat = op |(address & ADDR_MASK);
9.    /* 通過SPI寫數(shù)據(jù)*/
10.       spi_sendbyte(dat);
11.   /* 通過SPI讀出數(shù)據(jù) */
12.        dat =spi_sendbyte(0xFF);
13.      
14.   /* 如果是MAC和MII寄存器,第一個(gè)讀取的字節(jié)無效,該信息包含在地址的最高位 */
15.        if(address& 0x80)
16.        {
17.              /* 再次通過SPI讀取數(shù)據(jù) */
18.     dat = spi_sendbyte(0xFF);
19.        }
20.      
21.   /* CS拉高 禁止ENC28J60 */
22.       ENC28J60_CSH();
23.  
24.   /* 返回?cái)?shù)據(jù) */
25.        return dat;
26. }</font>
復(fù)制代碼
讀控制寄存器實(shí)際上就是嚴(yán)格遵守?cái)?shù)據(jù)手冊的操作要求,一次編寫程序。在這里由于讀MAC和MII寄存器時(shí),第一個(gè)接收到的字節(jié)為無效字節(jié),第二個(gè)字節(jié)才為有效字節(jié)。程序通過寄存器地址的最高位來判斷是否為MAC或MII寄存器。寫寄存器函數(shù)較為簡單,第一次字節(jié)包括操作碼和寄存器地址,第二個(gè)字節(jié)則為數(shù)據(jù)。在這兩個(gè)函數(shù)中參數(shù)op為ENC28J60的指令,或稱之為操作碼,該指令占據(jù)了SPI第一個(gè)字節(jié)的前3位,參數(shù)address為寄存器地址,參數(shù)data為寄存器的具體值。
這兩個(gè)函數(shù)和硬件發(fā)生某些關(guān)系,ENC28J60_CSL()和ENC28J60_CSH()為操作CS端口的操作宏,而spi_sendbyte()可通過SPI發(fā)送一個(gè)字節(jié)。修改這些函數(shù)即可在其他平臺上使用ENC28J60。不過請?zhí)貏e注意,在使用其他開發(fā)板時(shí)由于SPI總線上可能掛載多個(gè)設(shè)備,單獨(dú)使用ENC28J60時(shí)需要把其他設(shè)備的CS端口拉高,或安裝一個(gè)上拉電阻。
1.  <font size="3">unsignedchar enc28j60ReadOp(unsigned char op, unsigned char address)
2.  {
3.         unsigned chardat = 0;
4.        
5.         /* CS拉低 使能ENC28J60 */
6.        ENC28J60_CSL();
7.         /* 操作碼和地址 */
8.         dat = op |(address & ADDR_MASK);
9.    /* 通過SPI寫數(shù)據(jù)*/
10.       spi_sendbyte(dat);
11.   /* 通過SPI讀出數(shù)據(jù) */
12.        dat =spi_sendbyte(0xFF);
13.      
14.   /* 如果是MAC和MII寄存器,第一個(gè)讀取的字節(jié)無效,該信息包含在地址的最高位 */
15.        if(address &0x80)
16.        {
17.              /* 再次通過SPI讀取數(shù)據(jù) */
18.     dat = spi_sendbyte(0xFF);
19.        }
20.      
21.   /* CS拉高 禁止ENC28J60 */
22.       ENC28J60_CSH();
23.  
24.   /* 返回?cái)?shù)據(jù) */
25.        return dat;
26. }
27. void enc28j60WriteOp(unsigned char op,unsigned char address, unsigned char data)
28. {
29.        unsigned chardat = 0;
30.   /* 使能ENC28J60 */                                                
31.       ENC28J60_CSL();        
32.   /* 通過SPI發(fā)送 操作碼和寄存器地址 */                        
33.        dat = op |(address & ADDR_MASK);
34.   /* 通過SPI1發(fā)送數(shù)據(jù) */
35.       spi_sendbyte(dat);
36.   /* 準(zhǔn)備寄存器數(shù)值 */                           
37.        dat = data;
38.   /* 通過SPI發(fā)送數(shù)據(jù) */
39.       spi_sendbyte(dat);
40.   /* 禁止ENC28J60 */                     
41.       ENC28J60_CSH();   
42. }</font>
復(fù)制代碼
3.2 讀寫緩沖區(qū)
       讀寫緩沖區(qū)的操作也是易于理解的。需要說明的是,兩個(gè)函數(shù)具有相同的輸入?yún)?shù),參數(shù)len代表被操作數(shù)據(jù)的長度,pdata為被操作數(shù)據(jù)的指針。和寄存器讀寫函數(shù)相似,發(fā)送或接收數(shù)據(jù)之前需要發(fā)送特定的操作碼。
1.  <font size="3">voidenc28j60ReadBuffer(unsigned int len, unsigned char* pdata)
2.  {
3.    /* 使能ENC28J60 */
4.    ENC28J60_CSL();
5.         /* 通過SPI發(fā)送讀取緩沖區(qū)命令*/
6.         spi_sendbyte(ENC28J60_READ_BUF_MEM);
7.    /* 循環(huán)讀取 */
8.         while(len)
9.         {
10.     len--;
11.     /* 讀取數(shù)據(jù) */
12.     *pdata = (unsignedchar)spi_sendbyte(0);
13.     /* 地址指針累加 */
14.     pdata++;
15.        }
16.   /* 增加字符串結(jié)尾 便于操作 */
17.        *pdata='\0';
18.   /* 禁止ENC28J60 */
19.        ENC28J60_CSH();
20. }
21. void enc28j60WriteBuffer(unsigned intlen, unsigned char* pdata)
22. {
23.   /* 使能ENC28J60 */
24.   ENC28J60_CSL();
25.        /* 通過SPI發(fā)送寫取緩沖區(qū)命令*/
26.       spi_sendbyte(ENC28J60_WRITE_BUF_MEM);
27.      
28.   /* 循環(huán)發(fā)送 */
29.        while(len)
30.        {
31.              len--;
32.     /* 發(fā)送數(shù)據(jù) */
33.              spi_sendbyte(*pdata);
34.     /* 地址指針累加 */
35.              pdata++;
36.        }
37.  
38.   /* 禁止ENC28J60 */
39.       ENC28J60_CSH();
40. }</font>
復(fù)制代碼
3.3 讀寫PHY寄存器
       PHY寄存器和由ENC28J60控制的LED指示燈有關(guān),控制這些寄存器可以控制這兩個(gè)LED的驅(qū)動(dòng)方式,和發(fā)生相應(yīng)事件時(shí)LED的顯示方式。一般情況下,一個(gè)LED指示燈常亮,顯示接收和發(fā)送活動(dòng),另一個(gè)LED指示燈顯示接收活動(dòng),有數(shù)據(jù)輸入時(shí)產(chǎn)生一個(gè)點(diǎn)亮脈沖。PHY是比較特殊的寄存器,先要想一個(gè)控制寄存器寫入PHY寄存器的地址,再向兩個(gè)控制寄存器依次寫入PHY寄存器的具體數(shù)據(jù)的高8位和低8位,最后等待PHY寄存器操作完成。
1.  <font size="3">voidenc28j60PhyWrite(unsigned char address, unsigned int data)
2.  {
3.         /* 向MIREGADR寫入地址 詳見數(shù)據(jù)手冊19頁*/
4.        enc28j60Write(MIREGADR, address);
5.         /* 寫入低8位數(shù)據(jù) */
6.        enc28j60Write(MIWRL, data);
7.    /* 寫入高8位數(shù)據(jù) */
8.        enc28j60Write(MIWRH, data>>8);
9.         /* 等待PHY寄存器寫入完成 */
10.       while(enc28j60Read(MISTAT) & MISTAT_BUSY);
11. }</font>
復(fù)制代碼
4 ENC28J60寫操作
       ENC28J60的寄存器操作時(shí)ENC28J60初始化,發(fā)送以太網(wǎng)數(shù)據(jù)和接收以太網(wǎng)數(shù)據(jù)的基礎(chǔ)。通過ENC28J60進(jìn)行以太網(wǎng)發(fā)送數(shù)據(jù)操作,本質(zhì)上為操作硬件緩沖區(qū)的發(fā)送緩沖區(qū)部分。每次發(fā)送時(shí)總是從發(fā)送緩沖區(qū)的起始地址開始填充數(shù)據(jù),數(shù)據(jù)填充的結(jié)束地址和數(shù)據(jù)的輸入長度有關(guān)。操作完發(fā)送緩沖區(qū)的大小之后可向發(fā)送緩沖區(qū)填充數(shù)據(jù),即調(diào)用ENC28J60_WRITE_BUF_MEM操作碼,接著置位ECON1中的 ECON1_TXRTS位啟動(dòng)發(fā)送,并使用等待法不斷查詢是否發(fā)送完畢;镜乃悸愤是和SPI或UART發(fā)送數(shù)據(jù)相似,即填充數(shù)據(jù),啟動(dòng)發(fā)送,查詢發(fā)送完成。寫操作的輸入?yún)?shù)為數(shù)據(jù)包的長度len和數(shù)據(jù)包指針packet,該參數(shù)正好和uIP的網(wǎng)絡(luò)層操作函數(shù)相對應(yīng)。若是LwIP協(xié)議,輸入?yún)?shù)將會是pBuf這種自定義數(shù)據(jù)結(jié)構(gòu),需要經(jīng)過適當(dāng)?shù)男薷牟艖?yīng)用于lwIP協(xié)議棧。
1.  <font size="3">voidenc28j60PacketSend(unsigned int len, unsigned char* packet)
2.  {
3.         /* 查詢發(fā)送邏輯復(fù)位位 */
4.         while((enc28j60Read(ECON1)& ECON1_TXRTS)!= 0);
5.   
6.    /* 設(shè)置發(fā)送緩沖區(qū)起始地址 */   
7.        enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF);
8.        enc28j60Write(EWRPTH, TXSTART_INIT >> 8);
9.   
10.        /* 設(shè)置發(fā)送緩沖區(qū)結(jié)束地址 該值對應(yīng)發(fā)送數(shù)據(jù)包長度 */  
11.       enc28j60Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);
12.       enc28j60Write(ETXNDH, (TXSTART_INIT + len) >>8);
13.  
14.        /* 發(fā)送之前發(fā)送控制包格式字 */
15.       enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
16.  
17.        /* 通過ENC28J60發(fā)送數(shù)據(jù)包 */
18.       enc28j60WriteBuffer(len, packet);
19.  
20.        /* 開始發(fā)送 */
21.        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET,ECON1, ECON1_TXRTS);
22.  
23.   /* 復(fù)位發(fā)送邏輯的問題 */
24.        if((enc28j60Read(EIR) & EIR_TXERIF) )
25.        {
26.              enc28j60SetBank(ECON1);
27.    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
28.   }
29. }</font>
復(fù)制代碼
5 ENC28J60讀操作
       讀操作要略比寫操作復(fù)雜。寫操作時(shí)每次總是從硬件發(fā)送緩沖區(qū)的起始地址開始操作,而讀操作時(shí)需要不斷修改接收緩沖區(qū)的讀指針地址,該參數(shù)需要通過NextPacketPtr完成,該變量為長度為16的全局變量。讀操作時(shí),先通過寄存器查看是否存在以太網(wǎng)數(shù)據(jù)包,讀EPKTCNT寄存器便可返回以太網(wǎng)數(shù)據(jù)包的個(gè)數(shù);若存在以太網(wǎng)數(shù)據(jù)包則設(shè)定讀指針的地址,執(zhí)行讀緩沖區(qū)操作,ENC28J60的以太網(wǎng)數(shù)據(jù)包中前兩個(gè)字節(jié)為下一個(gè)以太網(wǎng)數(shù)據(jù)包的起始地址,立即保存該參數(shù)至NextPacketPtr全局變量中;以太網(wǎng)數(shù)據(jù)包中的后兩個(gè)字節(jié)為該數(shù)據(jù)包的長度,該長度只從目標(biāo)MAC地址開始的數(shù)據(jù)包的長度,進(jìn)行處理時(shí)還應(yīng)該舍棄最后的4字節(jié)CRC校驗(yàn)結(jié)果;最重要的事情便是通過讀緩沖區(qū)操作碼把len長度的以太網(wǎng)數(shù)據(jù)讀出,讀出的目標(biāo)應(yīng)為軟件緩沖區(qū),例如定義在程序中的rxtx_buf。最后根據(jù)NextPacketPtr移動(dòng)讀指針以便下次操作,并通過操作ECON2的ECON2_PKTDEC位遞減了以太網(wǎng)數(shù)據(jù)包。
1.  <font size="3">unsignedint enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet)
2.  {
3.         unsigned intrxstat;
4.         unsigned intlen;
5.   
6.         /* 是否收到以太網(wǎng)數(shù)據(jù)包 */
7.         if(enc28j60Read(EPKTCNT) == 0 )
8.         {
9.               return(0);
10.     }
11.  
12.        /* 設(shè)置接收緩沖器讀指針 */
13.       enc28j60Write(ERDPTL, (NextPacketPtr));
14.       enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
15.  
16.   /* 接收數(shù)據(jù)包結(jié)構(gòu)示例 數(shù)據(jù)手冊43頁 */
17.  
18.        /* 讀下一個(gè)包的指針 */
19.       NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
20.        NextPacketPtr|= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
21.  
22.        /* 讀包的長度 */
23.       len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
24.        len |=enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
25.  
26.    /* 去除CRC校驗(yàn)部分 */
27.    len-= 4;
28.                  
29.        /* 讀取接收狀態(tài) */
30.       rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
31.        rxstat |=enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
32.  
33.        /* 限制檢索的長度  */
34.   if (len > maxlen-1)
35.        {
36.     len = maxlen-1;
37.   }
38.   /* 檢查CRC和符號錯(cuò)誤 */
39.   /* ERXFCON.CRCEN是默認(rèn)設(shè)置。通常我們不需要檢查 */
40.   if ((rxstat & 0x80)==0)
41.        {
42.          //無效的
43.          len = 0;
44.        }
45.        else
46.        {
47.     /* 從接收緩沖器中復(fù)制數(shù)據(jù)包 */
48.     enc28j60ReadBuffer(len,packet);
49.   }
50.  
51.   /* 移動(dòng)接收緩沖區(qū) 讀指針*/
52.       enc28j60Write(ERXRDPTL, (NextPacketPtr));
53.       enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
54.  
55.        /* 數(shù)據(jù)包遞減 */
56.       enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
57.  
58.   /* 返回長度 */
59.        return(len);
60. }</font>
復(fù)制代碼
6 ENC28J60初始化操作
       ENC28J60的操作比較瑣碎。第一,進(jìn)行CS端口的相關(guān)配置,即把該端口設(shè)置為輸出狀態(tài),該部分代碼可以出現(xiàn)在任何硬件初始化代碼中,例如可以把所有的IO操作放入gpio_config中;第二,進(jìn)行軟件復(fù)位,并通過查詢ESTAT的ESTAT_CLKRDY標(biāo)志位確定是否復(fù)位完成;第二,初始化NextPacketPtr變量,該變量的初值為發(fā)送緩沖區(qū)的起始地址;第三,配置發(fā)送和接收緩沖區(qū)的區(qū)間;第四,若干參數(shù)配置,請看代碼注釋部分,ENC28J60具有自動(dòng)填充0 的功能,即發(fā)送報(bào)文長度低于以太網(wǎng)最小報(bào)文長度時(shí)可以填充0至最小長度;第五,寫入MAC地址,由于ENC28J60內(nèi)部沒有全球唯一的MAC地址,所以該地址需要軟件填寫。但是這種軟件填寫方式存在缺陷,實(shí)際應(yīng)用中可以含有全球唯一的MAC地址的EEPROM,從EERPOM讀取MAC地址并用該地址初始化ENC28J60;第六,初始化中斷,并使能接收,ENC28J60含有多個(gè)中斷,最重要的有全局中斷和數(shù)據(jù)包帶接收中斷。
1.  <font size="3">voidenc28j60Init(unsigned char* macaddr)
2.  {
3.    /* CS端口為輸出 */
4.    DDRB |= (1<<4);
5.   
6.    /* 禁止ENC28J60 */
7.    ENC28J60_CSH();
8.         /* ENC28J60軟件復(fù)位 該函數(shù)可以改進(jìn)*/
9.        enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
10.   /*查詢ESTAT.CLKRDY位*/
11.       while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
12.     
13.        /* 設(shè)置接收緩沖區(qū)起始地址 該變量用于每次讀取緩沖區(qū)時(shí)保留下一個(gè)包的首地址 */
14.        NextPacketPtr= RXSTART_INIT;
15.  
16.   /* 設(shè)置接收緩沖區(qū) 起始指針*/
17.       enc28j60Write(ERXSTL, RXSTART_INIT & 0xFF);
18.       enc28j60Write(ERXSTH, RXSTART_INIT >> 8);
19.  
20.   /* 設(shè)置接收緩沖區(qū) 讀指針*/
21.       enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
22.       enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
23.  
24.   /* 設(shè)置接收緩沖區(qū) 結(jié)束指針 */
25.        enc28j60Write(ERXNDL,RXSTOP_INIT&0xFF);
26.       enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
27.  
28.        /* 設(shè)置發(fā)送緩沖區(qū) 起始指針 */
29.       enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
30.       enc28j60Write(ETXSTH, TXSTART_INIT>>8);
31.        /* 設(shè)置發(fā)送緩沖區(qū) 結(jié)束指針 */
32.        enc28j60Write(ETXNDL,TXSTOP_INIT&0xFF);
33.       enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
34.  
35.   /* 使能單播過濾 使能CRC校驗(yàn) 使能 格式匹配自動(dòng)過濾*/
36.       enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
37.       enc28j60Write(EPMM0, 0x3f);
38.       enc28j60Write(EPMM1, 0x30);
39.       enc28j60Write(EPMCSL, 0xf9);
40.       enc28j60Write(EPMCSH, 0xf7);
41.  
42.   /* 使能MAC接收 允許MAC發(fā)送暫?刂茙 當(dāng)接收到暫?刂茙瑫r(shí)停止發(fā)送*/
43.   /* 數(shù)據(jù)手冊34頁 */
44.       enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
45.  
46.   /* 退出復(fù)位狀態(tài) */
47.       enc28j60Write(MACON2, 0x00);
48.  
49.   /* 用0填充所有短幀至60字節(jié)長 并追加一個(gè)CRC 發(fā)送CRC使能 幀長度校驗(yàn)使能 MAC全雙工使能*/
50.        /* 提示 由于ENC28J60不支持802.3的自動(dòng)協(xié)商機(jī)制, 所以對端的網(wǎng)絡(luò)卡需要強(qiáng)制設(shè)置為全雙工 */
51.       enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
52.  
53.   /* 填入默認(rèn)值 */
54.        enc28j60Write(MAIPGL,0x12);
55.   /* 填入默認(rèn)值 */
56.       enc28j60Write(MAIPGH, 0x0C);
57.   /* 填入默認(rèn)值 */
58.       enc28j60Write(MABBIPG, 0x15);
59.  
60.   /* 最大幀長度 */
61.       enc28j60Write(MAMXFLL, MAX_FRAMELEN & 0xFF);
62.       enc28j60Write(MAMXFLH, MAX_FRAMELEN >> 8);
63.  
64.   /* 寫入MAC地址 */
65.       enc28j60Write(MAADR5, macaddr[0]);     
66.       enc28j60Write(MAADR4, macaddr[1]);
67.       enc28j60Write(MAADR3, macaddr[2]);
68.       enc28j60Write(MAADR2, macaddr[3]);
69.       enc28j60Write(MAADR1, macaddr[4]);
70.       enc28j60Write(MAADR0, macaddr[5]);
71.  
72.        /* 配置PHY為全雙工  LEDB為拉電流 */
73.       enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);
74.  
75.   /* LED狀態(tài) */
76.   enc28j60PhyWrite(PHLCON,0x0476);  
77.  
78.   /* 半雙工回環(huán)禁止 */
79.       enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
80.  
81.   /* 返回BANK0 */     
82.        enc28j60SetBank(ECON1);
83.  
84.   /* 使能中斷 全局中斷 接收中斷 接收錯(cuò)誤中斷 */
85.       enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIE_RXERIE);
86.  
87.   /* 接收使能位 */
88.       enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
89. }</font>
復(fù)制代碼

7 總結(jié)
ENC28J60的驅(qū)動(dòng)編寫算是比較復(fù)雜的。但是回過頭來看看,其他的以太網(wǎng)驅(qū)動(dòng)芯片的操作和ENC28J60的操作類似,其操作的核心即時(shí)數(shù)KB的硬件緩沖區(qū)。本例不能給出合適的運(yùn)行范例,因?yàn)橐蕴W(wǎng)驅(qū)動(dòng)芯片要配合以太網(wǎng)協(xié)議棧來實(shí)現(xiàn),而以太網(wǎng)協(xié)議棧內(nèi)容很多,即使通過uIP或是lwIP也必須面對繁多的基礎(chǔ)知識。ENC28J60的驅(qū)動(dòng)是以太網(wǎng)協(xié)議棧實(shí)現(xiàn)的基礎(chǔ),通過ENC28J60還將會分析uIP協(xié)議棧,lwIP協(xié)議棧的應(yīng)用。在實(shí)現(xiàn)TCP通信之后,還將會結(jié)合AVRNET或uIP,lwIP協(xié)議棧實(shí)現(xiàn)web服務(wù)器,通過網(wǎng)頁交換數(shù)據(jù)。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表