ENC28J60初始化操作
ENC28J60的操作比较琐碎。第一,进行CS端口的相关配置,即把该端口设置为输出状态,该部分代码可以出现在任何硬件初始化代码中,例如可以把所有的IO操作放入gpio_config中;第二,进行软件复位,并通过查询ESTAT的ESTAT_CLKRDY标志位确定是否复位完成;第二,初始化NextPacketPtr变量,该变量的初值为发送缓冲区的起始地址;第三,配置发送和接收缓冲区的区间;第四,若干参数配置,请看代码注释部分,ENC28J60具有自动填充0 的功能,即发送报文长度低于以太网最小报文长度时可以填充0至最小长度;第五,写入MAC地址,由于ENC28J60内部没有全球唯一的MAC地址,所以该地址需要软件填写。但是这种软件填写方式存在缺陷,实际应用中可以含有全球唯一的MAC地址的EEPROM,从EERPOM读取MAC地址并用该地址初始化ENC28J60;第六,初始化中断,并使能接收,ENC28J60含有多个中断,最重要的有全局中断和数据包带接收中断。
<font size="3">void enc28j60Init(unsigned char* macaddr)
{
/* CS端口为输出 */
DDRB |= (1<<4);
/* 禁止ENC28J60 */
ENC28J60_CSH();
/* ENC28J60软件复位 该函数可以改进*/
enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
/*查询ESTAT.CLKRDY位*/
while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
/* 设置接收缓冲区起始地址 该变量用于每次读取缓冲区时保留下一个包的首地址 */
NextPacketPtr = RXSTART_INIT;
/* 设置接收缓冲区 起始指针*/
enc28j60Write(ERXSTL, RXSTART_INIT & 0xFF);
enc28j60Write(ERXSTH, RXSTART_INIT >> 8);
/* 设置接收缓冲区 读指针*/
enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
/* 设置接收缓冲区 结束指针 */
enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
/* 设置发送缓冲区 起始指针 */
enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
enc28j60Write(ETXSTH, TXSTART_INIT>>8);
/* 设置发送缓冲区 结束指针 */
enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF);
enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
/* 使能单播过滤 使能CRC校验 使能 格式匹配自动过滤*/
enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
enc28j60Write(EPMM0, 0x3f);
enc28j60Write(EPMM1, 0x30);
enc28j60Write(EPMCSL, 0xf9);
enc28j60Write(EPMCSH, 0xf7);
/* 使能MAC接收 允许MAC发送暂停控制帧 当接收到暂停控制帧时停止发送*/
/* 数据手册34页 */
enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
/* 退出复位状态 */
enc28j60Write(MACON2, 0x00);
/* 用0填充所有短帧至60字节长 并追加一个CRC 发送CRC使能 帧长度校验使能 MAC全双工使能*/
/* 提示 由于ENC28J60不支持802.3的自动协商机制, 所以对端的网络卡需要强制设置为全双工 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
/* 填入默认值 */
enc28j60Write(MAIPGL, 0x12);
/* 填入默认值 */
enc28j60Write(MAIPGH, 0x0C);
/* 填入默认值 */
enc28j60Write(MABBIPG, 0x15);
/* 最大帧长度 */
enc28j60Write(MAMXFLL, MAX_FRAMELEN & 0xFF);
enc28j60Write(MAMXFLH, MAX_FRAMELEN >> 8);
/* 写入MAC地址 */
enc28j60Write(MAADR5, macaddr[0]);
enc28j60Write(MAADR4, macaddr[1]);
enc28j60Write(MAADR3, macaddr[2]);
enc28j60Write(MAADR2, macaddr[3]);
enc28j60Write(MAADR1, macaddr[4]);
enc28j60Write(MAADR0, macaddr[5]);
/* 配置PHY为全双工 LEDB为拉电流 */
enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);
/* LED状态 */
enc28j60PhyWrite(PHLCON,0x0476);
/* 半双工回环禁止 */
enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
/* 返回BANK0 */
enc28j60SetBank(ECON1);
/* 使能中断 全局中断 接收中断 接收错误中断 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIE_RXERIE);
/* 接收使能位 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
}</font>
复制代码
7 总结
ENC28J60的驱动编写算是比较复杂的。但是回过头来看看,其他的以太网驱动芯片的操作和ENC28J60的操作类似,其操作的核心即时数KB的硬件缓冲区。本例不能给出合适的运行范例,因为以太网驱动芯片要配合以太网协议栈来实现,而以太网协议栈内容很多,即使通过uIP或是lwIP也必须面对繁多的基础知识。ENC28J60的驱动是以太网协议栈实现的基础,通过ENC28J60还将会分析uIP协议栈,lwIP协议栈的应用。在实现TCP通信之后,还将会结合AVRNET或uIP,lwIP协议栈实现web服务器,通过网页交换数据。
转载
|