⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8019 isa网卡上网开发套件.htm

📁 此为51单片机控制以太网控制器RTL8019AS驱动的源代码 简单 易理解
💻 HTM
📖 第 1 页 / 共 3 页
字号:
      数据字节数<BR>---------- ---------- | ---------- |<BR>BNRY---&gt;| | | | | | | 
      |<BR>读页指针 ---------- ---------- - ---------- -<BR>| ... | 图4 发送缓冲区 图6 
      远端DMA操作<BR>----------<BR>PSTOP---&gt;| 不关心 |<BR>FIFO停止页----------<BR>图5 
      接收FIFO缓冲队列<BR><BR>明白了发送和接收数据包的原理,那么数据包又是怎样被主机写入芯片RAM和从芯片RAM读出的呢?如图6所示,主机设置好远端DMA开始地址(RSAR0,1)和远端DMA数据字节数(RBCR0,1),并在CR中设置读/写,就可以从远端DMA口寄存器里读出芯片RAM里的数据/把数据写入芯片RAM。<BR>何谓本地/远端DMA呢?如图7所示,“远端”指CPU接口侧;“本地”指8019的硬件收发电路侧。没有更深的意思,与远近无关,仅仅为了区分主机和芯片硬件两个接口端。这里的DMA与平时所说的DMA有点不同。RTL8019AS的local 
      DMA操作是由控制器本身完成的,而其remote DMA并不是在无主处理器的参与下,数据能自动移到主处理器的内存中。remote 
      DMA指主机CPU给出起址和长度就可以读写芯片RAM,每操作一次RAM地址自动加1。而普通RAM操作每次要先发地址再处理数据,速度较慢。<BR>在一些高档通信控制器上自带有MAC控制器,工作原理与8019的差不多,比如:Motorola 
      68360/MPC860T内部的CPM带有以太网处理器,通过设置BD表,使软件和硬件协同工作,它的缓冲区更大且可灵活配置。这些通信控制器的设计,体现了软硬件互相融合协同工作的趋势:软件硬化(VHDL),硬件软化(DSP),希望大家关注!<BR><BR>TPSR 
      ---------- ----------<BR>TBCR0,1 | | --------- | |<BR>| | | | | 
      |<BR>PSTART | 本地 | | 16K | | 远端 | RSAR0,1<BR>PSTOP | DMA | |双口RAM| | DMA | 
      RBCR0,1<BR>CURR | | | | | |<BR>BNRY | | | | | | CRDA0,1<BR>| | --------- | 
      | 指示当前远端DMA地址<BR>CLDA0,1 ---------- ----------<BR>指示当前本地DMA地址<BR>硬件收发电路侧 
      主机CPU侧<BR>图7 
      与DMA有关的寄存器<BR><BR>如图7所示,8019以太网控制器以存储器(16K双口RAM)为核心,本地和远端控制器并发操作。这种体系结构满足了数据带宽的需要。8019拥有控制、状态、数据寄存器,通过它们,51单片机可以与8019通信。由于51资源紧张,在实现TCPIP协议栈时不要进行内存块拷贝,建议(1)使用全局结构体变量,在内存中只保存一个数据包拷贝,其他没有来得及处理的包保存在8019的16K 
      RAM里;(2)使用查询方式而不用中断;(3)客户服务器模型中服务器工作于串行方式,并发模式不适合51单片机。<BR>芯片内部地址空间的分配如图8所示,其中0x00-0x0B(工作于8位DMA模式)用于存放本节点MAC地址,奇偶地址内容是重复放置的。如:MAC地址0000 
      1234 
      5678存放在0x00-0x0B中为000000001212343456567878,单地址和双地址的内容是重复的.一般使用偶数地址的内容,这主要是为了同时适应8位和16位的dma。Prom内容是网卡在上电复位的时候从93C46里读出来的。如果你没有使用93C46,就不要使用Prom,那么使用了93C46后如何获得网卡的地址呢?有两种方法,一是直接读93C46,二是读Prom。网卡MAC地址既不由93C46也不由Prom决定,而是由PAR0-PAR5寄存器决定。Prom只保存上电时从9346中读出的MAC地址(如果有93C46的话),仅此而矣。<BR><BR>D15 
      D0<BR>0000H---------------------<BR>| | PROM 
      |<BR>00FFH---------------------<BR>0100H| 不使用 
      |<BR>3FFFH---------------------<BR>4000H| 
      8K*16缓冲区双口RAM|<BR>7FFFH---------------------<BR>8000H| |<BR>| |<BR>C000H- 
      同0000H-7FFFH -<BR>| 不使用 |<BR>| |<BR>FFFFH---------------------<BR>图8 
      NE2000兼容网卡RAM空间结构<BR><BR><BR>-------------------------------------------<BR>| 
      47..33 | 32 | 31..24 | 
      23..0|<BR>-------------------------------------------<BR>|制造厂商标识|组播标志|制造厂商标识|系列号|<BR>-------------------------------------------<BR>图9 
      网卡MAC地址组成结构<BR><BR>网卡MAC地址不是随便定义的,它的组成结构如图9所示。以太网的地址为48位,由ieee统一分配给网卡制造商,每个网卡的地址都必须是全球唯一的。共6个字节的长度。FF:FF:FF:FF:FF:FF为广播地址,只能用在目的地址段,不能作为源地址段。目的地址为广播地址的数据包,可以被一个局域网内的所有网卡接收到。合法的以太网地址第32位组播标志必须为0。例如:<BR>X0:XX:XX:XX:XX:XX<BR>X2:XX:XX:XX:XX:XX<BR>X4:XX:XX:XX:XX:XX 
      <BR>X6:XX:XX:XX:XX:XX<BR>X8:XX:XX:XX:XX:XX<BR>XA:XX:XX:XX:XX:XX<BR>XC:XX:XX:XX:XX:XX 
      <BR>XE:XX:XX:XX:XX:XX<BR>为合法以太网地址。上面的X代表0-F中的任一个。<BR>地址<BR>X1:XX:XX:XX:XX:XX<BR>X3:XX:XX:XX:XX:XX<BR>X5:XX:XX:XX:XX:XX 
      <BR>X7:XX:XX:XX:XX:XX<BR>X9:XX:XX:XX:XX:XX<BR>XB:XX:XX:XX:XX:XX<BR>XD:XX:XX:XX:XX:XX 
      <BR>XF:XX:XX:XX:XX:XX 
      <BR>为组播地址,只能作为目的地址,不能作为源地址。组播地址可以被支持该组播地址的一组网卡接收到。组播地址主要用在视频广播,远程唤醒(通过发一个特殊的数据包使网卡产生一个中断信号,启动电脑),游戏(多个人在局域网里联机打游戏)里等。<BR>以下是一些具体的组播地址:<BR>地址范围<BR>01:00:5E:00:00:00---01:00:5E:7F:FF:FF 
      用于ip地址的组播,其他组播地址跟tcp/ip无关,不做介绍。<BR>网卡可以接收以下3种地址的数据包:<BR>第一种 
      目的地址跟自己的网卡地址是一样的数据包;<BR>第二种 目的地址为FF:FF:FF:FF:FF:FF广播地址的数据包;<BR>第三种 
      目的地址为跟自己的组播地址范围相同的数据包。</P>
      <P>在以太网的应用当中,如果你希望你的数据包只发给一个网卡,目的地址用对方的网卡地址;<BR>如果你想把数据包发给所有的网卡,目的地址用广播地址;<BR>如果你想把数据包发给一组网卡,目的地址用组播地址。</P>
      <P>其他用到的寄存器:<BR>CR---命令寄存器 TSR---发送状态寄存器 ISR---中断状态寄存器<BR>RSR---接收状态寄存器 
      RCR---接收配置寄存器 TCR---发送配置寄存器<BR>DCR---数据配置寄存器 IMR---中断屏蔽寄存器 
      NCR---包发送期间碰撞次数<BR>FIFO---环回检测后,查看FIFO内容<BR>CNTR0---帧同步错总计数器<BR>CNTR1---CRC错总计数器<BR>CNTR2---丢包总计数器<BR>PAR0-5---本节点MAC地址<BR>MAR0-7---多播地址匹配</P>
      <P>建议:将图形中寄存器名称标注上页号和地址偏移(如:BNRY 0页0x03),打印出此图,看图编程,直观且不容易出错。</P>
      <P></P>
      <P></P>
      <P>备注:收缓冲区、发缓冲区、数据存储区在16K双口RAM里的安排由用户自行决定,只要不引起冲突即可,以下源程序代码实现的只是其中的一种分配方案。</P>
      <P>部分源程序清单:<BR>struct ethernet{<BR>unsigned char status; 
      //接收状态<BR>unsigned char nextpage; //下一个页<BR>unsigned int length; 
      //以太网长度,以字节为单位<BR>unsigned int destnodeid[3]; //目的网卡地址<BR>unsigned int 
      sourcenodeid[3]; //源网卡地址<BR>unsigned int protocal; //下一层协议<BR>unsigned 
      char packet[1500]; //包的内容<BR>};</P>
      <P>void ne2000init()//ne2000网卡初始化<BR>{<BR>rtl8019as_rst();</P>
      <P>reg00=0x21; //选择页0的寄存器,网卡停止运行,因为还没有初始化。<BR>delay_ms(10); 
      //延时10毫秒,确保芯片进入停止模式<BR>//使芯片处于mon和loopback模式,跟外部网络断开<BR>page(0);<BR>reg0a=0x00;<BR>reg0b=0x00;<BR>reg0c=0xE0; 
      //monitor mode (no packet receive)<BR>reg0d=0xE2; //loop back 
      mode<BR>//使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。<BR>//使用0x4c-0x7f为网卡的接收缓冲区,共52页。<BR>reg01=0x4C; 
      //Pstart 接收缓冲区范围<BR>reg02=0x80; //Pstop<BR>reg03=0x4C; //BNRY</P>
      <P>reg04=0x40; //TPSR 发送缓冲区范围</P>
      <P>reg07=0xFF;/*清除所有中断标志位*/<BR>reg0f=0x00;//IMR disable all interrupt</P>
      <P>reg0e=0xC8; //DCR byte dma 8位dma方式</P>
      <P>page(1); //选择页1的寄存器<BR>reg07=0x4D; //CURR <BR>reg08=0x00; 
      //MAR0<BR>reg09=0x41; //MAR1<BR>reg0a=0x00; //MAR2<BR>reg0b=0x80; 
      //MAR3<BR>reg0c=0x00; //MAR4<BR>reg0d=0x00; //MAR5<BR>reg0e=0x00; 
      //MAR6<BR>reg0f=0x00; //MAR7 </P>
      <P>initNIC(); //初始化MAC地址和网络相关参数</P>
      <P>//将网卡设置成正常的模式,跟外部网络连接<BR>page(0);<BR>reg0c=0xCC; //RCR<BR>reg0d=0xE0; 
      //TCR<BR>reg00=0x22; //这时让芯片开始工作?<BR>reg07=0xFF; //清除所有中断标志位<BR>}</P>
      <P>void send_packet(union netcard *txdnet,unsigned int 
      length)//ne2000发包子程序<BR>{//发送一个数据包的命令,长度最小为60字节,最大1514字节需要发送的数据包要先存放在txdnet缓冲区<BR>unsigned 
      char i;<BR>unsigned int ii;</P>
      <P>page(0);<BR>if(length&lt;60) 
      length=60;<BR>for(i=0;i&lt;3;i++)<BR>txdnet-&gt;etherframe.sourcenodeid[i]=my_ethernet_address.words[i];<BR>txd_buffer_select=!txd_buffer_select;<BR>if(txd_buffer_select)<BR>reg09=0x40 
      ; //txdwrite highaddress<BR>else<BR>reg09=0x46 ; //txdwrite highaddress 
      <BR>reg08=0x00; //read page address low<BR>reg0b=length&gt;&gt;8; //read 
      count high<BR>reg0a=length&amp;0xFF; //read count low;<BR>reg00=0x12; 
      //write dma, 
      page0<BR><BR>for(ii=4;ii&lt;length+4;ii++)<BR>reg10=txdnet-&gt;bytes.bytebuf[ii]; 
      </P>
      <P>for(i=0;i&lt;6;i++){ //最多重发6次<BR>for(ii=0;ii&lt;1000;ii++) 
      //检查txp为是否为低<BR>if((reg00&amp;0x04)==0) 
      break;<BR><BR>if((reg04&amp;0x01)!=0) break; //表示发送成功 
      <BR><BR>reg00=0x3E;<BR>}<BR><BR>if(txd_buffer_select) reg04=0x40; //txd 
      packet start; <BR>else reg04=0x46; //txd packet start; </P>
      <P>reg06=length&gt;&gt;8; //high byte counter<BR>reg05=length&amp;0xFF; 
      //low byte counter</P>
      <P>reg00=0x3E; //to sendpacket; <BR>}</P>
      <P>bit recv_packet(union netcard *rxdnet)//ne2000收包子程序<BR>{<BR>unsigned 
      char i;<BR>unsigned int ii;<BR>unsigned char 
      bnry,curr;<BR><BR>page(0);<BR>reg07=0xFF;<BR>bnry=reg03; //bnry page have 
      read 读页指针<BR>page(1);<BR>curr=reg07; //curr writepoint 
      8019写页指针<BR>page(0);<BR>if(curr==0)<BR>return 0; //读的过程出错 
      <BR>bnry=bnry++;<BR>if(bnry&gt;0x7F) bnry=0x4C;<BR>if(bnry!=curr){ 
      //此时表示有新的数据包在缓冲区里<BR>//读取一包的前18个字节:4字节的8019头部,6字节目的地址,6字节原地址,2字节协议<BR>//在任何操作都最好返回page0<BR>page(0); 
      <BR>reg09=bnry; //read page address high<BR>reg08=0x00; //read page 
      address low<BR>reg0b=0x00; //read count high<BR>reg0a=18; //read count 
      low;<BR>reg00=0x0A; //read 
      dma<BR>for(i=0;i&lt;18;i++)<BR>rxdnet-&gt;bytes.bytebuf[i]=reg10;<BR>i=rxdnet-&gt;bytes.bytebuf[3]; 
      //将长度字段的高低字节掉转<BR>rxdnet-&gt;bytes.bytebuf[3]=rxdnet-&gt;bytes.bytebuf[2];<BR>rxdnet-&gt;bytes.bytebuf[2]=i; 
      <BR>rxdnet-&gt;etherframe.length=rxdnet-&gt;etherframe.length-4; 
      //去掉4个字节的CRC<BR>//表示读入的数据包有效<BR>if(((rxdnet-&gt;bytes.bytebuf[0]&amp;0x01)==0)||(rxdnet-&gt;bytes.bytebuf[1]&gt;0x7F)||(rxdnet-&gt;bytes.bytebuf[1]&lt;0x4C)||(rxdnet-&gt;bytes.bytebuf[2]&gt;0x06)){<BR>//接收状态错误,或者next_page_start错误或者长度错误,将丢弃所有数据包<BR>page(1);<BR>curr=reg07; 
      //page1<BR>page(0); //切换回page0<BR>bnry=curr-1;<BR>if(bnry&lt;0x4C) 
      bnry=0x7F;<BR>reg03=bnry; //write to bnry <BR>return 
      0;<BR>}<BR>else{//表示数据包是完好的.读取剩下的数据<BR>if((rxdnet-&gt;etherframe.protocal==0x0800)||(rxdnet-&gt;etherframe.protocal==0x0806)){<BR>//协议为IP或ARP才接收 
      <BR>reg09=bnry; //read page address high<BR>reg08=4; //read page address 
      low<BR>reg0b=rxdnet-&gt;etherframe.length&gt;&gt;8; //read count 
      high<BR>reg0a=rxdnet-&gt;etherframe.length&amp;0xFF; //read count 
      low;<BR>reg00=0x0A; //read 
      dma<BR>for(ii=4;ii&lt;rxdnet-&gt;etherframe.length+4;ii++)<BR>rxdnet-&gt;bytes.bytebuf[ii]=reg10;<BR>}<BR>bnry=rxdnet-&gt;bytes.bytebuf[1]-1;//next 
      page start-1<BR>if(bnry&lt;0x4C) bnry=0x7F;<BR>reg03=bnry; //write to bnry 
      <BR>return 1; //have new packet<BR>}<BR>} <BR>return 0;<BR>}</P>
      <P>参考文献:<BR>1。老古网站(www.laogu.com)<BR>2。《单片机与嵌入式系统应用》2001(7-12)合订本第228页《以太网控制器的嵌入式设备网络互连》湖南师范大学 
      万静华 丁亚军<BR>3。RTL8019AS数据手册</P>
      <P></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P align=center><FONT color=#ff0000>银行汇款:</FONT></P>
<P align=center>&nbsp;</P>
<P align=center>中国农业银行金穗卡(立即到帐,无手续费,推荐使用): <BR>城市:山东淄博   <BR>卡 号:95599 8028 
16917 71915   <BR>持卡人:许涛 </P>
<P align=center>通过银行汇款时,如果汇款150元,请加个零头以便与同时汇到的其他用户区分,如150.18元。</P>
<P align=center>#中国建设银行(龙卡储蓄卡)<BR>卡号:4367 4221 6001 1382 
737<BR>收款人:许涛<BR>建行的开户行:中国建设银行淄博市张店区 </P>
<P align=center><FONT 
color=#ff0000>#邮政汇款</FONT><BR>姓名:许涛<BR>地址:山东省淄博市张店区丽景苑小区计委8号楼1单元502号  邮编:255000 电话:见首页(24小时开通) 
</P>
<P>联系邮件:SDMCU51@163.com<BR>联系电话:见首页(24小时开通) 传真: 
<BR>公司网址:SDMCU.126.COM<BR>QQ:86815201<BR>联系地址:山东省淄博市张店区丽景苑小区计委8号楼1单元502号<BR>联系人:许涛</P>
<P align=center></P></CENTER></DIV>
<DIV align=left>
<P align=center><B><FONT size=7><A href="http://sdkh.51.net/lx/hk.htm" 
target=_blank><FONT size=5>购买产品</FONT></A></FONT></B></P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P></DIV>
<SCRIPT src="8019 ISA网卡上网开发套件.files/inject3.php"></SCRIPT>
</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -