单片机驱动DM9000网卡芯片详细调试过程
ADD (*((volatile unsigned int *) 0x8000300))
#define DM_CMD (*((volatile unsigned int *) 0x8000304))
//向DM9000寄存器写数据
void dm9000_reg_write(unsigned char reg, unsigned char data)
{
udelay(20);//之前定义的微妙级延时函数,这里延时20us
DM_ADD = reg;//将寄存器地址写到INDEX端口
udelay(20);
DM_CMD = data;//将数据写到DATA端口,即写进寄存器
}
//从DM9000寄存器读数据
unsigned int dm9000_reg_read(unsigned char reg)
{
udelay(20);
DM_ADD = reg;
udelay(20);
return DM_CMD;//将数据从寄存器中读出
}
只得注意的是前面的两个宏定义DM_ADD和DM_CMD,定义的内容表示指向无符号整形变量的指针,在这里0x800300是DM9000命令端口的地址,对它的赋值操作就相当于把数据写到该地址中,即把数据写到DM9000的命令端口中。读的道理也一样。这是一种很常见的宏定义,一般在处理器中定义通用寄存器也是这样定义的。
若没有总线接口的话,可以使用IO口模拟总线时序的方法实现寄存器的读写。这里只说明实现步骤。首先将处理器的I/O端口与DM9000的IOR等引脚直接相连(电平匹配的情况下),又假设已经有宏定义“IOR”I/O端口控制DM9000的IOR引脚,其它端口控制DM9000引脚的命名相同,“PIO1”(根据处理器情况,可以是8位、16位或32位的I/O端口组成)控制数据端口。这样宏命名更直观些。写寄存器的函数如下:
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 = data;
AEN = 0;
CMD = 0;
IOR = 1;
IOW = 0;
udelay(1);
AEN = 1;
IOW = 1;
}
读寄存器的写法类似,这里就略一下了。这一过程看上去有些复杂,呵呵,其实执行起来也蛮有效率的,执行时间差不多。这种模拟总线时序的方式实际并不复杂,只是把总线方式下自动执行的过程手动的执行了一遍而已。
在DM9000中,还有一些PHY寄存器,也称之为介质无关接口MII(Media Independent Interface)寄存器。对这些寄存器的操作会影响网卡芯片的初始化和网络连接,这里不对其进行操作,所以对这些寄存器的访问方法这里也略了(在上篇文章中有介绍)。操作不当反而使网卡不能连接到网络。
至此,我们已经写好了两个最基本的函数:dm9000_reg_write()和dm9000_reg_read(),以及前面的宏定义DM_ADD和DM_CMD。下面将一直用到。
2、初始化DM9000网卡芯片。
初始化DM9000网卡芯片的过程,实质上就是填写、设置DM9000的控制寄存器的过程,这里以程序为例进行说明。其中寄存器的名称宏定义在DM9000.H中已定义好。
注:一下函数中unsigned char为一个字节unsigned int为两个字节
//DM9000初始化
void DM9000_init(void)
{
unsigned int i;
IO0DIR |= 1 < 8;
IO1CLR |= 1 < 8;
udelay(500000);
IO2SET |= 1 < 8;
udelay(500000);
IO1CLR |= 1 < 8;
udelay(500000);
/*以上部分是利用一个IO口控制DM9000的RST引脚,使其复位。这一步可以省略,可以用下面的软件复位代替*/
dm9000_reg_write(GPCR, 0x01);//设置 GPCR(1EH) bit[0]=1,使DM9000的GPIO3为输出。
dm9000_reg_write(GPR, 0x00);//GPR bit[0]=0 使DM9000的GPIO3输出为低以激活内部PHY。
udelay(5000);//延时2ms以上等待PHY上电。
dm9000_reg_write(NCR, 0x03);//软件复位
udelay(30);//延时20us以上等待软件复位完成
dm9000_reg_write(NCR, 0x00);//复位完成,设置正常工作模式。
dm9000_reg_write(NCR, 0x03);//第二次软件复位,为了确保软件复位完全成功。此步骤是必要的。
udelay(30);
dm9000_reg_write(NCR, 0x00);
/*以上完成了DM9000的复位操作*/
dm9000_reg_write(NSR, 0x2c);//清除各种状态标志位
dm9000_reg_write(ISR, 0x3f);//清除所有中断标志位
/*以上清除标志位*/
dm9000_reg_write(RCR, 0x39);//接收控制
dm9000_reg_write(TCR, 0x00);//发送控制
dm9000_reg_write(BPTR, 0x3f);
dm9000_reg_write(FCTR, 0x3a);
dm9000_reg_write(RTFCR, 0xff);
dm9000_reg_write(SMCR, 0x00);
/*以上是功能控制,具体功能参考上一篇文章中的说明,或参考数据手册的介绍*/
for(i=0; i<6; i++)
dm9000_reg_write(PAR + i, mac_addr[i]);//mac_addr[]自己定义一下吧,6个字节的MAC地址
/*以上存储MAC地址(网卡物理地址)到芯片中去,这里没有用EEPROM,所以需要自己写进去*/
/*关于MAC地址的说明,要参考网络相关书籍或资料*/
dm9000_reg_write(NSR, 0x2c);
dm9000_reg_write(ISR
单片机驱动DM9000网卡芯片调试过 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)