驱动网卡芯片DM9000调试过程及其具体的单片机程序计算机linuxUnix相关_计算机-计算机硬件与维护.pdf

上传人:c****3 文档编号:95777342 上传时间:2023-08-30 格式:PDF 页数:18 大小:861.19KB
返回 下载 相关 举报
驱动网卡芯片DM9000调试过程及其具体的单片机程序计算机linuxUnix相关_计算机-计算机硬件与维护.pdf_第1页
第1页 / 共18页
驱动网卡芯片DM9000调试过程及其具体的单片机程序计算机linuxUnix相关_计算机-计算机硬件与维护.pdf_第2页
第2页 / 共18页
点击查看更多>>
资源描述

《驱动网卡芯片DM9000调试过程及其具体的单片机程序计算机linuxUnix相关_计算机-计算机硬件与维护.pdf》由会员分享,可在线阅读,更多相关《驱动网卡芯片DM9000调试过程及其具体的单片机程序计算机linuxUnix相关_计算机-计算机硬件与维护.pdf(18页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、驱动网卡芯片 DM9000A 的过程及具体驱动程序 一、电路连接 DM9000E网卡芯片支持 8 位、16 位、32 位模式的处理器,通过芯片引脚 EEDO(65 脚)和 WAKEUP(79 脚)的复位值设置支持的处理器类型,如 16 位处理器只需将这两个引脚接低电平即可,其中 WAKEUP内部有 60K下拉电阻,因此可悬空该引脚,或作为网卡芯片唤醒输出用。其它型号请参考相应的数据手册。图 1 DM9000引脚 如图所示,对处理器驱动网卡芯片来说,我们比较关心的有以下几个引脚:IOR、IOW、AEN、CMD(SA2)、INT、RST,以及数据引脚 SD0-SD15-SD31 和地址引脚 SA4

2、-SA9。其中,地址引脚配合 AEN引脚来选通该网卡芯片,对于大多数的应用来说没有意义,因为在我们的应用中一般只用一个网卡芯片,而这些地址引脚主要用于在多网卡芯片环境下选择其中之一。DM9000工作的默认基地址为 0 x300,这里我们按照默认地址选择,将 SA9、SA8接高电平,SA7-DA4 接低电平。多网卡环境可以根据 TXD0-TXD3 配置 SA4-SA7来选择不同的网卡,这里不做介绍,有兴趣的朋友请参考应用手册和数据手册。数据引脚 SD0-SD31则根据前面所讲的配置处理器模式与处理器的数据总线进行选择连接即可,没用到的引脚悬空。那么,除了地址、数据引脚外,剩下的与处理器有关引脚对

3、我们来说及其重要了,而与处理器无关的引脚,只需按照应用手册连接即可。IOR 和 IOW是 DM9000的读写选择引脚,低电平有效,即低电平时进行读(IOR)写(IOW)操作;AEN 是芯片选通引脚,低电平有效,该引脚为低时才能进行读写操作;CMD 的命令/数据切换引脚,低电平时读写命令操作,高电平时读写数据操作。图 2 读时序 图 3 写时序 这些引脚接口和其它单片机外围器件的引脚接口基本相同,其使用也一样。对于有总线接口的单片机来说,如 51 系列,ARM 等直接连接即可。对于没有总线接口的来说,如 AVR mega32等可以直接用 I/O 引脚模拟总线时序进行连接。连接时要参考读写时序,如

4、上图所示。具体连接电路,有时间我再画出来,暂时先略了。二、编写驱动程序 在这,我使用 C语言编写驱动程序,这需要非常注意一点,即处理器所用的 C编译器使用“大端格式”还是“小端格式”,这可以在相应处理器的 C编译器说明上找到。一般比较常见的是小端格式。而对于 8 位处理器来说,在编写驱动程序时,可以不考虑,但是在编写网络协议的时候,一定好考虑,因为网络协议的格式是大端格式,而大部分编译器或者我们习惯的是小端格式,这一点需要注意。在 DM9000中,只有两个可以直接被处理器访问的寄存器,这里命名为 CMD 端口和 DATA端口。事实上,DM9000中有许多控制和状态寄存器(这些寄存器在上一篇文章

5、中有详细的使用说明),但它们都不能直接被处理器访问,访问这些控制、状态寄存器的方法是:(1)、将寄存器的地址写到 CMD 端口;(2)、从 DATA 端口读写寄存器中的数据;1、读、写寄存器 其实,INDEX端口和 DATA 端口的就是由芯片上的 CMD 引脚来区分的。低电平为 INDEX端口,高电平为 DATA 端口。所以,要想实现读写寄存器,就必须先控制好 CMD 引脚。若使用总线接口连接 DM9000的话,假设总线连接后芯片的基地址为 0 x800300(24 根地址总线),只需如下方法:#define DM_ADD(*(volatile unsigned int*)0 x8000300

6、)#define DM_CMD(*(volatile unsigned int*)0 x8000304)/向 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)u

