开发指南51单片机+RTL8019上网编程指南.docx

上传人:b****5 文档编号:4712210 上传时间:2022-12-07 格式:DOCX 页数:88 大小:1.08MB
下载 相关 举报
开发指南51单片机+RTL8019上网编程指南.docx_第1页
第1页 / 共88页
开发指南51单片机+RTL8019上网编程指南.docx_第2页
第2页 / 共88页
开发指南51单片机+RTL8019上网编程指南.docx_第3页
第3页 / 共88页
开发指南51单片机+RTL8019上网编程指南.docx_第4页
第4页 / 共88页
开发指南51单片机+RTL8019上网编程指南.docx_第5页
第5页 / 共88页
点击查看更多>>
下载资源
资源描述

开发指南51单片机+RTL8019上网编程指南.docx

《开发指南51单片机+RTL8019上网编程指南.docx》由会员分享,可在线阅读,更多相关《开发指南51单片机+RTL8019上网编程指南.docx(88页珍藏版)》请在冰豆网上搜索。

开发指南51单片机+RTL8019上网编程指南.docx

开发指南51单片机+RTL8019上网编程指南

RTL8019编程指南

(未完待续)

1.绪言

——单片机如何控制以太网网卡进行传输数据,如何加载TCP/IP协议连接到互联网,这些都是一些令人感兴趣的问题。

——可以说以太网和TCP/IP协议已经成为使用最广泛的协议,而其它总线协议如RS485、RS232,CAN,LANWORKS,都只是一些局部系统的总线。

——围绕以太网而制造的集线器,交换机已进入大小公司,企业,家庭。

我现在在众达天网公司,由于公司是搞电脑防火墙的,所以对网络的接触也越来越多,我研究的主要是网络的底层,并掌握了很多网络分析工具如(SNIFFER),对以太网和TCP/IP协议的研究就更加深入了。

——我比较熟悉的网卡是10M的网卡,100M的以太网卡还在研究之中。

曾经用单片机(89C52)控制和驱动10M的NE2000兼容型以太网卡与电脑主机传输数据。

——现在将我的一些研究成果写成一系列的文单,提供给大家。

也许有一天研究了100M的网卡之后,可以让单片机驱动它,那是可能的事,只不过接口可能会复杂一些。

——我所写的驱动程序并不是标准的,因为我没有学过UNIX,无法使用UNIX提供的原代码。

如果能使用UNIX的原代码,那将是很好的事。

我也正在接触UNIX和VC++,DDK等方面的内容,希望有一天能够重写我现在所写的驱动程序。

——我知道有很多人在了解单片机与以太网方面的东西,在BBS上也发现了很多这方面的内容,有些人的研究甚至比我还深入,我也希望能跟这些人交流交流,如果对我的文章感兴趣,当然可以给我发电子啦。

——在接下来的文章将介绍以太网协议,网卡驱动,IP协议,ICMP协议,ARP协议,TCP协议等。

----为帮助读者开发该tcp/ip的应用,本站制作了以太网开发板,可以购买。

 

2.以太网协议

  ——--以太网协议(用于10MBPS的以太网,作者以下所说的以太网均指10M以太网,而不是100M,1000M的以太网)

——以太网协议有两种,一种是IEEE802.2/IEEE802.3,还有一种是以太网的封装格式。

——现代的操作系统均能同时支持这两种类型的协议格式。

因此对我们来说只需要了解其中的一种就够了,特别是对单片机来说,不可能支持太多的协议格式。

——以太网的物理传输帧:

(仅介绍第二种格式)

PR

SD

DA

SA

TYPE

DATA

PAD

FCS

56位

8位

48位

48位

16位

不超过1500字节

可选

32位

——

——SD:

分隔位,表示下面跟着的是真正的数据,而不是同步时钟,为8位的10101011,跟同步位不同的是最后2位是11而不是10.

——DA:

目的地址,以太网的地址为48位(6个字节)二进制地址,表明该帧传输给哪个网卡.如果为FFFFFFFFFFFF,那么是广播地址,广播地址的数据可以被任何网卡接收到.

——SA:

源地址,48位,表明该帧的数据是哪个网卡发的,即发送端的网卡地址,同样是6个字节.

----TYPE:

类型字段,表明该帧的数据是什么类型的数据,不同的协议的类型字段不同。

如:

