单片机驱动DM9000网卡芯片详细调试过程
, 0x3f);
/*为了保险,上面有清除了一次标志位*/
dm9000_reg_write(IMR, 0x81);
/*中断使能(或者说中断屏蔽),即开启我们想要的中断,关闭不想要的,这里只开启的一个接收中断*/
/*以上所有寄存器的具体含义参考上一篇文章,或参考数据手册*/
}
这样就对DM9000初始化完成了,怎么样,挺简单的吧。
3、发送、接收数据包
同样,以程序为例,通过注释说明。
//发送数据包
//参数:datas为要发送的数据缓冲区(以字节为单位),length为要发送的数据长度(两个字节)。
void sendpacket(unsigned char *datas, unsigned int length)
{
unsigned int len, i;
dm9000_reg_write(IMR, 0x80);//先禁止网卡中断,防止在发送数据时被中断干扰
len = length;
dm9000_reg_write(TXPLH, (len>>8) & 0x0ff);
dm9000_reg_write(TXPLL, len & 0x0ff);
/*这两句是将要发送数据的长度告诉DM9000的寄存器*/
DM_ADD = MWCMD;//这里的写法是针对有总线接口的处理器,没有总线接口的处理器要注意加上时序。
for(i=0; i { udelay(20); DM_CMD = datas[i] | (datas[i+1]<8); } /*上面是将要发送的数据写到DM9000的内部SRAM中的写FIFO中,注意没有总线接口的处理器要加上适当的时序*/ /*只需要向这个寄存器中写数据即可,MWCMD是DM9000内部SRAM的DMA指针,根据处理器模式,写后自动增加*/ dm9000_reg_write(TCR, 0x01);//发送数据到以太网上 while((dm9000_reg_read(NSR) & 0x0c) == 0);//等待数据发送完成 udelay(20); dm9000_reg_write(NSR, 0x2c);//清除状态寄存器,由于发送数据没有设置中断,因此不必处理中断标志位 dm9000_reg_write(IMR, 0x81);//DM9000网卡的接收中断使能 } 以上是发送数据包,过程很简单。而接收数据包确需要些说明了。DM9000从网络中接到一个数据包后,会在数据包前面加上4个字节,分别为“01H”、“status”(同RSR寄存器的值)、“LENL”(数据包长度低8位)、“LENH”(数据包长度高8位)。所以首先要读取这4个字节来确定数据包的状态,第一个字节“01H”表示接下来的是有效数据包,若为“00H”则表示没有数据包,若为其它值则表示网卡没有正确初始化,需要从新初始化。 如果接收到的数据包长度小于60字节,则DM9000会自动为不足的字节补上0,使其达到60字节。同时,在接收到的数据包后DM9000还会自动添加4个CRC校验字节。可以不予处理。于是,接收到的数据包的最小长度也会是64字节。当然,可以根据TCP/IP协议从首部字节中出有效字节数,这部分在后面讲解。下面为接收数据包的函数。 //接收数据包 //参数:datas为接收到是数据存储位置(以字节为单位) //返回值:接收成功返回数据包类型,不成功返回0 unsigned int receivepacket(unsigned char *datas) { unsigned int i, tem; unsigned int status, len; unsigned char ready; ready = 0;//希望读取到“01H” status = 0;//数据包状态 len = 0; //数据包长度 /*以上为有效数据包前的4个状态字节*/ if(dm9000_reg_read(ISR) & 0x01) { dm9000_reg_write(ISR, 0x01); } /*清除接收中断标志位*/ /***********************************************************************************/ /*这个地方遇到了问题,下面的黑色字体语句应该替换成成红色字体,也就是说MRCMDX寄存器如果第一次读不到数据,还要读一次才能确定完全没有数据。 在做 PING 实验时证明:每个数据包都是通过第二次的读取MRCMDX寄存器操作而获知为有效数据包的,对初始化的寄存器做了多次修改依然是此结果,但是用如下方法来实现,绝不会漏掉数据包。*/ ready = dm9000_reg_read(MRCMDX); // 第一次读取,一般读取到的是 00H if((ready & 0x0ff) != 0x01) { ready = dm9000_reg_read(MRCMDX); // 第二次读取,总能获取到数据 if((ready & 0x01) != 0x01) { if((ready & 0x01) != 0x00) //若第二次读取到的不是 01H 或 00H ,则表示没有初始化成功 { dm9000_reg_write(IMR, 0x80);//屏幕网卡中断 DM9000_init();//重新初始化 dm9000_reg_write(IMR, 0x81);//打开网卡中断 } retrun 0; } } /* ready = dm9000_reg_read(MRCMDX); // read a byte without pointer increment if(!(ready & 0x01)) { return 0; }*/ /***********************************************************************************/ /*以上表示若接收到的第一个字节不是“01H”,则表示没有数据包,返回0*/ status = dm9
单片机驱动DM9000网卡芯片调试过 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)