7、delay(20);DM_ADD=reg;udelay(20);return DM_CMD;/将数据从寄存器中读出 只得注意的是前面的两个宏定义 DM_ADD 和 DM_CMD,定义的内容表示指向无符号整形变量的指针,在这里 0 x800300 是 DM9000命令端口的地址,对它的赋值操作就相当于把数据写到该地址中,即把数据写到 DM9000的命令端口中。读的道理也一样。这是一种很常见的宏定义,一般在处理器中定义通用寄存器也是这样定义的。若没有总线接口的话,可以使用 IO 口模拟总线时序的方法实现寄存器的读写。这里只说明实现步骤。首先将处理器的 I/O 端口与 DM9000的 IOR等引脚直

8、接相连(电平匹配的情况下),又假设已经有宏定义“IOR”I/O 端口控制 DM9000的 IOR引脚,其它端口控制 DM9000引脚的命名相同,“PIO1”(根据处理器情况,可以是 8 位、16 位或 32 位的 I/O 端口组成)控制数据端口。这样宏命名更直观些。写寄存器的函数如下:设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们

9、按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该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;I

10、OW=0;udelay(1);AEN=1;IOW=1;读寄存器的写法类似,这里就略一下了。这一过程看上去有些复杂,呵呵,其实执行起来也蛮有效率的,执行时间差不多。这种模拟总线时序的方式实际并不复杂,只是把总线方式下自动执行的过程手动的执行了一遍而已。在 DM9000中,还有一些 PHY寄存器,也称之为介质无关接口 MII(Media Independent Interface)寄存器。对这些寄存器的操作会影响网卡芯片的初始化和网络连接,这里不对其进行操作,所以对这些寄存器的访问方法这里也略了(在上篇文章中有介绍)。操作不当反而使网卡不能连接到网络。至此,我们已经写好了两个最基本的函数:dm90

11、00_reg_write()和 dm9000_reg_read(),以及前面的宏定义 DM_ADD 和 DM_CMD。下面将一直用到。2、初始化 DM9000 网卡芯片。初始化 DM9000 网卡芯片的过程,实质上就是填写、设置 DM9000的控制寄存器的过程,这里以程序为例进行说明。其中寄存器的名称宏定义在中已定义好。设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选

12、择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该注:一下函数中 unsigned char为一个字节 unsigned int为两个字节/DM9000 初始化 void DM9000_init(void)unsigned int i;IO0DIR|=1 8;IO1CLR|=1 8;udelay(500000);IO2S

13、ET|=1 8;udelay(500000);IO1CLR|=1 8;udelay(500000);/*以上部分是利用一个 IO 口控制 DM9000的 RST引脚,使其复位。这一步可以省略,可以用下面的软件复位代替*/dm9000_reg_write(GPCR,0 x01);/设置 GPCR(1EH)bit0=1,使 DM9000的 GPIO3为输出。dm9000_reg_write(GPR,0 x00);/GPR bit0=0 使 DM9000的 GPIO3输出为低以激活内部 PHY。udelay(5000);/延时 2ms以上等待 PHY上电。dm9000_reg_write(NCR,0

14、 x03);/软件复位 udelay(30);/延时 20us 以上等待软件复位完成 dm9000_reg_write(NCR,0 x00);/复位完成,设置正常工作模式。dm9000_reg_write(NCR,0 x03);/第二次软件复位,为了确保软件复位完全成功。此步骤是必要的。udelay(30);dm9000_reg_write(NCR,0 x00);/*以上完成了 DM9000的复位操作*/dm9000_reg_write(NSR,0 x2c);/清除各种状态标志位 dm9000_reg_write(ISR,0 x3f);/清除所有中断标志位/*以上清除标志位*/dm9000_r