0800H表示数据为IP包,0806H表示数据为ARP包,814CH是SNMP包,8137H为IPX/SPX包,(小于0600H的值是用于IEEE802的,表示数据包的长度。

----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字节.

----以太网卡可以接收三种地址的数据,一个是广播地位,一个是多播地址(我们用不上),一个是它自已的地址.但网卡也可以设置为接收任何数据包(用于网络分析和监控).

----任何两个网卡的物理地址都是不一样的,是世界上唯一的,网卡地址由专门机构分配.不同厂家使用不同地址段,同一厂家的任何两个网卡的地址也是唯一的.根据网卡的地址段(网卡地址的前三个字节),可以知道网卡的生产厂家.有些网卡的地址也可以由用户去设定,但一般不需要.

3.网卡上电复位

----当你买到一个新的RTL8019AS网卡,你要先将该网卡设置为以下的配置:

操作方式OperatingMode:

跳线方式Jumperless(不是即插即用PlugandPlay)

端口I/Obase:

0240-25FH

中断Interrupt:

2/9(我的程序没有用到网卡中断,所以也可以不用设置)

你要将这个网卡插到你的电脑里,用这个网卡带的设置程序RSET8019.exe将这个卡按照上面的配置设置好。

(最好在纯DOS方式下设置).

--在介绍网卡驱动程序之前,先介绍一下RTL8019AS的基本情况:

3.1.输入输出地址:

共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等奇数地址的复位)

 

3.2.跟复位有关的引脚:

RSTDRV连接到ISA总线的RSTDRV的引脚上。

RSTDRV同时也是ISA总线的复位信号。

RSTDRV为高电平有效,至少需要800ns的宽度。

给该引脚施加一个1us以上的高电平就可以复位。

施加一个高电平之后,然后施加一个低电平。

RSTDRV从高电平到低电平之后要等多久,单片机才可以对网卡进行操作?

复位的过程将执行一些操作,比如将93c46读入,将内部寄存器初始化等。

这些至少需要2毫秒的时间。

我们推荐大家等待更久的时间之后才对网卡操作,比如100毫秒之后才对它操作,以确保完全复位。

对RSTDRV可以接单片机的一个引脚进行对网卡的复位。

但也可以直接将RSTDRV跟单片机的RESET引脚并联,单片机复位的时候,网卡也复位,以减少一个单片机的引脚的使用。

这种情况下,为了保证能够完全复位,可以使用下面介绍的热复位代码。

3.3.跟复位有关的寄存器:

18H--1FH共8个地址,为复位端口。

对该端口偶数地址的读,或者写入任何数,都引起网卡的复位。

3.4.跟复位有关的标志位:

其中的第7位RST跟复位有关。

网卡执行正确的复位之后该位为1。

在linux或windows的驱动程序中,一般在复位之后检查该标志位以确认是否正确复位,特别是在即插即用的检测过程中。

对于我们用单片机控制网卡来说,我们可以不检查该标志位,因为如果复位不正常的情况通常是网卡坏了。

3.5.寄存器:

00H--0FH共16个地址是寄存器地址。

寄存器分成4页PAGE0--PAGE3,但NE2000兼容的寄存器只有3页(Page0-Page2),(第四页是RTL8019AS自己定义的,我们不用去管这些寄存器,因为你对第四页的寄存器的操作仅对这个网卡是有效的,如果你换成其他Ne2000兼容的网卡,例如DM9008,DP8390等,你的程序将无法正常运行。

为了保证驱动程序对所有Ne2000的网卡有效,不要去操作第四页的寄存器)

由于寄存器较多,我将在用到该寄存器的时候才对该寄存器介绍。

3.6.对网卡进行复位:

这是网卡驱动程序的需要做的第一个内容,由于我们将网卡设置为跳线模式,而不是即插即用的模式,RTL8019AS.PDF中介绍的PLUGandPLAY的一些过程,我们不需要做,因为单片机的资源有限,能够减少的操作,都尽量减少。

程序从main()开始执行:

#include/*my.h为作者所用的头文件,包含所有89c52寄存器的大写和小写的定义,

和一些常用的子函数,一些宏的定义*/

main()

{

delaymsecond(10);//延时大约1秒,保证电源稳定和网卡自身的上电完成。

netcardreset();//复位网卡的子程序

}

下面介绍网卡的复位子程序:

#definereg1fXBYTE[0xdf00]//网卡的复位端口的地址,对应于网卡的地址25FH。

#defineuintunsignedint//uint代表unsignedint,作者一般使用缩写uint

#defineucharunsignedchar//uchar代表unsignedchar,我比较懒,不愿意多写

voidnetcardreset()

