RTL8019AS使用Word文件下载.docx
《RTL8019AS使用Word文件下载.docx》由会员分享,可在线阅读,更多相关《RTL8019AS使用Word文件下载.docx(79页珍藏版)》请在冰豆网上搜索。
----DATA:
数据段,该段数据不能超过1500字节。
因为以太网规定整个传输包的最大长度不能超过1514字节。
(14字节为DA,SA,TYPE)
----PAD:
填充位。
由于以太网帧传输的数据包最小不能小于60字节,除去(DA,SA,TYPE14字节),还必须传输46字节的数据,当数据段的数据不足46字节时,后面补000000.....(当然也可以补其它值)
----FCS:
32位数据校验位.为32位的CRC校验,该校验由网卡自动计算,自动生成,自动校验,自动在数据段后面填入.对于数据的校验算法,我们无需了解.
----事实上,PR,SD,PAD,FCS这几个数据段我们不用理它,它是由网卡自动产生的,我们要理的是DA,SA,TYPE,DATA四个段的内容.
----所有数据位的传输由低位开始(但传输的位流是用曼彻斯特编码的)
----以太网的冲突退避算法就不介绍了,它是由硬件自动执行的.
DA+SA+TYPE+DATA+PAD最小为60字节,最大为1514字节.
----以太网卡可以接收三种地址的数据,一个是广播地位,一个是多播地址(我们用不上),一个是它自已的地址.但网卡也可以设置为接收任何数据包(用于网络分析和监控).
----任何两个网卡的物理地址都是不一样的,是世界上唯一的,网卡地址由专门机构分配.不同厂家使用不同地址段,同一厂家的任何两个网卡的地址也是唯一的.根据网卡的地址段(网卡地址的前三个字节),可以知道网卡的生产厂家.有些网卡的地址也可以由用户去设定,但一般不需要.
RTL8019AS--网卡上电复位
当你买到一个新的RTL8019AS网卡,你要先将该网卡设置为以下的配置:
操作方式OperatingMode:
跳线方式Jumperless(不是即插即用PlugandPlay)
端口I/Obase:
0240-25FH
中断Interrupt:
2/9(我的程序没有用到网卡中断,所以也可以不用设置)
你要将这个网卡插到你的电脑里,用这个网卡带的设置程序RSET8019.exe将这个卡按照上面的配置设置好。
(最好在纯DOS方式下设置).
--在介绍网卡驱动程序之前,先介绍一下RTL8019AS的基本情况:
输入输出地址:
共32个,地址偏移量为00H--1FH,(对应于240H--25FH,240H的地址偏移量为0,241H的地址偏移量为1,。
。
25FH的地址偏移量为1FH)。
其中00H--0FH共16个地址,为寄存器地址。
10H--17H共8个地址,为DMA地址。
18H--1FH共8个地址,为复位端口。
对于8位的操作方式,上面的地址中只有18个是有用的:
00H--0FH共16个寄存器地址。
10HDMA地址(10H--17H的8个地址是一样的,都可以用来做DMA端口,只要用其中的一个就可以了)
1FH复位地址。
(18H到1FH共8个地址都是复位地址,每个地址的功能都是一样的,只要其中的一个就可以了,但实际上只有18H,1AH,1CH,1EH这几个复位端口是有效的,其他不要使用,有些兼容卡不支持19H,1BH,1DH等奇数地址的复位)
跟复位有关的引脚:
RSTDRV连接到ISA总线的RSTDRV的引脚上。
RSTDRV同时也是ISA总线的复位信号。
RSTDRV为高电平有效,至少需要800ns的宽度。
给该引脚施加一个1us以上的高电平就可以复位。
施加一个高电平之后,然后施加一个低电平。
RSTDRV从高电平到低电平之后要等多久,单片机才可以对网卡进行操作?
复位的过程将执行一些操作,比如将93c46读入,将内部寄存器初始化等。
这些至少需要2毫秒的时间。
我们推荐大家等待更久的时间之后才对网卡操作,比如100毫秒之后才对它操作,以确保完全复位。
对RSTDRV可以接单片机的一个引脚进行对网卡的复位。
但也可以直接将RSTDRV跟单片机的RESET引脚并联,单片机复位的时候,网卡也复位,以减少一个单片机的引脚的使用。
这种情况下,为了保证能够完全复位,可以使用下面介绍的热复位代码。
跟复位有关的寄存器:
对该端口偶数地址的读,或者写入任何数,都引起网卡的复位。
跟复位有关的标志位:
其中的第7位RST跟复位有关。
网卡执行正确的复位之后该位为1。
在linux或windows的驱动程序中,一般在复位之后检查该标志位以确认是否正确复位,特别是在即插即用的检测过程中。
对于我们用单片机控制网卡来说,我们可以不检查该标志位,因为如果复位不正常的情况通常是网卡坏了。
寄存器:
00H--0FH共16个地址是寄存器地址。
寄存器分成4页PAGE0--PAGE3,但NE2000兼容的寄存器只有3页(Page0-Page2),(第四页是RTL8019AS自己定义的,我们不用去管这些寄存器,因为你对第四页的寄存器的操作仅对这个网卡是有效的,如果你换成其他Ne2000兼容的网卡,例如DM9008,DP8390等,你的程序将无法正常运行。
为了保证驱动程序对所有Ne2000的网卡有效,不要去操作第四页的寄存器)
由于寄存器较多,我将在用到该寄存器的时候才对该寄存器介绍。
---对网卡进行复位:
这是网卡驱动程序的需要做的第一个内容,由于我们将网卡设置为跳线模式,而不是即插即用的模式,RTL8019AS.PDF中介绍的PLUGandPLAY的一些过程,我们不需要做,因为单片机的资源有限,能够减少的操作,都尽量减少。
程序从main()开始执行:
#include<
my.h>
/*my.h为作者所用的头文件,包含所有89c52寄存器的大写和小写的定义,
和一些常用的子函数,一些宏的定义*/
main()
{
delaymsecond(10);
//延时大约1秒,保证电源稳定和网卡自身的上电完成。
netcardreset();
//复位网卡的子程序
}
下面介绍网卡的复位子程序:
#definereg1fXBYTE[0xdf00]//网卡的复位端口的地址,对应于网卡的地址25FH。
#defineuintunsignedint//uint代表unsignedint,作者一般使用缩写uint
#defineucharunsignedchar//uchar代表unsignedchar,我比较懒,不愿意多写
sbitreset=p3^4;
//单片机的p3.4脚连接到网卡的RSTDRV复位引脚
voidnetcardreset()
{uintdatai;
uchardatatemp;
reset=1;
//使网卡的RSTDRV引脚变成高电平,网卡是高电平复位的。
for(i=0;
i<
250;
i++);
//延时程序,至少需要
reset=0;
//使网卡的RSTDRV引脚变成低电平,网卡上电复位完毕
temp=reg1f;
//读网卡的复位端口
reg1f=temp;
//写网卡的复位端口
上面所讲的实际上是网卡复位的两种情况,
reset=0相当于冷复位
reg1f=temp相当于热复位
对网卡的复位端口的读或写将复位网卡,网卡内部将执行复位过程。
读写是随意的,写入任意的数都将复位网卡。
实际上只要使用冷复位就可以了,热复位程序可以不要。
热复位主要在电脑里有用,冷复位就像电脑的冷启动,热复位相当于电脑的热启动。
--作者的复位网卡的过程是简化了的,一个电脑里的复位过程是比较复杂的,如果你有网卡驱动的UNIX,LINUX程序的源代码,它的代码将会做一些判断和检查,检查网卡是否存在,和是否工作正常,和是否存在地址和中断冲突。
但在我们的这个系统里可以省去这些,我们认为网卡的地址和I/O是没有冲突和正常工作的。
当然如果读者愿意,也可以写一些检查代码。
RTL8019AS--网卡初始化
完成复位之后,你要对网卡的工作参数进行设置.以使网卡开始工作.
先介绍一个子函数
#definereg00XBYTE[0xc000]//对应于地址240H为命令寄存器CR地址
voidpage(ucharpagenumber)
{uchardatatemp;
temp=reg00;
//commandregister
temp=temp&
0x3f;
pagenumber=pagenumber<
<
6;
temp=temp|pagenumber;
reg00=temp;
错误修正:
(2001年11月10日):
以上程序有问题,在中断驱动或发送数据包不作等待时,因为发送数据包的命令是让TXP置位,如果在发送数据包的过程中,使用该函数,就会不断地向外发送数据包.原因是TXP置位之后,只能是发完数据包的时候,由网卡内部将TXP位清0,命令不能使TXP清0,对该位写入0没有作用.读取时要屏蔽该位,上面的程序修正如下,请用户使用下面的程序:
{uchardatatemp;
0x3B;
//注意不是0x3F,TXP位在平时一定要置为0.
pagenumber=pagenumber<
6
temp=temp|pagenumber;
从实验当中也发现,只要再置位TXP位就可以重发该数据包(重发数据包时,不需要设置TPSTART,TBCR0,TBCR1).
作用是选择指定的页,网卡共有4页寄存器,Ne2000兼容的有3页。
第四页可以不用。
reg00命令寄存器:
CR,commandregister,地址偏移量00H,为一个字节
位
7
5
4
3
2
1
名字
PS1
PS0
RD2
RD1
RD0
TXP
STA
STP
PS1和PS0这两个位用来选择寄存器页,PS1PS0=00时选择寄存器页0,=01时选择寄存器页1,=10时选择寄存器页2,=11时选择寄存器页3.
上面的程序的参数为pagenumber,用来指定第几页。
temp=reg00;
//读入命令寄存器的值。
//将高2位,即PS1,PS0清0
//将低2位移至高端
temp=temp|pagenumber,//写入高2位
//设置第几页
当然也可以写成更加简单的几句:
temp=reg00&
reg00=temp|pagenumber;
但这样对读者来说不好理解。
从执行的速度来说,上面的代码也不是最快的。
但作者主要讲述原理,而不是探讨最快的实现。
--RD2,RD1,RD0这3个位代表要执行的功能。
=001读网卡内存
=010写网卡内存
=011发送网卡数据包
=1**完成或结束DMA的读写操作
---TXP这个位写入1时发送数据包,发完自动清零
---STA,STP这两个位用来启动命令或停止命令
=10启动命令
=01停止命令
下面介绍网卡的初始化子程序:
voidne2000init()
{reg00=0x21;
//选择页0的寄存器,网卡停止运行,因为还没有初始化。
reg01=0x4c;
//寄存器Pstart
reg02=0x80;
//Pstop
reg03=0x4c;
//BNRY
reg04=0x45;
//TPSR
reg0c=0xcc;
//RCR
reg0d=0xe0;
//TCR
reg0e=0xc8;
//DCR数据配置寄存器8位数据dma
reg0f=0x00;
//IMRdisableallinterrupt
page
(1);
//选择页1的寄存器
reg07=0x4d;
//CURR
reg08=0x00;
//MAR0
reg09=0x41;
//MAR1
reg0a=0x00;
//MAR2
reg0b=0x80;
//MAR3
reg0c=0x00;
//MAR4
reg0d=0x00;
//MAR5
reg0e=0x00;
//MAR6
//MAR7
reg00=0x22;
//选择页0寄存器,网卡执行命令。
}
PSTART接收缓冲区的起始页的地址。
PSTOP接收缓冲区的结束页地址。
(该页不用于接收)
BNRY指向最后一个已经读取的页(读指针)
CURR当前的接收结束页地址。
(写指针)
--网卡含有16K字节的RAM,地址为0x4000-0x7fff(指的是网卡上的存储地址,而不是ISA总线的地址,是网卡工作用的存储器),每256个字节称为一页,共有64页。
页的地址就是地址的高8位,页地址为0x40--0x7f。
这16k的ram的一部分用来存放接收的数据包,一部分用来存储待发送的数据包。
当然也可以给用户使用。
(例如把网卡设置成使用8K的ram,另外8K的ram就可以用来给单片机作为存储器,但我没有这样做,原因是操作网卡上的ram比较复杂)
---在我的程序中使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
使用0x4c-0x7f为网卡的接收缓冲区,共52页。
因此PSTART=0x4c,PSTOP=0x80(0x80为停止页,就是直到0x7f,是接收缓冲区,不包括0x80);
刚开始,网卡没有接收到任何数据包,所以,BNRY设置为指向第一个接收缓冲区的页0x4c)
这四个寄存器用于接收的设置。
--CURR是网卡写内存的指针。
它指向当前正在写的页的下一页。
那么初始化它就应该指向0x4c+1=0x4d。
网卡写完接收缓冲区一页,就将这个页地址加一,CURR=CURR+1。
这是网卡自动加的。
当加到最后的空页(这里是0x80,PSTOP)时,将CURR置为接收缓冲区的第一页(这里是0x4c,PSTART),也是网卡自动完成的。
当CURR=BNRY时,表示缓冲区全部被存满,数据没有被用户读走,这时网卡将停止往内存写数据,新收到的数据包将被丢弃不要,而不覆盖旧的数据。
此时实际上出现了内存溢出。
---而BNRR要由用户来操作。
用户从网卡读走一页数据,要将BNRY加一,然后再写到BNRY寄存器。
当BNRY加到最后的空页(0x80,PSTOP)时,同样要将BNRY变成第一个接收页(PSTART,0x4c)BNRY=0x4c;
---CURR和BNRY主要用来控制缓冲区的存取过程,保证能顺次写入和读出)。
当CURR=BNRY+1(或当BNRY=0x7f,CURR=0x4c)时,网卡的接收缓冲区里没有数据,表示没有收到数据包。
用户通过这个判断知道没有包可以读。
当上述条件不成立时,表示接收到新的数据包。
然后用户应该读取数据包,直到上述条件成立时,表示所以数据包已经读完,此时停止读取数据包。
--TPSR为发送页的起始页地址。
初始化为指向第一个发送缓冲区的页,0x40。
--RCR接收配置寄存器,设置为使用接收缓冲区,仅接收自己的地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃(这是协议的规定,设置成接收是用于网络分析),校验错的数据包不接收。
--TCR发送配置寄存器,启用crc自动生成和自动校验,工作在正常模式。
--DCR数据配置寄存器,设置为使用FIFO缓存,普通模式,8位数据传输模式,字节顺序为高位字节在前,低位字节在后(符合我们的习惯)(如果用16位的单片机,设置成16位的数据总线操作会更快,但80c52是8位总线的单片机)
--IMR中断屏蔽寄存器,设置成0x00,屏蔽所有的中断。
设置成0xff将允许中断)
--MAR0--MAR8是设置多点播送的参数,这点我也不是很清楚,我从电脑读出来是什么数,我也将这8个寄存器设置成这几个数.由于我们不使用多点播送,所以不要紧,只要保证网卡能正常工作就可以了。
--PAGE2的寄存器是只读的,所以不可以设置,不用设置,PAGE3的寄存器不是NE2000兼容的,所以也不用设置。
RTL8019AS--读取网卡的网卡地址
完成上面的过程之后,网卡还不能正确的接收数据包,因为我们还没有对网卡的物理地址(网卡地址,48位的地址)进行设置。
网卡还不知道它应该什么地址的数据包。
要对网卡的物理地址进行设置,就必须知道网卡的物理地址是多少。
读取网卡的物理地址的子程序:
unionu{uintword;
struct{ucharhigh;
ucharlow;
}bytes;
};
//我定义的数据结构,为两个字节的结构//,可以按照uint(unsignedint)来读取,也可以按照高低字节high和low来读取。
unionumynodeid[3];
//存储网卡的物理地址
unionuprotocal;
//临时变量
voidreadmynodeid()
{uchardatai,temp;
page(0);
reg09=0;
//寄存器RSAR1dmareadhighaddress=0
reg08=0;
//RSAR0dmareadlowaddress=0;
reg0b=0;
//RBCR1readcounthigh
reg0a=12;
//RBCR0countlow
reg00=0x0a;
//dmareadandstart
for(i=0;
i++)
{temp=reg10;
//读取一个字节
if(i%2==0)
{protocal.bytes.high=temp;
else{protocal.bytes.low=temp;
mynodeid[i/2].word=protocal.word;
temp=reg10;
//读取一个重复的字节,这个字节被丢弃
--网卡除了16k(地址0x4000-0x7FFFF)的接收发送存储RAM之外,还有别的RAM,还有一块大小为256字节的RAM,地址为0x0000-0x00FF,这部分RAM是eeprom93C46的影像存储(不完全一样),存储的内容的一部分跟93C46存储的是一样的。
网卡在上电的时候将93C46的一部分内容读到这256字节的RAM里。
存储是WORD类型,其中地址:
0x0000-0x000b共12个字节是网卡的物理地址。
(网卡的物理地址是6个字节的,为什么要用12字节?
因为这12字节是重复存储的。
例如网卡物理地址0x52544CC118CF,存储在0x0000-0x000b里是这样的:
525254544C4CC1C11818CFCF
我们可以看到单和双的地址存储的是一样的。
0x000b后面的地址存储的是生产厂商的代码和产品标识代码,也是单双地址重复存储,这里就不说了。
这个程序又用到4个新的寄存器:
RSAR1RSAR0RBCR1RBCR0
这4个寄存器是专门用于读取网卡上面的ram的。
RSAR1网卡上的RAM的起始地址高8位
RSAR0网卡上的RAM的起始地址低8位
--程序中的reg09,reg08都设成0,所以是从网卡上的0x0000地址开始读。
RBCR1要读取的字节数的计数(高8位)
RBCR0要读取的字节数的计数(低8位)
--程序中的reg0b=0,reg0a=12,所以要读取12个字节。
reg00=0x0a的意思是进行DMA的内存读取操作。
--结果将网卡地址存储在mynodeid[3](共6个字节)里。
RTL8019AS--设置网卡地址
以下程序是设置网卡的地址,只有符合这个地址的数据包才接收.
voidwritemynodeid()
{page
(1);
reg01=mynodeid[0].bytes.high;
//PAR0
reg02=mynodeid[0].bytes.low;
//PAR1
reg03=mynodeid[1].bytes.high;
//PAR2
reg04=mynodeid[1].bytes.low;
//PAR3
reg05=mynodeid[2].bytes.high;
//PAR4
reg06=mynodeid[2].bytes.low;
//PAR5
又用到几个新的寄存器,是页1的几个寄存器:
PAR0,PAR1,PAR2,PAR3,PAR4,PAR5
这几个寄存器是网卡的工作时候用的地址,只有符合这个地址的数据包才接收,这个地址是可以设置为其他的值,不一定设置为网卡的物理地址,为了不跟别的网卡地址冲突,最好设置为网卡的地址,(如果用户需要设置为其他的值,也是可以的).
RTL8019AS--RTL8019AS的跳线方式
rtl8019as有3种工作方式:
第一种为跳线方式,网卡的i/o和中断由跳线决定
第二种为即插即用方式,由软件进行自动配置plugandplay
第三种为免跳线方式,网卡的i/o和中断由外接的93c46里的内容决定。
我们买到的网卡一般只支持第2和第3种。
在嵌入式应用的场合,如果可以不使用93c46的话,可以降低成本,同时又减少连线