查看: 747|回复: 0
打印 上一主题 下一主题

ENC28J60学习笔记——AVRNET项目

[复制链接]
跳转到指定楼层
沙发
发表于 2015-10-29 08:56:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1前言
嵌入式以太网开发,可以分为两个部分,一个是以太网收发芯片的使用,一个是嵌入式以太网协议栈的实现。以太网收发芯片的使用要比串口收发芯片的使用复杂的多,市面上流通比较广泛的以太网收发芯片种类还不少,有SPI接口的ENC28J60,也有并口形式的RTL8019S,CS8900A等。嵌入式以太网协议栈有著名的uIP协议栈,Lwip协议栈,还有其他嵌入式高手开发的协议栈。无论是硬件还是软件,都无法分出高下,适合项目需求的才是最好的。
1.1 写作理由
        在前言的最后,再说明一下我写作的理由。以前从淘宝上购买过ENC28J60,店家信誓旦旦地说能提供51 AVR LPC STM32等多个平台的代码,可以实现一个网页控制LED。头脑一热买了回来,买回来才发现,店家提供的资料零零散散,非常难懂,虽然不贵仅仅需要40多元,现在只需要20多元。但是总感觉有欺骗的嫌疑,这也可以映射出中国人做技术买卖的原则,产品多是实物而非服务。几经周转,发现原来这些ENC28J60的代码都出自一个地方——AVRNET,源自老外的一个开源项目。把最原始的代码拿来细细品味,以太网协议就不那么神秘了。在这里说一下ENC28J60的使用,熟悉了ENC28J60的驱动可以分几步走。第一步,通过ENC28J60移植uIP或者lwIP协议栈,实现TCP或是UDP通信,第二,顺着AVRNET项目走,实现一个简单的web服务器,运行静态或者动态网页。嵌入式以太网和计算机以太网开发不同,对于TCP通信而言没有windwos socke用,对于网页编程而言也没有ISS或PHP,所示实现起来会比较麻烦,但是也非常有乐趣。
1.2 平台说明
硬件平台 Atmega32 + proteus 7.10+WinPcap
编译平台 AVR Studio 6
        关于硬件平台,由于AVRNET项目采用ATmega32,分析的时候也采用Atmega32。就ENC28J60而言,对于其他的平台,例如STM32或是MSP而言只需要修改SPI操作即可。由于没有硬件平台,所以使用proteus仿真,注意仿真以太网是proteus需要安装WinPcap。
        关于编译平台,AVRNET项目使用的是AVR Stdui 4.XX。这个版本稍显老旧,我就进行了相关修改,在AVR Studio 6中重新编译,并修正了几个错误。当然其他的编译平台也适用。
        总结一句,平台选用原则——“求同存异”。
1.3 资料准备
        以太网开发是非常复杂的工作,在开始之前最好先大致浏览一些ENC28J60的使用手册,MICROCHIP可以下载,中文版本阅读非常方便。除此之外,需要认真阅读TCP IP相关知识,推荐一本图书《嵌入式Internet TCP/IP基础、实现和应用》。
        嵌入式开发总是一个反复借鉴的过程。该部分代码参考了AVRNET项目和奋斗开发板的相关范例。AVRNET项目网址链接http://www.avrportal.com/?page=avrnet
2 寄存器和寄存器操作
       ENC28J60的寄存器很多,操作这些寄存器需要一个良好的代码组织工作。在AVRNET项目中,把ENC28J60的驱动分解成ENC28J60.h文件和ENC28J60.c文件。H文件中主要描述ENC28J60寄存器的基本定义,而C文件主要实现了这些寄存器的操作。
2.1 寄存器定义
首先分析一下ENC28J60头文件。阅读数据手册之后,会发现ENC28J60寄存器数量较多,通过分析和整理,操作ENC28J60的寄存器需要注意以下3点。
(1)   共有三种不同形式的寄存器——控制寄存器,以太网寄存器 和PHY寄存器,不同的寄存器以不同的字母开头,以E、 MA和MI加以区分。操作这三种不同的寄存器需要不同的组合命令。
(2)   寄存器被分布在4个不同的bank中,也就是说存在地址相同的寄存器,但是这些寄存器却位于不同的分区中,在操作寄存器之前必须选中正确的bank。
(3)  虽然存在4个bank,但是有5个寄存器在4个bank的位置相同,它们是EIE、 EIR、ESTAT、ECON1、ECON2。不言而喻,这5个寄存器将会非常重要。
AVRNET项目中,寄存器被定义成8位长度,而这8位长度包含了三个部分,地址bit7(最高位)用以区分PHY和MAC寄存器;地址bit6和bit5用以区分BANK,2位空间正好区分4个BANK;地址的最后5位才是寄存器的地址。通过这种方式就可以区分所有的寄存器了。列举了几行代码。由于头文件很长,所以不全部列出。
// 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的以太网寄存器,第一个数字0x01代表BANK0中的地址,该地址为0x01,第二个数字0x00代表BANK编号,该编号为0,意味第0个BANK;EHT1为位于BANK1中的控制寄存器,第二个0x20代表BANK地址为1,请注意由于BANK编号被保存在bit6和bit5,所以此处为0x20,绝不是0x10;MACON2为位于bank2的以太网寄存器,第一个数字0x01代表在该BANK中的寄存器地址,第二个数字0x40代表BANK编号,而第三个数字0x80代表该寄存器为以太网寄存器或是PHY寄存器,这些寄存器的操作和控制寄存器有区别。
       为了方便寄存器操作,h文件中还定义了寄存器地址操作的掩码,简单而言就是需要查看哪些位,不需要查看哪些位。
/* 寄存器地址掩码 */
#defineADDR_MASK        0x1F
/* 存储区域掩码 */
#defineBANK_MASK        0x60
/* MAC和MII寄存器掩码*/
#defineSPRD_MASK        0x80
       另外还有比较特殊的5个控制寄存器,EIE,EIR,ESTAT,ECON2和ECON1
/* 关键寄存器 */
#defineEIE                     0x1B
#defineEIR                     0x1C
#defineESTAT                   0x1D
#defineECON2                  0x1E
#defineECON1                  0x1F转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表