15、eg_write(RCR,0 x39);/接收控制 dm9000_reg_write(TCR,0 x00);/发送控制 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其

16、重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 dm9000_reg_write(BPTR,0 x3f);dm9000_reg_write(FCTR,0 x3a);dm9000_reg_write(RTFCR,0 xff);dm9000_reg_write(SMCR,0 x00);/*以上是功能控制,具体功能参考上一篇文章中的说明,或参考数据手册的介绍*/for(i=0;i8)&0 x0ff);设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型

17、号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 dm9000_reg_write(TXPLL,len&0 x0ff);/*这两句是将要发送数据的长度告诉 DM90

18、00的寄存器*/DM_ADD=MWCMD;/这里的写法是针对有总线接口的处理器,没有总线接口的处理器要注意加上时序。for(i=0;ilen;i+=2)/16 bit mode udelay(20);DM_CMD=datasi|(datasi+18);/*上面是将要发送的数据写到 DM9000的内部 SRAM 中的写 FIFO中,注意没有总线接口的处理器要加上适当的时序*/*只需要向这个寄存器中写数据即可,MWCMD是 DM9000内部 SRAM 的 DMA 指针,根据处理器模式,写后自动增加*/dm9000_reg_write(TCR,0 x01);/发送数据到以太网上 while(dm90

19、00_reg_read(NSR)&0 x0c)=0);/等待数据发送完成 udelay(20);dm9000_reg_write(NSR,0 x2c);/清除状态寄存器,由于发送数据没有设置中断,因此不必处理中断标志位 dm9000_reg_write(IMR,0 x81);/DM9000网卡的接收中断使能 以上是发送数据包,过程很简单。而接收数据包确需要些说明了。DM9000从网络中接到一个数据包后,会在数据包前面加上 4 个字节,分别为“01H”、“status”(同RSR寄存器的值)、“LENL”(数据包长度低8 位)、“LENH”(数据包长度高 8 位)。所以首先要读取这 4个字节来确

20、定数据包的状态,第一个字节“01H”表示接下来的是有效数据包,若为“00H”则表示没有数据包,若为其它值则表示网卡没有正确初始化,需要从新初始化。如果接收到的数据包长度小于 60 字节,则 DM9000会自动为不足的字节补上 0,使其达到 60 字节。同时,在接收到的数据包后 DM9000还会自动添加 4 个 CRC校验字节。可以不予处理。于是,接收到的数据包的最小长度也会是 64 字节。当然,可以根据 TCP/IP 协议从首部字节中出有效字节数,这部分在后面讲解。下面为接收数据包的函数。/接收数据包/参数:datas 为接收到是数据存储位置(以字节为单位)/返回值:接收成功返回数据包类型,不

21、成功返回 0 unsigned int receivepacket(unsigned char*datas)设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处

22、理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 unsigned int i,tem;unsigned int status,len;unsigned char ready;ready=0;/希望读取到“01H”status=0;/数据包状态 len=0;/数据包长度/*以上为有效数据包前的 4 个状态字节*/if(dm9000_reg_read(ISR)&0 x01)dm9000_reg_write(ISR,0 x01);/*清除接收中断标志位*/*/*这个地方遇到了问题,下面的黑色字体语句应该替换成成红色字体,也就是说 M

23、RCMDX寄存器如果第一次读不到数据,还要读一次才能确定完全没有数据。在做 PING 实验时证明:每个数据包都是通过第二次的读取 MRCMDX寄存器操作而获知为有效数据包的,对初始化的寄存器做了多次修改依然是此结果,但是用如下方法来实现,绝不会漏掉数据包。*/ready=dm9000_reg_read(MRCMDX);/第一次读取,一般读取到的是 00H if(ready&0 x0ff)!=0 x01)ready=dm9000_reg_read(MRCMDX);/第二次读取,总能获取到数据 if(ready&0 x01)!=0 x01)if(ready&0 x01)!=0 x00)/若第二次读

24、取到的不是 01H 或 00H,则表示没有初始化成功 dm9000_reg_write(IMR,0 x80);/屏幕网卡中断 DM9000_init();/重新初始化 dm9000_reg_write(IMR,0 x81);/打开网卡中断 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可

