首页 单片机驱动DM9000网卡芯片(详细调试过程)【下】

单片机驱动DM9000网卡芯片(详细调试过程)【下】

举报
开通vip

单片机驱动DM9000网卡芯片(详细调试过程)【下】单片机驱动DM9000网卡芯片(详细调试过程)【下】 2008年05月20日 星期二 14:10 4、验证初始化中的各个函数。 下面我们来看一下,上面所写的初始化函数是否可用。以上我们写好了三个函数,分别为 DM9000_init(),sendpacket()和receivepacket(),保存并命名为dm9000.c。既然我们要进行调试,当 然要有结果输出,根据自己的处理器的情况写一个串口程序,这些函数是学某个单片机的基础,这里不 做详细介绍,用到是时候会在函数里注释一下。 接下来我们来写个主函数...

单片机驱动DM9000网卡芯片(详细调试过程)【下】
单片机驱动DM9000网卡芯片(详细调试过程)【下】 2008年05月20日 星期二 14:10 4、验证初始化中的各个函数。 下面我们来看一下,上面所写的初始化函数是否可用。以上我们写好了三个函数,分别为 DM9000_init(),sendpacket()和receivepacket(),保存并命名为dm9000.c。既然我们要进行调试,当 然要有结果输出,根据自己的处理器的情况写一个串口程序,这些函数是学某个单片机的基础,这里不 做详细介绍,用到是时候会在函数里注释一下。 接下来我们来写个主函数,新建C文件,命名为mian.c,填写如下函数: void main(void) { unsigned int i; unsigned char c; uart0_init();//初始化串口,调试时用到 DM9000_init();//初始化网卡 print_regs();/*通过串口,将DM9000中的寄存器打印出来,显示在超级终端上。此函数根据自己 的处理器进行修改,功能仅仅是读DM9000寄存器dm9000_reg_read(),再通过串口打印出来而已*/ } 函数写好,保存文件,连接硬件,连接网线到电脑上或局域网上,运行结果如下图所示: 图4 显示寄存器值 这里首先检查,各个控制寄存器是否是自己写进去的值,在检查状态寄存器是否正确,其中主要要 看NSR寄存器的bit[6]是否为“1”,该位 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示是否连接成功。本例中NSR的值为40H,括号里的数为对应 的十进制数。 下面我们将主函数改进一下,增加个中断接收函数,查看是否能接收到数据。 void main(void) { unsigned int i; unsigned char c; uart0_init();//初始化串口,调试时用到 DM9000_init();//初始化网卡 /********************************************************************************/ /*这一部分要根据自己的处理器情况,将DM9000的INT引脚连接到处理器的外部中断上,打开中断*/ /********************************************************************************/ sendpacket(60);/*我事先已经在Buffer[]中存储了ARP请求数据包,这里就直接发送了,以便接收 ARP应答包。大家可以先参考后面讲的ARP协议,根据自己机器的情况,将数据事先存到Buffer[]中*/ while(1);//等待中断 } void int_issue(void) //中断处理函数,需要根据自己的处理器进行设置 { unsigned int i; i = receivepacket(Buffer);//将数据读取到Buffer中。 int_again : if(i == 0) { return; } else { print_buffer();//将接收到的所有数据打印出来 while(1);//停止在这里等待观察,注意:实际应用中是不允许停止在中断中的。 } /************************************************************************************/ /*这里加上这一段,目的是判断中断期间是否接收到其它数据包。有则加以处理。不加也完全可以*/ /* 根据自己的处理器,判断处理器是否还处在中断状态,若是则进行如下操作,不是则跳过该段。*/ i = receivepacket(Buffer); if(i != 0) { goto int_again; } /************************************************************************************/ } 编译调试,运行结果如下: 图5 接收数据包中的数据 这是一个ARP应答包,包含了我电脑上的MAC地址和局域网内的IP地址。反正我也不是啥重要人物, 这里就不保密了,呵呵。 如果一些顺利,到这里对DM9000网卡芯片的初始化工作就完成了。如果出现问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 ,首先要 检查寄存器的值是否正确。可以将DM9000中的寄存器打印出来,查看到底是哪里的问题。如果打印出的 值很混乱,在确保串口程序无误的前提下,查看硬件连接,以及寄存器读写时序是否正确,重复调试几 次查找原因。 三、ARP协议的实现 1、ARP协议原理简述 ARP协议(Address Resolution Protocol 地址解析协议),在局域网中,网络中实际传输的是“ 帧”,帧里面有目标主机的MAC地址。在以太网中,一个注意要和另一个主机进行直接通信,必须要知 道目标主机的MAC地址。这个MAC地址就是标识我们的网卡芯片唯一性的地址。但这个目标MAC地址是如 何获得的呢?这就用到了我们这里讲到的地址解析协议。所有“地址解析”,就是主机在发送帧前将目 标IP地址转换成MAC地址的过程。ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC 地址,以保证通信的顺利进行。所以在第一次通信前,我们知道目标机的IP地址,想要获知目标机的 MAC地址,就要发送ARP报文(即ARP数据包)。它的传输过程简单的说就是:我知道目标机的IP地址, 那么我就向网络中所有的机器发送一个ARP请求,请求中有目标机的IP地址,请求的意思是目标机要是 收到了此请求,就把你的MAC地址告诉我。如果目标机不存在,那么此请求自然不会有人回应。若目标 机接收到了此请求,它就会发送一个ARP应答,这个应答是明确发给请求者的,应答中有MAC地址。我接 到了这个应答,我就知道了目标机的MAC地址,就可以进行以后的通信了。因为每次通信都要用到MAC地 址。 ARP报文被封装在以太网帧头部中传输,如图为ARP请求报文的头部格式。 图6 用于以太网的ARP请求或应答分组格式 注意,以太网的传输存储是“大端格式”,即先发送高字节后发送低字节。例如,两个字节的数据 ,先发送高8位后发送低8位。所以接收数据的时候要注意存储顺序。 整个报文分成两部分,以太网首部和ARP请求/应答。下面挑重点讲述。 “以太网目的地址”字段:若是发送ARP请求,应填写广播类型的MAC地址FF-FF-FF-FF-FF-FF,意思是 让网络上的所有机器接收到; “帧类型”字段:填写08-06表示次报文是ARP协议; “硬件类型”字段:填写00-01表示以太网地址,即MAC地址; “协议类型”字段:填写08-00表示IP,即通过IP地址查询MAC地址; “硬件地址长度”字段:MAC地址长度为6(以字节为单位); “协议地址长度”字段:IP地址长度为4(以字节为单位); “操作类型”字段:ARP数据包类型,1表示ARP请求,2表示ARP应答; “目的以太网地址”字段:若是发送ARP请求,这里是需要目标机填充的。 2、ARP的处理程序 ARP协议原理很简单,下面我们来编写ARP协议的处理函数。新建文件命名为arp.c,填写如下函数 : unsigned char mac_addr[6] = {*,*,*,*,*,*}; unsigned char ip_addr[4] = { 192, 168, *, * }; unsigned char host_ip_addr[4] = { 192, 168, *, * }; unsigned char host_mac_addr[6]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; unsigned char Buffer[1000]; uint16 packet_len; /*这些全局变量,在前面将的文件中有些已经有过定义,这里要注意在前面加上“extern”关键字。“ *”应该根据自己的机器修改*/ #define HON(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) /*此宏定义是将小端格式存储的字(两个字节)转换成大端格式存储*/ void arp_request(void) //发送ARP请求数据包 { //以太网首部 memcpy(ARPBUF->ethhdr.d_mac, host_mac_addr, 6); /*字符串拷贝函数,文件要包含头文件。参数依次是,拷贝目标指针,拷贝数据源指针,拷 贝字符数*/ memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6); ARPBUF->ethhdr.type = HON( 0x0806 ); /*小端格式的编译器,可以用HON()宏来转换成大端格式,如果你的编译器是大端格式,直接填写 0x0806即可*/ /*就是简单的按照协议格式填充,以下同*/ //ARP首部 ARPBUF->hwtype = HON( 1 ); ARPBUF->protocol = HON( 0x0800 ); ARPBUF->hwlen = 6; ARPBUF->protolen = 4; ARPBUF->opcode = HON( 1 ); 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, packet_len ); } 注释:ARPBUF的宏定义和ARP首部结构,在前面已经讲过。同时注意执行该函数时中断的处理。这里没 作处理。 看上去很easy吧,下面函数实现接收ARP请求或接收ARP应答的处理。 unsigned char arp_process(void)//ARP接收函数,成功返回1,否则返回0 { //简单判断ARP数据包有无损坏,有损坏则丢弃,不予处理 if( packet_len < 28 )//ARP数据长度为28字节为无效数据 { return 0; } switch ( HON( ARPBUF->opcode ) ) { case 1 : //处理ARP请求 if( ARPBUF->dipaddr[0] == ip_addr[0] && ARPBUF->dipaddr[1] == ip_addr[1] && ARPBUF->dipaddr[2] == ip_addr[2] && ARPBUF->dipaddr[3] == ip_addr[3] )//判断是否是自己的IP,是否向自己询问MAC地址 。 { ARPBUF->opcode = HON( 2 );//设置为ARP应答 memcpy(ARPBUF->dmac, ARPBUF->smac, 6); memcpy(ARPBUF->ethhdr.d_mac, ARPBUF->smac, 6); memcpy(ARPBUF->smac, mac_addr, 6); memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6); memcpy(ARPBUF->dipaddr, ARPBUF->sipaddr, 4); memcpy(ARPBUF->sipaddr, ip_addr, 4); ARPBUF->ethhdr.type = HON( 0x0806 ); packet_len = 42; sendpacket( Buffer, packet_len );//发送ARP数据包 return 1; } else { return 0; } break; case 2 : //处理ARP应答 if( ARPBUF->dipaddr[0] == ip_addr[0] && ARPBUF->dipaddr[1] == ip_addr[1] && ARPBUF->dipaddr[2] == ip_addr[2] && ARPBUF->dipaddr[3] == ip_addr[3] )//再次判断IP,是否是给自己的应答 { memcpy(host_mac_addr, ARPBUF->smac, 6);//保存服务器MAC地址 return 1; } else { return 0; } break; default ://不是ARP协议 return 0; } } 根据ARP协议格式看这两个函数并不困难。于是我们又得到两个函数:arp_request()和 arp_process()。 3、ARP程序调试 下面我们修改主函数和中断处理函数。 将mian()函数中的“sendpacket(60);”语句换成“arp_request();”语句。 void int_issue(void) //中断处理函数,需要根据自己的处理器进行设置 { unsigned int i; i = receivepacket(Buffer);//将数据读取到Buffer中。 if(i == 0) { return; } else { i = arp_process(); if(i == 1)//判断是否是ARP协议 print_hostmacaddr();//打印目标机的MAC地址,就是用串口打印host_mac_addr[]中的6 个字节 } } 保存运行调试。 图7 主机MAC地址 至此,关于DM9000的调试过程就完成了。之后我还调试了UDP通讯、TCP通讯等,主要是关于协议的 处理了,这里就不介绍了。有兴趣的朋友可以参看《TCP/IP协议》第一卷,将会有很大帮助。希望这些 调试过程能为读者或多或少的提供些有用的信息,也欢迎大家和我一起讨论。 我的Email:mengqx25@163.com 补充:增加了udp实现 【全文完】   类别:默认分类 | | 添加到搜藏 | 分享到i贴吧 | 浏览(2101) | 评论 (9) 上一篇:单片机驱动DM9000网卡芯片(详细...    下一篇:google的秘密入口 已有1人分享了这篇文章: dianzi0702 Ta的转贴       相关文章: ? 单片机驱动DM9000网卡芯片(详细...   ? 写DM9000网卡芯片驱动的预备知识 ? linux-2.6.22内核下dm9000网卡   ? 嵌入式系统中常见的网卡芯片比较... ? 移植dm9000驱动(支持四网卡)s3c2...   ? 嵌入式系统中常见的网卡(CS8900A...         最近读者: 登录后,您就出现在这里。            
本文档为【单片机驱动DM9000网卡芯片(详细调试过程)【下】】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_477730
暂无简介~
格式:doc
大小:47KB
软件:Word
页数:12
分类:工学
上传时间:2019-05-06
浏览量:20