{

uintdatai;

uchardatatemp;

reset=1;//使网卡的RSTDRV引脚变成高电平,网卡是高电平复位的。

for(i=0;i<250;i++);//延时程序,至少需要

reset=0;//使网卡的RSTDRV引脚变成低电平,网卡上电复位完毕

for(i=0;i<250;i++);

temp=reg1f;//读网卡的复位端口

reg1f=temp;//写网卡的复位端口

for(i=0;i<250;i++);

}

上面所讲的实际上是网卡复位的两种情况,

reset=1;reset=0相当于冷复位

temp=reg1f;reg1f=temp相当于热复位

对网卡的复位端口的读或写将复位网卡,网卡内部将执行复位过程。

读写是随意的,写入任意的数都将复位网卡。

实际上只要使用冷复位就可以了,热复位程序可以不要。

热复位主要在电脑里有用,冷复位就像电脑的冷启动,热复位相当于电脑的热启动。

--作者的复位网卡的过程是简化了的,一个电脑里的复位过程是比较复杂的,如果你有网卡驱动的UNIX,LINUX程序的源代码,它的代码将会做一些判断和检查,检查网卡是否存在,和是否工作正常,和是否存在地址和中断冲突。

但在我们的这个系统里可以省去这些,我们认为网卡的地址和I/O是没有冲突和正常工作的。

当然如果读者愿意,也可以写一些检查代码。

4.网卡初始化

----完成复位之后,你要对网卡的工作参数进行设置.以使网卡开始工作.

先介绍一个子函数

4.1.voidpage(ucharpagenumber)

#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没有作用.读取时要屏蔽该位,上面的程序修正如下,请用户使用下面的程序:

voidpage(ucharpagenumber)

{uchardatatemp;

temp=reg00;

temp=temp&0x3B;//注意不是0x3F,TXP位在平时一定要置为0.

pagenumber=pagenumber<<6

temp=temp|pagenumber;

reg00=temp;

}

从实验当中也发现,只要再置位TXP位就可以重发该数据包(重发数据包时,不需要设置TPSTART,TBCR0,TBCR1).

作用是选择指定的页,网卡共有4页寄存器,Ne2000兼容的有3页。

第四页可以不用。

 

4.2.reg00命令寄存器:

CR,commandregister,地址偏移量00H,为一个字节

7

6

5

4

3

2

1

0

名字

PS1

PS0

RD2

RD1

RD0

TXP

STA

STP

 

 

 

 

 

 

 

 

 

●PS1和PS0这两个位用来选择寄存器页,

PS1PS0=00时选择寄存器页0,=01时选择寄存器页1,=10时选择寄存器页2,=11时选择寄存器页3.上面的程序的参数为pagenumber,用来指定第几页。

temp=reg00;//读入命令寄存器的值。

temp=temp&0x3b;//将高2位,即PS1,PS0清0

pagenumber=pagenumber<<6;//将低2位移至高端

temp=temp|pagenumber,//写入高2位

reg00=temp;//设置第几页

 

当然也可以写成更加简单的几句:

temp=reg00&0x3B;

pagenumber=pagenumber<<6;

reg00=temp|pagenumber;

但这样对读者来说不好理解。

从执行的速度来说,上面的代码也不是最快的。

但作者主要讲述原理,而不是探讨最快的实现。

●RD2,RD1,RD0这3个位代表要执行的功能。

=001读网卡内存

=010写网卡内存

=011发送网卡数据包

=1**完成或结束DMA的读写操作

●TXP这个位写入1时发送数据包,发完自动清零

●STA,STP这两个位用来启动命令或停止命令

=10启动命令

=01停止命令

4.3.下面介绍网卡的初始化子程序:

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

reg0f=0x00;//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兼容的,所以也不用设置。

5.读取网卡的网卡地址

----完成上面的过程之后,网卡还不能正确的接收数据包,因为我们还没有对网卡的物理地址(网卡地址,48位的地址)进行设置。

网卡还不知道它应该什么地址的数据包。

要对网卡的物理地址进行设置,就必须知道网卡的物理地址是多少。

5.1.读取网卡的物理地址的子程序:

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<6;i++)

{

temp=reg10;//读取一个字节

if(i%2==0)

{protocal.bytes.high=temp;}

else{protocal.bytes.low=temp;mynodeid[i/2].word=protocal.word;}

temp=reg10;//读取一个重复的字节,这个字节被丢弃

}

}

5.2.256字节的RAM

--网卡除了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后面的地址存储的是生产厂商的代码和产品标识代码,也是单双地址重复存储,这里就不说了。

5.3.这个程序又用到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个字节)里。

}

6.设置网卡地址

以下程序是设置网卡的地址,只有符合这个地址的数据包才接收.

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1