25、以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 retrun 0;/*ready=dm9000_reg_read(MRCMDX);/read a byte without pointer increment if(!(ready&0 x01)return 0;*/*/*以上表示若接收到的第一个字节不是“01H”,则表示没有数据包,返回0*/status=dm9000_reg_read(MRCMD)

26、;udelay(20);len=DM_CMD;if(!(status&0 xbf00)&(len 1522)for(i=0;i 8)&0 x0ff;else return 0;/*以上接收数据包,注意的地方与发送数据包的地方相同*/if(len 1000)return 0;if(HON(ETHBUF-type)!=ETHTYPE_ARP)&设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于

27、在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 (HON(ETHBUF-type)!=ETHTYPE_IP)return 0;packet_len=len;/*以上对接收到的数据包作一些必要的限制,去除大数据包,去除非 ARP或 IP 的数据包*/return HON(ETHBUF-type);/

28、返回数据包的类型,这里只选择是 ARP或 IP 两种类型 注意:上面的函数用到了一些宏定义,已经在头文件中定义过,这里说明一下:其中uint16 定义为两个字节的变量,根据 C编译器进行定义。unsigned char Buffer1000;/定义了一个 1000 字节的接收发送缓冲区 uint16 packet_len;/接收、发送数据包的长度,以字节为单位。struct eth_hdr/以太网头部结构,为了以后使用方便 unsigned char d_mac6;/目的地址 unsigned char s_mac6;/源地址 uint16 type;/协议类型;struct arp_hdr/

29、以太网头部+ARP首部结构 struct eth_hdr ethhdr;/以太网首部 uint16 hwtype;/硬件类型(1 表示传输的是以太网 MAC 地址)uint16 protocol;/协议类型(0 x0800 表示传输的是 IP 地址)unsigned char hwlen;/硬件地址长度(6)unsigned char protolen;/协议地址长度(4)uint16 opcode;/操作(1 表示 ARP请求,2 表示 ARP应答)unsigned char smac6;/发送端 MAC 地址 unsigned char sipaddr4;/发送端 IP 地址 unsign

30、ed char dmac6;/目的端 MAC 地址 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚

31、低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该unsigned char dipaddr4;/目的端 IP 地址;struct ip_hdr/以太网头部+IP 首部结构 struct eth_hdr ethhdr;/以太网首部 unsigned char vhl,/4位版本号 4 位首部长度(0 x45)tos;/服务类型(0)uint16 len,/整个 IP 数据报总字节长度 ipid,/IP标识 ipoffset;/3位标识 13 位偏移 unsigned char ttl,/生存时间(32 或 64)proto;/协议(1 表示 ICMP,2 表示 IGMP,6表示 TCP

32、,17表示 UDP)uint16 ipchksum;/首部校验和 unsigned char srcipaddr4,/源 IP destipaddr4;/目的 IP;以上定义的三种首部结构,是根据 TCP/IP 协议的相关规范定义的,后面会对 ARP协议进行详细讲解。【上半部分完】4、验证初始化中的各个函数。下面我们来看一下,上面所写的初始化函数是否可用。以上我们写好了三个函数,分别为 DM9000_init(),sendpacket()和 receivepacket(),保存并命名为。既然我们要进行调试,当 然要有结果输出,根据自己的处理器的情况写一个串口程序,这些函数是学某个单片机的基础,

33、这里不 做详细介绍,用到是时候会在函数里注释一下。接下来我们来写个主函数,新建 C文件,命名为,填写如下函数:void main(void)unsigned int i;设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了

34、地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 unsigned char c;uart0_init();/初始化串口,调试时用到 DM9000_init();/初始化网卡 print_regs();/*通过串口,将 DM9000中的寄存器打印出来,显示在超级终端上。此函数根据自己 的处理器进行修改,功能仅仅是读 DM9000寄存器 dm9000_reg_read(),再通过串口打印出来而已*/函数写好,保存文件,连接硬件,连接网线到电脑上或局域网上,运行结果如下图

35、所示:图 4 显示寄存器值 这里首先检查,各个控制寄存器是否是自己写进去的值,在检查状态寄存器是否正确,其中主要要 看 NSR寄存器的 bit5是否为“1”,该位表示是否连接成功。本例中 NSR的值为 40H,括号里的数为对应 的十进制数。下面我们将主函数改进一下,增加个中断接收函数,查看是否能接收到数据。void main(void)unsigned int i;unsigned char c;uart0_init();/初始化串口,调试时用到 DM9000_init();/初始化网卡/*/*这一部分要根据自己的处理器情况,将 DM9000的 INT 引脚连接到处理器的外部中断上,打开中断*

36、/*/sendpacket(60);/*我事先已经在 Buffer中存储了 ARP请求数据包,这里就直接发送了,以便接收 ARP应答包。大家可以先参考后面讲的 ARP协议,根据自己机器的情况,将数据事先存到 Buffer中*/while(1);/等待中断 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低

37、电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该void int_issue(void)/中断处理函数,需要根据自己的处理器进行设置 unsigned int i;i=receivepacket(Buffer);/将数据读取到 Buffer中。int_again:if(i=0)return;else print_buffer();/将接收到的所有数据打印出来 while(1);/停止

38、在这里等待观察,注意:实际应用中是不允许停止在中断中的。/*/*这里加上这一段,目的是判断中断期间是否接收到其它数据包。有则加以处理。不加也完全可以*/*根据自己的处理器,判断处理器是否还处在中断状态,若是则进行如下操作,不是则跳过该段。*/i=receivepacket(Buffer);if(i!=0)goto int_again;/*/编译调试,运行结果如下:图 5 接收数据包中的数据 这是一个 ARP应答包,包含了我电脑上的 MAC 地址和局域网内的 IP 地址。设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请

39、参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 如果一些顺利,到这里对 DM9000网卡芯片的初始化工作就完成了。如果出现问题,出现问题首先要 检查寄存器的值是否正确

40、。可以将 DM9000中的寄存器打印出来,查看到底是哪里的问题。如果打印出的 值很混乱,在确保串口程序无误的前提下,查看硬件连接,以及寄存器读写时序是否正确,重复调试几 次查找原因。三、ARP 协议的实现 1、ARP协议原理简述 ARP协议(Address Resolution Protocol 地址解析协议),在局域网中,网络中实际传输的是“帧”,帧里面有目标主机的 MAC 地址。在以太网中,一个注意要和另一个主机进行直接通信,必须要知 道目标主机的 MAC 地址。这个 MAC 地址就是标识我们的网卡芯片唯一性的地址。但这个目标 MAC地址是如 何获得的呢?这就用到了我们这里讲到的地址解析协

41、议。所有“地址解析”,就是主机在发送帧前将目 标 IP 地址转换成 MAC 地址的过程。ARP协议的基本功能就是通过目标设备的 IP 地址,查询目标设备的 MAC 地址,以保证通信的顺利进行。所以在第一次通信前,我们知道目标机的 IP 地址,想要获知目标机的 MAC 地址,就要发送 ARP报文(即 ARP数据包)。它的传输过程简单的说就是:我知道目标机的IP 地址,那么我就向网络中所有的机器发送一个 ARP请求,请求中有目标机的 IP 地址,请求的意思是目标机要是 收到了此请求,就把你的 MAC 地址告诉我。如果目标机不存在,那么此请求自然不会有人回应。若目标 机接收到了此请求,它就会发送一个

42、 ARP应答,这个应答是明确发给请求者的,应答中有 MAC地址。我接 到了这个应答,我就知道了目标机的 MAC 地址,就可以进行以后的通信了。因为每次通信都要用到 MAC 地 址。ARP报文被封装在以太网帧头部中传输,如图为 ARP请求报文的头部格式。图 6 用于以太网的 ARP请求或应答分组格式 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基

43、地址为这里我们按照默认地址选择将接高电平接低电平多网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该 注意,以太网的传输存储是“大端格式”,即先发送高字节后发送低字节。例如,两个字节的数据,先发送高 8 位后发送低 8 位。所以接收数据的时候要注意存储顺序。整个报文分成两部分,以太网首部和 ARP请求/应答。下面挑重点讲述。“以太网目的地址”字段:若是发送 ARP请求,应填写广播类型的 MA

44、C 地址 FF-FF-FF-FF-FF-FF,意思是 让网络上的所有机器接收到;“帧类型”字段:填写 08-06 表示次报文是 ARP协议;“硬件类型”字段:填写 00-01 表示以太网地址,即 MAC 地址;“协议类型”字段:填写 08-00 表示 IP,即通过 IP 地址查询 MAC 地址;“硬件地址长度”字段:MAC 地址长度为 6(以字节为单位);“协议地址长度”字段:IP 地址长度为 4(以字节为单位);“操作类型”字段:ARP数据包类型,0 表示 ARP请求,1 表示 ARP应答;“目的以太网地址”字段:若是发送 ARP请求,这里是需要目标机填充的。2、ARP的处理程序 ARP协议

45、原理很简单,下面我们来编写 ARP协议的处理函数。新建文件命名为,填写如下函数:unsigned char mac_addr6=*,*,*,*,*,*;unsigned char ip_addr4=192,168,*,*;unsigned char host_ip_addr4=192,168,*,*;unsigned char host_mac_addr6=0 xff,0 xff,0 xff,0 xff,0 xff,0 xff;unsigned char Buffer1000;uint16 packet_len;/*这些全局变量,在前面将的文件中有些已经有过定义,这里要注意在前面加上“exte

46、rn”关键字。“*”应该根据自己的机器修改*/#define HON(n)(uint16)(n)&0 xff)8)/*此宏定义是将小端格式存储的字(两个字节)转换成大端格式存储*/void arp_request(void)/发送 ARP请求数据包 设置支持的处理器类型如位处理器只需将这两个引脚接低电平即可其中内部有下拉电阻因此可悬空该引脚或作为网卡芯片唤醒输出用其它型号请参考相应的数据手册图引脚如图所示对处理器驱动网卡芯片来说我们比较关心的有以下在我们的应用中一般只用一个网卡芯片而这些地址引脚主要用于在多网卡芯片环境下选择其中之一工作的默认基地址为这里我们按照默认地址选择将接高电平接低电平多

47、网卡环境可以根据配置来选择不同的网卡这里不做介有兴趣的可没用到的引脚悬空那么除了地址数据引脚外剩下的与处理器有关引脚对我们来说及其重要了而与处理器无关的引脚只需按照应用手册连接即可和是的读写选择引脚低电平有效即低电平时进行读写操作是芯片选通引脚低电平有效该/以太网首部 memcpy(ARPBUF-,host_mac_addr,6);/*字符串拷贝函数,文件要包含头文件。参数依次是,拷贝目标指针,拷贝数据源指针,拷 贝字符数*/memcpy(ARPBUF-,mac_addr,6);ARPBUF-=HON(0 x0806);/*小端格式的编译器,可以用 HON()宏来转换成大端格式,如果你的编译器

48、是大端格式,直接填写 0 x0806 即可*/*就是简单的按照协议格式填充,以下同*/ARP 首部 ARPBUF-hwtype=HON(1);ARPBUF-protocol=HON(0 x0800);ARPBUF-hwlen=6;ARPBUF-protolen=4;ARPBUF-opcode=HON(0);memcpy(ARPBUF-smac,mac_addr,6);memcpy(ARPBUF-sipaddr,ip_addr,4);memcpy(ARPBUF-dipaddr,host_ip_addr,4);packet_len=42;/14+28=42 sendpacket(Buffer,pa

49、cket_len);注释:ARPBUF 的宏定义和 ARP首部结构,在前面已经讲过。同时注意执行该函数时中断的处理。这里没 作处理。看上去很 easy 吧,下面函数实现接收 ARP请求或接收 ARP应答的处理。unsigned char arp_process(void)/ARP接收函数,成功返回 1,否则返回 0 /简单判断 ARP数据包有无损坏,有损坏则丢弃,不予处理 if(packet_len opcode)case 0 :/处理 ARP请求 if(ARPBUF-dipaddr0=ip_addr0&ARPBUF-dipaddr1=ip_addr1&ARPBUF-dipaddr2=ip_a

50、ddr2&ARPBUF-dipaddr3=ip_addr3)/判断是否是自己的 IP,是否向自己询问 MAC 地址。ARPBUF-opcode=HON(2);/设置为 ARP应答 memcpy(ARPBUF-dmac,ARPBUF-smac,6);memcpy(ARPBUF-,ARPBUF-smac,6);memcpy(ARPBUF-smac,mac_addr,6);memcpy(ARPBUF-,mac_addr,6);memcpy(ARPBUF-dipaddr,ARPBUF-sipaddr,4);memcpy(ARPBUF-sipaddr,ip_addr,4);ARPBUF-=HON(0 x

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > PPT文档

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