enc28j60初始化缓冲器初始化后读接收指针为什么不是0

ENC28J60学习笔记——第3部分
0.相关资料
& &&相关资料中包括其他精彩博文和代码仓库
& & 【】& &
& & 【ENC28J60学习笔记——索引】 【】【】【】【&】
4.ENC28J60写操作
通过ENC28J60发送以太网数据包,操作ENC28J60硬件缓冲区的发送部分即可。每次发送时总是从发送缓冲区的起始地址开始填充数据,数据填充的结束地址和数据包长度有关。设置发送缓冲区大小之后可向发送缓冲区填充数据,即调用ENC28J60_WRITE_BUF_MEM操作命令,接着置位ECON1中的 ECON1_TXRTS位启动发送,并使用等待法不断查询是否发送完毕。基本的思路还是和SPI或UART发送数据相似,即填充数据,启动发送,查询发送完成。写操作的输入参数为数据包的长度len和数据包指针packet,该参数正好和uIP的网络层操作函数相对应。&
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
/* 查询发送逻辑复位位 */
while((enc28j60Read(ECON1) & ECON1_TXRTS)!= 0);
/* 设置发送缓冲区起始地址 */
enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF);
enc28j60Write(EWRPTH, TXSTART_INIT && 8);
/* 设置发送缓冲区结束地址 该值对应发送数据包长度 */
enc28j60Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);
enc28j60Write(ETXNDH, (TXSTART_INIT + len) &&8);
/* 发送之前发送控制包格式字 */
enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
/* 通过ENC28J60发送数据包 */
enc28j60WriteBuffer(len, packet);
/* 开始发送 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
/* 复位发送逻辑的问题 */
if( (enc28j60Read(EIR) & EIR_TXERIF) )
enc28j60SetBank(ECON1);
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
5 ENC28J60读操作
读操作要比写操作复杂一些。写操作时每次总是从硬件发送缓冲区的起始地址开始操作,而读操作时需要不断修改接收缓冲区的读指针地址,该参数需要通过NextPacketPtr完成,该变量为uint16_t类型的全局变量。读操作时,先通过寄存器查看是否存在以太网数据包,读EPKTCNT寄存器便可返回以太网数据包的个数;若存在以太网数据包则设定读指针的地址,执行读缓冲区操作,ENC28J60的以太网接收数据包中前两个字节为下一个以太网数据包的起始地址,立即保存该参数至NextPacketPtr全局变量;以太网数据包中的后两个字节为该数据包的长度,该长度指从目标MAC地址开始的数据包的长度,进行处理时还需要舍弃最后的4字节CRC校验结果;通过读缓冲区操作码把长度为Len的以太网接收数据包保存至RAM中的某个位置,例如rxtx_buf全局数组。最后根据NextPacketPtr移动读指针以便下次操作,并通过操作ECON2的ECON2_PKTDEC位递减了以太网数据包个数。
unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet)
/* 是否收到以太网数据包 */
if( enc28j60Read(EPKTCNT) == 0 )
return(0);
/* 设置接收缓冲器读指针 */
enc28j60Write(ERDPTL, (NextPacketPtr));
enc28j60Write(ERDPTH, (NextPacketPtr)&&8);
/* 接收数据包结构示例 数据手册43页 */
/* 读下一个包的指针 */
NextPacketPtr
= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)&&8;
/* 读包的长度 */
= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)&&8;
/* 去除CRC校验部分 */
/* 读取接收状态 */
= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) && 8;
/* 限制检索的长度 */
if (len & maxlen-1)
len = maxlen-1;
/* 检查CRC和符号错误 */
/* ERXFCON.CRCEN是默认设置。通常我们不需要检查 */
if ((rxstat & 0x80)==0)
/* 从接收缓冲器中复制数据包 */
enc28j60ReadBuffer(len, packet);
/* 移动接收缓冲区 读指针*/
enc28j60Write(ERXRDPTL, (NextPacketPtr));
enc28j60Write(ERXRDPTH, (NextPacketPtr)&&8);
/* 数据包递减 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
/* 返回长度 */
return(len);
大神可以发个例程源码不?谢谢了。
xukai871105
[reply]yimizqc[/reply]请查看uIP学习笔记http://blog.csdn.net/xukai871105/article/details/。其中的代码仓库里面有ENC28J60驱动
本分类共有文章32篇,更多信息详见
& 2012 - 2014 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";
/*爱悠闲底部960*75*/
var cpro_id = "u1888128";ENC28J60_cn中文手册_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
ENC28J60_cn中文手册
上传于||文档简介
&&以​太​网​控​制​器​ ​S​P​I​控​制​ ​符​合​I​E​E​E0.​3
大小:10.37MB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢6663人阅读
物联网学习笔记(37)
0.相关资料
& &&相关资料中包括其他精彩博文和代码仓库
& & 【】& &
& & 【ENC28J60学习笔记——索引】 【】【】【】【】
3 寄存器操作实现
ENC28j60的寄存器操作分为2+2+2部分,分别为写寄存器和读寄存器部分,读缓冲区和写缓冲区部分,写PHY寄存器和读PHY寄存器部分。
3.1 读写寄存器
读或写寄存器的函数如下:
unsigned char enc28j60Read(unsigned char address)
/* 设定寄存器地址区域 */
enc28j60SetBank(address);
/* 读取寄存器值 发送读寄存器命令和地址 */
return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
void enc28j60Write(unsigned char address, unsigned char data)
/* 设定寄存器地址区域 */
enc28j60SetBank(address);
/* 写寄存器值 发送写寄存器命令和地址 */
enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
}读写寄存器的分为两步,第一步为选定寄存器的BANK编号,第二步使用写命令或读命令,操作指定地址的寄存器。在ENC28J60中,由ECON1中的低两位(BIT1-BIT1)保存BANK编号,ECON1是比较特殊的控制寄存器, 4个BANK均具有该寄存器且该寄存器的地址相同。Enc28j60Bank为全局变量,用于保存当前的BANK编号,如果两次操作控制寄存器在同一个BANK时,该变量保持不变,若两次操作的控制寄存器位于不同的BANK,那么BANK的值会变为新的BANK编号。
void enc28j60SetBank(unsigned char address)
/* 计算本次寄存器地址在存取区域的位置 */
if((address & BANK_MASK) != Enc28j60Bank)
/* 清除ECON1的BSEL1 BSEL0 详见数据手册15页 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
/* 请注意寄存器地址的宏定义,bit6 bit5代码寄存器存储区域位置 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)&&5);
/* 重新确定当前寄存器存储区域 */
Enc28j60Bank = (address & BANK_MASK);
unsigned char enc28j60ReadOp(unsigned char op, unsigned char address)
unsigned char dat = 0;
/* CS拉低 使能ENC28J60 */
ENC28J60_CSL();
/* 操作码和地址 */
dat = op | (address & ADDR_MASK);
/* 通过SPI写数据*/
spi_sendbyte(dat);
/* 通过SPI读出数据 */
dat = spi_sendbyte(0xFF);
/* 如果是MAC和MII寄存器,第一个读取的字节无效,该信息包含在地址的最高位 */
if(address & 0x80)
/* 再次通过SPI读取数据 */
dat = spi_sendbyte(0xFF);
/* CS拉高 禁止ENC28J60 */
ENC28J60_CSH();
/* 返回数据 */
}读控制寄存器实际上就是严格遵守数据手册的操作要求。由于读MAC和MII寄存器时,第一个接收到的字节为无效字节,第二个字节才为有效字节。程序通过寄存器地址的最高位来判断是否为MAC或MII寄存器。写寄存器函数较为简单,第一次字节包括操作码和寄存器地址,第二个字节为数据。在这两个函数中参数op为ENC28J60的指令,或称之为操作码,该指令占据SPI首字节的前3位,参数address为寄存器地址,参数data为寄存器的具体值。
ENC28J60_CSL()和ENC28J60_CSH()为操作CS端口的操作宏,而spi_sendbyte()可通过SPI发送一个字节。修改这些函数即可在其他平台上操作ENC28J60。不过请特别注意,在使用其他开发板时由于SPI总线上可能挂载多个设备,单独使用ENC28J60时需要把其他设备的CS端口拉高,或安装一个上拉电阻。
unsigned char enc28j60ReadOp(unsigned char op, unsigned char address)
unsigned char dat = 0;
/* CS拉低 使能ENC28J60 */
ENC28J60_CSL();
/* 操作码和地址 */
dat = op | (address & ADDR_MASK);
/* 通过SPI写数据*/
spi_sendbyte(dat);
/* 通过SPI读出数据 */
dat = spi_sendbyte(0xFF);
/* 如果是MAC和MII寄存器,第一个读取的字节无效,该信息包含在地址的最高位 */
if(address & 0x80)
/* 再次通过SPI读取数据 */
dat = spi_sendbyte(0xFF);
/* CS拉高 禁止ENC28J60 */
ENC28J60_CSH();
/* 返回数据 */
void enc28j60WriteOp(unsigned char op, unsigned char address, unsigned char data)
unsigned char dat = 0;
/* 使能ENC28J60 */
ENC28J60_CSL();
/* 通过SPI发送 操作码和寄存器地址 */
dat = op | (address & ADDR_MASK);
/* 通过SPI1发送数据 */
spi_sendbyte(dat);
/* 准备寄存器数值 */
/* 通过SPI发送数据 */
spi_sendbyte(dat);
/* 禁止ENC28J60 */
ENC28J60_CSH();
3.2 读写缓冲区
读写缓冲区的操作也易于理解的。需要说明的是,两个函数具有相同的输入参数,参数len代表被操作数据的长度,pdata为被操作数据的指针。和寄存器读写函数相似,发送或接收数据之前需要发送特定的操作码。
void enc28j60ReadBuffer(unsigned int len, unsigned char* pdata)
/* 使能ENC28J60 */
ENC28J60_CSL();
/* 通过SPI发送读取缓冲区命令*/
spi_sendbyte(ENC28J60_READ_BUF_MEM);
/* 循环读取 */
while(len)
/* 读取数据 */
*pdata = (unsigned char)spi_sendbyte(0);
/* 地址指针累加 */
/* 禁止ENC28J60 */
ENC28J60_CSH();
void enc28j60WriteBuffer(unsigned int len, unsigned char* pdata)
/* 使能ENC28J60 */
ENC28J60_CSL();
/* 通过SPI发送写取缓冲区命令*/
spi_sendbyte(ENC28J60_WRITE_BUF_MEM);
/* 循环发送 */
while(len)
/* 发送数据 */
spi_sendbyte(*pdata);
/* 地址指针累加 */
/* 禁止ENC28J60 */
ENC28J60_CSH();
3.3 读写PHY寄存器
PHY寄存器和被ENC28J60控制的LED指示灯有关,控制该寄存器可以控制LED驱动方式和发生相应事件时LED显示方式。一般情况下,一个LED指示灯用于指示网络状态(常亮可理解为网络接通),另一个LED指示灯显示接收活动,有数据输入时产生一个点亮脉冲。PHY是比较特殊的寄存器,先要想一个控制寄存器写入PHY寄存器的地址,再向两个控制寄存器依次写入PHY寄存器的具体数据的高8位和低8位,最后等待PHY寄存器操作完成。
void enc28j60PhyWrite(unsigned char address, unsigned int data)
/* 向MIREGADR写入地址 详见数据手册19页*/
enc28j60Write(MIREGADR, address);
/* 写入低8位数据 */
enc28j60Write(MIWRL, data);
/* 写入高8位数据 */
enc28j60Write(MIWRH, data&&8);
/* 等待PHY寄存器写入完成 */
while(enc28j60Read(MISTAT) & MISTAT_BUSY);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1579290次
积分:15732
积分:15732
排名:第396名
原创:186篇
评论:1229条
所在地: 江苏无锡
(2)(1)(1)(3)(1)(3)(2)(1)(7)(16)(17)(14)(5)(13)(9)(4)(15)(11)(13)(12)(1)(3)(2)(21)(1)(4)(2)(1)(5)(2)(1)解读ENC28J60嵌入式网络接口电路
日 14:10 来源:互联网 作者:秩名 (0)
  设计了以ENC28J60 为核心的以太网接口实现方案, 描述了该系统硬件架构的设计方法。在简要介绍了以太网控制器ENC28J60 的结构、功能、外围电路的基础上, 对 与Atmega16 的 通讯进行了阐述。此方案不仅成本低, 而且可以实现500Kbps 以上的传输速率, 满足了嵌入式系统的Internet 控制要求。
   在嵌入式网络接口的应用
  利用ENC28J60 可以构成不同功能的网络终端节点, 如网络服务器、带Internet 功能的设备、远程监控(数据采集, 诊断)设备等。图2 所示为基于ENC28J60 的嵌入式网络接口的硬件电路原理图。电路中有:2 个LED 状态指示灯主要用来显示网络连接状态,包括PHY 是否冲突、连接是否建立、是否接收数据、连接速度、双工模式等; 必需的偏置电阻R3(2k&O, 精度为1%);高速局域网电磁隔离模块(即RJ45 以太网接口), 应用中, 的物理端口与隔离变压器HR901170A 连接时必须符合IEEE802.3 对物理层规范的要求, 如 的插孔与隔离变压器的间隔应尽量小, 输出和输入差分信号对的走线要有很好的隔离。
  电路中的主控制器采用Atmel 公司的ATmega16 单片机,它具有先进的RISC(精简指令集计算机)结构、16 kB 可编程Flash 存储器、512 B 的EEPROM 和1 kB 片内SRAM, 具有丰富的外设接口, 其SPI 接口允许ATmega16 与外设进行高速的同步数据传输。本设计中ATmega16 SPI 配置为主机模式,ENC28J60 为从设备。ATmega16 的SPI 工作模式由CPOL、CPHA 设置, 根据ENC28J60 的SPI 读写时序, ATmega16的SPI 工作模式应设置为模式0.ATmega16 通过将ENC28J60 的CS 引脚置低实现与其的同步。SPI 时钟由写入到SPI 发送缓冲寄存器的数据启动, SPI MOSI(PB5)引脚上的数据发送秩序由寄存器SPCR 的DORD 位控制, 置位时数据的LSB(最低位)首先发送, 否则数据的MSB(最高位)首先发送。我们选择先发送MSB,同时接收到的数据传送到接收缓冲寄存器, CPU 进行右对齐从接收缓冲器中读取接收到的数据。应该注意, 当需要从ENC28J60 中读取多个数据时, 即使 并不需要ATmega16 串行输出的数据, 每读取一个数据前都要向SPI 发送缓冲器写一个数据以启动SPI 接口时钟。由于SPI 系统的发送方向只有1 个缓冲器, 而在接收方向有2 个缓冲器, 所以在发送时一定要等到移位过程全部结束后, 才能对SPI 数据寄存器执行写操作; 而在接收数据时,需要在下一个字节移位过程结束之前通过访问 数据寄存器读取当前接收到的数据,否则第1 个数据丢失。
相关技术文章:
相关资料下载:
上周热点文章排行榜
上周资料下载排行榜
技术交流、我要发言! 发表评论可获取积分! 请遵守相关规定。
创新实用技术专题
自苹果Siri推出以来,基于语音技术的交互应用着实是火红了一...

我要回帖

更多关于 enc28j60中文手册 的文章

 

随机推荐