210977|43

1098

帖子

0

TA的资源

至上芯片

楼主
 

单片机与ISA总线以太网解决方案 [复制链接]

单片机与TCP/IP网络



——单片机如何控制以太网网卡进行传输数据,如何加载TCP/IP协议连接到互联网,这些都是一些令人感兴趣的问题。
——可以说以太网和TCP/IP协议已经成为使用最广泛的协议,而其它总线协议如RS485、RS232,CAN,LANWORKS,都只是一些局部系统的总线。
——围绕以太网而制造的集线器,交换机已进入大小公司,企业,家庭。我现在在众达天网公司,由于公司是搞电脑防火墙的,所以对网络的接触也越来越多,我研究的主要是网络的底层,并掌握了很多网络分析工具如(SNIFFER),对以太网和TCP/IP协议的研究就更加深入了。
——我比较熟悉的网卡是10M的网卡,100M的以太网卡还在研究之中。曾经用单片机(89C52)控制和驱动10M的NE2000兼容型以太网卡与电脑主机传输数据。
——现在将我的一些研究成果写成一系列的文单,提供给大家。也许有一天研究了100M的网卡之后,可以让单片机驱动它,那是可能的事,只不过接口可能会复杂一些。
——我所写的驱动程序并不是标准的,因为我没有学过UNIX,无法使用UNIX提供的原代码。如果能使用UNIX的原代码,那将是很好的事。我也正在接触UNIX和VC++,DDK等方面的内容,希望有一天能够重写我现在所写的驱动程序。
[size=+1]
——我知道有很多人在了解单片机与以太网方面的东西,在BBS上也发现了很多这方面的内容,有些人的研究甚至比我还深入,我也希望能跟这些人交流交流,如果对我的文章感兴趣 ,当然可以给我发电子邮件啦。
——在接下来的文章将介绍以太网协议,网卡驱动,IP协议,ICMP协议,ARP协议,TCP协议等 。
此帖出自单片机论坛

最新回复

谢谢分享  详情 回复 发表于 2014-3-9 19:20
点赞 关注
 

回复
举报

1098

帖子

0

TA的资源

至上芯片

沙发
 

(二)以太网协议

——--以太网协议(用于10MBPS的以太网,作者以下所说的以太网均指10M以太网,而不是100M,1000M的以太网)
——以太网协议有两种,一种是IEEE802.2/IEEE802.3,还有一种是以太网的封装格式。
——现代的操作系统均能同时支持这两种类型的协议格式。因此对我们来说只需要了解其中的一种就够了,特别是对单片机来说,不可能支持太多的协议格式。
——以太网的物理传输帧:(仅介绍第二种格式)
PRSDDASATYPEDATAPADFCS
56位8位48位48位16位不超过1500字节可选32位
——PR:同步位,用于收发双方的时钟同步,同时也指明了传输的速率(10M和100M的时钟频率不一样,所以100M网卡可以兼容10M网卡),是56位的二进制数101010101010.....
——SD: 分隔位,表示下面跟着的是真正的数据,而不是同步时钟,为8位的10101011,跟同步位不同的是最后2位是11而不是10.
[size=+1]
——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,TYPE 14字节),还必须传输46字节的数据,当数据段的数据不足46字节时,后面补000000.....(当然也可以补其它值)
----FCS:32位数据校验位.为32位的CRC校验,该校验由网卡自动计算,自动生成,自动校验,自动在数据段后面填入.对于数据的校验算法,我们无需了解.
----事实上,PR,SD,PAD,FCS这几个数据段我们不用理它 ,它是由网卡自动产生的,我们要理的是DA,SA,TYPE,DATA四个段的内容.
----所有数据位的传输由低位开始(但传输的位流是用曼彻斯特编码的)
----以太网的冲突退避算法就不介绍了,它是由硬件自动执行的.
DA+SA+TYPE+DATA+PAD最小为60字节,最大为1514字节.
----以太网卡可以接收三种地址的数据,一个是广播地位,一个是多播地址(我们用不上),一个是它自已的地址.但网卡也可以设置为接收任何数据包(用于网络分析和监控).
----任何两个网卡的物理地址都是不一样的,是世界上唯一的,网卡地址由专门机构分配.不同厂家使用不同地址段,同一厂家的任何两个网卡的地址也是唯一的.根据网卡的地址段(网卡地址的前三个字节),可以知道网卡的生产厂家.有些网卡的地址也可以由用户去设定,但一般不需要.
此帖出自单片机论坛
 
 

回复

1098

帖子

0

TA的资源

至上芯片

板凳
 

(三)ISA总线接口定义

ISA ISA=Industry Standard Architecture (isa总线)

Pin Name Description
引脚 名称 含义
A1 /I/O CH CK I/O channel check; active low=parity error
A2 D7 Data bit 7
A3 D6 Data bit 6
A4 D5 Data bit 5
A5 D4 Data bit 4
A6 D3 Data bit 3
A7 D2 Data bit 2
A8 D1 Data bit 1
A9 D0 Data bit 0
A10 I/O CH RDY I/O Channel ready, pulled low to lengthen memory cycles
A11 AEN Address enable; active high when DMA controls bus
A12 A19 Address bit 19
A13 A18 Address bit 18
A14 A17 Address bit 17
A15 A16 Address bit 16
A16 A15 Address bit 15
A17 A14 Address bit 14
A18 A13 Address bit 13
A19 A12 Address bit 12
A20 A11 Address bit 11
A21 A10 Address bit 10
A22 A9 Address bit 9
A23 A8 Address bit 8
A24 A7 Address bit 7
A25 A6 Address bit 6
A26 A5 Address bit 5
A27 A4 Address bit 4
A28 A3 Address bit 3
A29 A2 Address bit 2
A30 A1 Address bit 1
A31 A0 Address bit 0
B1 GND Ground
B2 RESET Active high to reset or initialize system logic
B3 +5V +5 VDC
B4 IRQ2 Interrupt Request 2
B5 -5VDC -5 VDC
B6 DRQ2 DMA Request 2
B7 -12VDC -12 VDC
B8 /NOWS No WaitState
B9 +12VDC +12 VDC
B10 GND Ground
B11 /SMEMW System Memory Write
B12 /SMEMR System Memory Read
B13 /IOW I/O Write
B14 /IOR I/O Read
B15 /DACK3 DMA Acknowledge 3
B16 DRQ3 DMA Request 3
B17 /DACK1 DMA Acknowledge 1
B18 DRQ1 DMA Request 1
B19 /REFRESH Refresh
B20 CLOCK System Clock (67 ns, 8-8.33 MHz, 50% duty cycle)
B21 IRQ7 Interrupt Request 7
B22 IRQ6 Interrupt Request 6
B23 IRQ5 Interrupt Request 5
B24 IRQ4 Interrupt Request 4
B25 IRQ3 Interrupt Request 3
B26 /DACK2 DMA Acknowledge 2
B27 T/C Terminal count; pulses high when DMA term. count reached
B28 ALE Address Latch Enable
B29 +5V +5 VDC
B30 OSC High-speed Clock (70 ns, 14.31818 MHz, 50% duty cycle)
B31 GND Ground
C1 SBHE System bus high enable (data available on SD8-15)
C2 LA23 Address bit 23
C3 LA22 Address bit 22
C4 LA21 Address bit 21
C5 LA20 Address bit 20
C6 LA18 Address bit 19
C7 LA17 Address bit 18
C8 LA16 Address bit 17
C9 /MEMR Memory Read (Active on all memory read cycles)
C10 /MEMW Memory Write (Active on all memory write cycles)
C11 SD08 Data bit 8
C12 SD09 Data bit 9
C13 SD10 Data bit 10
C14 SD11 Data bit 11
C15 SD12 Data bit 12
C16 SD13 Data bit 13
C17 SD14 Data bit 14
C18 SD15 Data bit 15
D1 /MEMCS16 Memory 16-bit chip select (1 wait, 16-bit memory cycle)
D2 /IOCS16 I/O 16-bit chip select (1 wait, 16-bit I/O cycle)
D3 IRQ10 Interrupt Request 10
D4 IRQ11 Interrupt Request 11
D5 IRQ12 Interrupt Request 12
D6 IRQ15 Interrupt Request 15
D7 IRQ14 Interrupt Request 14
D8 /DACK0 DMA Acknowledge 0
D9 DRQ0 DMA Request 0
D10 /DACK5 DMA Acknowledge 5
D11 DRQ5 DMA Request 5
D12 /DACK6 DMA Acknowledge 6
D13 DRQ6 DMA Request 6
D14 /DACK7 DMA Acknowledge 7
D15 DRQ7 DMA Request 7
D16 +5 V
D17 /MASTER Used with DRQ to gain control of system
D18 GND Ground Note: Direction is Motherboard relative ISA-Cards.


[size=+1](未完)
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

4
 

(四)89C52单片机与网卡接口电路图

——电路是由作者自己设计的,可能不是很标准,也可能不是理想的,但是它可以实现。网卡是ne2000兼容型的网卡。作者所用的网卡是TP-LINK的TE-2008,接口为ISA接口,网卡的主芯片是RTL8019AS.此款网卡在电脑城可以买到。价钱不超过50元。如果买不到,也可以使用别的ne2000的兼容网卡,例如芯片Davicom的DM9008,NSI的DP8390,
MXIC的MX98905,还有华邦的,dlink的。这些芯片的资料可以在本站的硬件程序下载区下载。但推荐使用RTL8019AS。为阅读以下的内容,请在本站下载RTL8019AS的芯片资料。
这是缩小的图,点击这里放大
放大的图可能还不是很清楚,要看更为清楚的图,点击这里下载SCH电路图。(可以用PROTEL 98或PROTEL 99打开。如果你没有protel98,可以在本站下载protel98安装程序(要下载几个小时)。
__电路用到的主要芯片有MAX232(串口的电平转换),24c02(IIC总线的eeprom),373(8位锁存),62256(32K的RAM).其中的24C02也可以不要,可以通过存取网卡上的93C46来实现,但我没有这样做。62256为外部32K的Ram,也可以不用,可以用网卡上的RAM来代替,但是网卡上的Ram的存取比较复杂,速度会比加62256慢。为了编程的方便,和实现快的传输速度,以及为完成更为复杂的应用,推荐使用62256,用77E58单片机和外加62256,可以实现500KBPS以上的传输速度。电路图上方的两大块为ISA槽,网卡是插在这ISA槽上的。本站还有一个一体化的电路图,是将RTL8019AS也做到板上的,来自http://8052.lphard.cz ,这个网站还有现成的程序,是用asm写的,用到的I/O 300H.
--作者以下文章的描述全部基于自己的电路图,而不是来自8052.lphard.cz的电路图,请不要混在一起。作者的全部程序用C51编写,而不是汇编,为了方便大家移植和扩充。


[size=+1](未完)
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

5
 

(五)接口电路图详解(1)

----89c52单片机部分
——ISA接口的A,B部分.
这是RTL8019网卡ISA的前半部分A1--A31(1...31),B1--B31(32...62)共62个引脚.
DATA0--DATA7是网卡的8位数据总线,接单片机的P0口.
RESDRV(33脚)(RESET)接单片机的T0(P3.4),单片机用P3.4来复位网卡。
IRQ9接单片机的INT0(P3.2),IRQ9是网卡的中断9,接到单片机的中断0上。(但我的程序没有使用中断操作,我是用查询操作的)
IOR,IOW接到单片机的p3.6,p3.7(/WR,/RD)
GND是地,VCC为+5V的电源。
A0--A19为网卡的地址线,共20根,我们用到网卡的地址为十六进制的0240H---025FH, 转换为二进制为
地址线A19A18A17A16A15A14A13A12A11A10A9A8A7A6A5A4A3A2A1A0
240H00000000001001000000
...000000000010010XXXXX
25FH00000000001001011111
我们看到从地址240H到25FH,地址线的A19---A5是固定的000000000010010,因此A10--A19接地,A7-A8接地,ADDR8--ADDR15对应地址线的A0--A6.(实际上A5也可以接地,这样可以减少一个单片机的引脚。这是作者在设计电路时没有注意到,同时A9也可以接VCC)。
A0--A6(ADDR8--ADDR15)接单片机的P2口。
因此当P2口为
地址线 A6,A9(ADDR15)A5(ADDR13)A4(ADDR12)A3(ADDR11)A2(ADDR10A1(ADDR9)A0(ADDR8)
10XXXXX
P2口 P2.7P2.5P2.4P2.3P2.2P2.1P2.0
10XXXXX
当P2口为二进制 1X0XXXXX时 将选中网卡的I/O地址空间。在程序里,我使用110XXXXX来选中网卡的地址。
地址映射:
  单片机(P2口)也就是DPH网卡(I/O)
11000000 (0C0H)240H
110XXXXX2XXH
11011111 (0DFH)25FH
我在程序里定义了 reg00--reg1f 来对应240H--25FH端口。
#define reg00 XBYTE[0xc000] /* 240H*/
#define reg01 XBYTE[0xc100] /* 241H*/
#define reg02 XBYTE[0xc200]
#define reg03 XBYTE[0xc300]
...
#define reg1f XBYTE[0xDF00] /* 25FH*/

---ISA接口的C,D部分



这是网卡的接口的后半部分,ISA槽的扩展部分。只用到GND,VCC,IOCS16.其中的IOCS16是16位I/O的选择脚。当网卡上电复位的时候,这个脚为网卡的输入脚,如果这个脚为低电平,网卡将选择8位模式,如果这个脚为高电平,网卡将选择16位的模式。我用了个电阻R10下拉,因此在复位时,这个脚为低电平,网卡选择8位模式。
--网卡可以兼容8位和16位操作。由于89c52是8位的数据总线,因此要用网卡的8位总线模式(每次读入或写入1个字节)。如果你是用80c196或dsp等16位总线的芯片的话,你可以使用16位的操作模式,这样有更快的传输速度(每次读入或写入2个字节)。(16位总线时,这个下拉电阻去掉,不用接,同时网卡的DATA8--DATA15要接到你的CPU的数据8--15上。DMA操作为16位)
[size=+1](未完)
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

6
 

(六)接口电路图详解(2)

----89c52单片机部分
——外部存储器62256和373。
--这是外部存储器62256(32K字节的RAM),62256的
DATA0--DATA7接单片机的P0口。
/OE接单片机的/RD
/WE接单片机的/WR
/CE接单片机的P2.7
A0--A14接单片机的P2.0-P2.6

----373的
DATA0--DATA7接单片机的P0口
/OE接地
LE接单片机的ALE。
---因此外部存储器62256占用单片机的外部数据地址空间0000H--7FFFH,共32K字节。
我们使用外部RAM的目的是提高单片机的数据传输速度,和复杂的TCP/IP的处理。由于以太网的包最大可以有1500多字节,89c52单片机是无法存储这么大的包的,只有放到外部的RAM里。同时这外部的RAM也用作串行口的输入输出缓冲。以使单片机可以高速的吞吐数据。(用网卡上的RAM来代替62256会影响速度)

----MAX232,24c02



--24C02是IIC总线的eeprom,可以用来存储用户的一些设置,比如IP地址,网关等。
SCL接单片机的T1(P3.5)
SDA接单片机的INT1(P3.3)
---MAX232为串口电平转换电路。
CPUTXD接单片机的TXD
CPURXD接单片机的RXD
PCRXD和PCTXD是RS-232电平,为标准串口电平。数据可以从串口输入到单片机,单片机再把数据送到网卡传出去。
晶振可以用11.0592Mhz,也可以用22.1184Mhz,或更高的频率。

此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

7
 

(七)网卡上电复位

----当你买到一个新的RTL8019AS网卡,你要先将该网卡设置为以下的配置:
操作方式Operating Mode:跳线方式Jumperless(不是即插即用Plug and Play)
端口I/O base: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个寄存器地址。
10H DMA地址 (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引脚并联,单片机复位的时候,网卡也复位,以减少一个单片机的引脚的使用。这种情况下,为了保证能够完全复位,可以使用下面介绍的热复位代码。
跟复位有关的寄存器:
18H--1FH共8个地址,为复位端口。对该端口偶数地址的读,或者写入任何数,都引起网卡的复位。
跟复位有关的标志位:

其中的第7位RST跟复位有关。
网卡执行正确的复位之后该位为1。在linux或windows的驱动程序中,一般在复位之后检查该标志位以确认是否正确复位,特别是在即插即用的检测过程中。对于我们用单片机控制网卡来说,我们可以不检查该标志位,因为如果复位不正常的情况通常是网卡坏了。

寄存器:00H--0FH共16个地址是寄存器地址。寄存器分成4页PAGE0--PAGE3,但NE2000兼容的寄存器只有3页(Page0-Page2),(第四页是RTL8019AS自己定义的,我们不用去管这些寄存器,因为你对第四页的寄存器的操作仅对这个网卡是有效的,如果你换成其他Ne2000兼容的网卡,例如DM9008,DP8390等,你的程序将无法正常运行。 为了保证驱动程序对所有Ne2000的网卡有效,不要去操作第四页的寄存器)
由于寄存器较多,我将在用到该寄存器的时候才对该寄存器介绍。

---对网卡进行复位:
这是网卡驱动程序的需要做的第一个内容,由于我们将网卡设置为跳线模式,而不是即插即用的模式,RTL8019AS.PDF中介绍的PLUG and PLAY的一些过程,我们不需要做,因为单片机的资源有限,能够减少的操作,都尽量减少。
程序从main()开始执行:
#include /*my.h 为作者所用的头文件,包含所有89c52寄存器的大写和小写的定义,
和一些常用的子函数,一些宏的定义*/
main()
{
delaymsecond(10);//延时大约1秒,保证电源稳定和网卡自身的上电完成。
netcardreset();//复位网卡的子程序
。。。。
}
下面介绍网卡的复位子程序:
#define reg1f XBYTE[0xdf00] //网卡的复位端口的地址,对应于网卡的地址25FH。
#define uint unsigned int //uint 代表unsigned int ,作者一般使用缩写uint
#define uchar unsigned char //uchar 代表unsigned char,我比较懒,不愿意多写
sbit reset=p3^4; //单片机的p3.4脚连接到网卡的RSTDRV复位引脚
void netcardreset()
{uint data i;
uchar data temp;
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是没有冲突和正常工作的。当然如果读者愿意,也可以写一些检查代码。
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

8
 

(八)网卡初始化

---- 完成复位之后,你要对网卡的工作参数进行设置.以使网卡开始工作.
先介绍一个子函数
#define reg00 XBYTE[0xc000] //对应于地址240H 为命令寄存器CR地址
void page(uchar pagenumber)
{ uchar data temp;
temp=reg00;//command register
temp=temp&0x3f;
pagenumber=pagenumber <<6;
temp=temp | pagenumber;
reg00=temp;
}

错误修正:(2001年11月10日) :以上程序有问题,在中断驱动或发送数据包不作等待时,因为发送数据包的命令是让TXP置位,如果在发送数据包的过程中,使用该函数,就会不断地向外发送数据包.原因是TXP置位之后,只能是发完数据包的时候,由网卡内部将TXP位清0,命令不能使TXP清0,对该位写入0没有作用.读取时要屏蔽该位,上面的程序修正如下,请用户使用下面的程序:
void page(uchar pagenumber)
{uchar data temp;
temp=reg00;
temp=temp&0x3B; //注意不是0x3F ,TXP位在平时一定要置为0.
pagenumber=pagenumber<<6
temp=temp|pagenumber;
reg00=temp;
}
从实验当中也发现,只要再置位TXP位就可以重发该数据包(重发数据包时,不需要设置TPSTART,TBCR0,TBCR1).
作用是选择指定的页,网卡共有4页寄存器,Ne2000兼容的有3页。第四页可以不用。
reg00命令寄存器:CR,command register,地址偏移量00H,为一个字节
76543210
名字PS1PS0RD2RD1RD0TXPSTASTP
PS1和PS0这两个位用来选择寄存器页,PS1 PS0=00时选择寄存器页0,=01时选择寄存器页1, =10时选择寄存器页2,=11时选择寄存器页3.
上面的程序的参数为pagenumber,用来指定第几页。
temp=reg00 ;//读入命令寄存器的值。
temp=temp&0x3f;//将高2位,即PS1,PS0清0
pagenumber=pagenumber<<6;//将低2位移至高端
temp=temp|pagenumber, //写入高2位
reg00=temp; //设置第几页
当然也可以写成更加简单的几句:
temp=reg00&0x3f;
pagenumber=pagenumber<<6;
reg00=temp|pagenumber;
但这样对读者来说不好理解。
从执行的速度来说,上面的代码也不是最快的。但作者主要讲述原理,而不是探讨最快的实现。
--RD2,RD1,RD0这3个位代表要执行的功能。
=001 读网卡内存
=010 写网卡内存
=011 发送网卡数据包
=1** 完成或结束DMA的读写操作
---TXP这个位写入1时发送数据包,发完自动清零
---STA,STP这两个位用来启动命令或停止命令
=10 启动命令
=01 停止命令
下面介绍网卡的初始化子程序:
void ne2000init()
{ 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; //IMR disable all interrupt
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兼容的,所以也不用设置。
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

9
 

(九)读取网卡的网卡地址

---- 完成上面的过程之后,网卡还不能正确的接收数据包,因为我们还没有对网卡的物理地址(网卡地址,48位的地址)进行设置。网卡还不知道它应该什么地址的数据包。要对网卡的物理地址进行设置,就必须知道网卡的物理地址是多少。
读取网卡的物理地址的子程序:
union u {uint word; struct{uchar high;uchar low;}bytes;}; //我定义的数据结构,为两个字节的结构 //,可以按照uint(unsigned int)来读取,也可以按照高低字节high和low来读取。
union u mynodeid[3];//存储网卡的物理地址
union u protocal; //临时变量
void readmynodeid()
{uchar data i,temp;
page(0);
reg09=0;//寄存器RSAR1 dma read highaddress=0
reg08=0;//RSAR0 dma read lowaddress=0;
reg0b=0; //RBCR1 read count high
reg0a=12;//RBCR0 count low
reg00=0x0a;//dma read and start
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;//读取一个重复的字节,这个字节被丢弃

}
}

--网卡除了16k(地址0x4000-0x7FFFF)的接收发送存储RAM之外,还有别的RAM,还有一块大小为256字节的RAM,地址为0x0000-0x00FF,这部分RAM是eeprom 93C46的影像存储(不完全一样),存储的内容的一部分跟93C46存储的是一样的。 网卡在上电的时候将93C46的一部分内容读到这256字节的RAM里。
存储是WORD类型,其中地址:
0x0000-0x000b共12个字节是网卡的物理地址。(网卡的物理地址是6个字节的,为什么要用12字节?因为这12字节是重复存储的。例如网卡物理地址0x52544CC118CF,存储在0x0000-0x000b里是这样的:
525254544C4CC1C11818CFCF
我们可以看到单和双的地址存储的是一样的。0x000b后面的地址存储的是生产厂商的代码和产品标识代码,也是单双地址重复存储,这里就不说了。

这个程序又用到4个新的寄存器:RSAR1 RSAR0 RBCR1 RBCR0
这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个字节)里。
}

此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

10
 

(十)设置网卡地址

---- 很久没有写网卡的文章了,很多网友很关心其他方面的内容,也只好写下去.
以下程序是设置网卡的地址,只有符合这个地址的数据包才接收.

void writemynodeid()
{ 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
这几个寄存器是网卡的工作时候用的地址,只有符合这个地址的数据包才接收,这个地址是可以设置为其他的值,不一定设置为网卡的物理地址,为了不跟别的网卡地址冲突,最好设置为网卡的地址,(如果用户需要设置为其他的值,也是可以的).
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

11
 

(十一)RTL8019AS网卡的电路图

有些人想做成一体化的电路板,我在这里提供一下RTL8019AS网卡的电路图。电路图为双端口的网卡(含utp和bnc接口)。有该原理图,就可以自己制造isa接口的网卡。
包含3种格式,一是pdf(扩展名为pdf),一是orcad(扩展名为.dsn),一是protel99格式(扩展名为.ddb)。

8019sch.zip

142.17 KB, 下载次数: 185

此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

12
 

(十二)RTL8019AS的跳线方式

rtl8019as有3种工作方式:
第一种为跳线方式,网卡的i/o和中断由跳线决定
第二种为即插即用方式,由软件进行自动配置plug and play
第三种为免跳线方式,网卡的i/o和中断由外接的93c46里的内容决定。
我们买到的网卡一般只支持第2和第3种。在嵌入式应用的 场合,如果可以不使用93c46的话,可以降低成本,同时又减少连线。那么我们如何使用第1种方式跳线方式呢?网卡使用哪种方式由rtl8019as的第65脚JP决定。我们来看引脚图:



第65脚jp是输入引脚,当65脚为低电平时,8019工作在第2种或第3种方式,具体由93c46里的内容决定。我们买到的 rtl8019as网卡一般第65脚为悬空的,rtl8019as悬空时,引脚的 输入状态为低电平(其他引脚也是这样,悬空的输入脚的电平为低电平,里面有一个100k的下拉电阻),网卡工作在第2,3种工作方式,需要使用93c46芯片。如果我们把65脚接高电平(vcc),那么网卡的i/o和中断就不是用93c46的内容决定,这时不需要使用93c46,可以不接93c46。那么这时候的i/o和中断irq是多少呢?这时需要用到
64,65,78,79,80,81,82,84,85等引脚。

64脚aui,该引脚决定使用aui还是bnc接口。我们用的网卡的接口一般是bnc的,很少用aui。bnc接口方式支持8线双绞或同轴电缆。高电平时使用aui接口,悬空为低电平,使用bnc接口。我们将该引脚悬空即可。
65脚jp 为高电平时(接到vcc或通过一个10k的电阻上拉)使用跳线方式,这时芯片的i/o地址由以下几个引脚85,84,82,81(IOS3..IOS0)决定:



芯片的中断线由以下引脚80,79,78(IRQS2..IRQS0)决定:


芯片的brom地址由以下引脚72,71,69,68,67(BS4..BS0)决定:

在嵌入式领域一般都不用该brom。brom是boot rom的缩写。在电脑里用来做无盘工作站时候用到,可以从网卡进行引导,而不是从a盘,c盘等引导系统。
网络接口类型由74,77(PL0,PL1)引脚决定:

我们使用第一种自动检测就可以了。会自动检测接口类型然后进行工作。自动检测是用同轴还是双绞线。

作为一个例子来自
http://8052.lphard.cz
的电路图,该电路图没有使用中断方式工作,使用跳线方式,所以没有接93c46,
I/O地址用的是300H,网络接口为bnc(双绞线),没有使用brom),他使用at89c8252单片机运行在14.74兆赫,支持http协议,24c512用来存储网页,FC22为耦合隔离变压器模块:




此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

13
 

(十三)网卡地址和多点播送(组播)及广播

以太网的地址为48位,由ieee统一分配给网卡制造商,每个网卡的地址都必须是全球唯一的。共6个字节的长度,以下是按我们通常的顺序(不是按ieee的顺序,ieee的顺序为在一个字节中,低位在前,高位在后)

字节543210
47。。4039。。3231。。2423。。1615。。87。。0
例子080009A04AB1
我们需要注意的是以太网地址的第40位是组播地址的标志位(第一个字节的最低位)
(如果以ieee的顺序为第47位为组播地址,第一个字节的高位):
第41位是本地管理地址,该位为1表示自行分配的地址,非ieee分配的地址,(类似于ip地址的内网地址),自行保证任一地址不同即可,用于自建的封闭的网络)
47。。42414039。。2423。。0
制造厂商标识本地管理地址组播标志位制造厂商标识系列号




共6个字节,其中前面3个字节(除了第40位,41位),组成制造厂商的标识,每个制造厂商的前3个字节是不同的,如果两个网卡的前面3个字节是一样的,那么这个卡是同一个公司制造的。同时通过该3个字节就可以反过来知道这个卡是哪个厂制造的。后面3个字节为系列号,由制造厂商给自己生产的网卡分配一个号码,不同网卡的号码必须不同, 网卡地址的制造厂商的3个字节的标识中,例如上面的08:00:09 ,080009 是惠普公司的标识,表示这个卡是惠普公司制造的。3个字节的第一个字节,必须为偶数,上面的08是一个偶数,是因为第40位,就是第一个字节的最低位是组播标识,必须为0。
以下
X0:XX:XX:XX:XX:XX
X2:XX:XX:XX:XX:XX
X4:XX:XX:XX:XX:XX
X6:XX:XX:XX:XX:XX
X8:XX:XX:XX:XX:XX
XA:XX:XX:XX:XX:XX
XC:XX:XX:XX:XX:XX
XE:XX:XX:XX:XX:XX

为合法的以太网网卡地址。上面的X代表0-F中的任一个。如果你不是购买网卡,而是自己购买芯片制造,那么地址怎么办?可以自己使用一个还没有被ieee分配的厂商编号就可以了。就算是使用已经分配的厂商编号也没有不可,只要你能保证在你使用的局域网内,任何两个网卡的地址不一样就可以了。

地址 FF:FF:FF:FF:FF:FF 为广播地址,只能用在目的地址段,不能作为源地址段。目的地址为广播地址的数据包,可以被一个局域网内的所有网卡接收到。

地址

X1:XX:XX:XX:XX:XX
X3:XX:XX:XX:XX:XX
X5:XX:XX:XX:XX:XX
X7:XX:XX:XX:XX:XX
X9:XX:XX:XX:XX:XX
XB:XX:XX:XX:XX:XX
XD:XX:XX:XX:XX:XX
XF:XX:XX:XX:XX:XX 为组播地址,只能作为目的地址,不能作为源地址。组播地址可以被支持该组播地址的一组网卡接收到。组播地址主要用在视频广播,远程唤醒(通过发一个特殊的数据包使网卡产生一个中断信号,启动电脑),游戏(多个人在局域网里联机打游戏)里等。
以下是一些具体的组播地址:
地址 范围
01:00:5E:00:00:00---01:00:5E:7F:FF:FF 用于ip地址的组播
其他组播地址跟tcp/ip无关,不做介绍。

网卡可以接收以下3种地址的数据包:
第一种 目的地址跟自己的网卡地址是一样的数据包
第二种 目的地址为FF:FF:FF:FF:FF:FF广播地址的数据包
第三种 目的地址为跟自己的组播地址范围相同的数据包

那么在以太网的应用当中,如果你希望你的数据包只发给一个网卡,目的地址用对方的网卡地址
如果你想把数据包发给所有的网卡,目的地址用广播地址
如果你想把数据包发给一组网卡,目的地址用组播地址。

rtl8019跟网卡地址有关的寄存器:



物理地址寄存器,位于page1,共6个字节,这就是网卡的地址,复位之后该6个寄存器的值是不定的。
要由用户将网卡地址写入到该6个寄存器中,以后网卡接收到的数据包,会将数据包的目的地址跟这6个寄存器的值进行比较,结果相同的数据包被接收下来。上电复位时从93c46读入的网卡地址不会自动写入到这里,而是放在rtl8019as的内存地址0000H,0002H,0004H,0006H,0008H,000AH,0000CH里。你的程序要从这6个内存地址里读出网卡地址,写入到PAR0-5 共6个寄存器地址里。如果你的系统没有使用93c46来存储该网卡地址,那么要由你的软件自行产生或分配一个网卡地址,写入到6个寄存器里(比如你可以把网卡地址存储在单片机的flash rom里,存储在24c02的eeprom里等)。

跟组播地址有关的寄存器:

为8个寄存器,提供对组播地址的过滤。跟crc的逻辑有关。我对于该8个寄存器跟组播地址的关系不是很清楚,也没有找到相关的资料。将该8个寄存器全部写入0FFH,可以接收所有的组播地址地数据包。全部写入0,将不接收任何组播地址的数据包。在windows 98操作系统里,操作系统写入到这8个寄存器的值为:
MAR0 :00H
MAR1 :41H
MAR2 :00H
MAR3 :80H
MAR4 :00H
MAR5 :00H
MAR6 :00H
MAR7 :00H

写入的这8个值跟具体的组播地址是什么关系?我也不知道。lphard的方案是写入8个0xff 。
那么在嵌入式应用中应该如何处理?建议为全部写入0xff。如果不想支持组播,可以不用理这8个寄存器,或全部写入0。

跟网卡地址有关的标志位:


[size=+1]其中的第3位ATD,0为正常操作,1为由组播地址控制(用作流控)。我们把这个位设置为0。
我们不需要使用流控,因为流控的标准不被所有的网卡支持,有些网卡支持,有些不支持。

其中的PRO,AM,AB跟地址有关:
PRO为1时,将接收所有的数据包,不管任何地址, 统统收下来。通常用在一些网桥,或一些用来监视网络的电脑里。sniffer软件就是利用这个特性,将以太网上所有数据包都收下来进行分析,以统计以太网里的数据传输率,冲突,出错情况,网卡地址情况,ip数据包等情况。
PRO为0时,接收跟自己的地址一样的数据包,其他目的地址的被丢弃(不包括广播和组播包)。我们设置为0就可以了。
AM=1时,接收组播地址的数据包,AM=0时,不接收组播地址的数据包。 将该位根据你的情况设置为1或0,推荐设置为1。
AB=1时,接收广播地址的数据包,AB=0时,不接收广播地址FF:FF:FF:FF:FF:FF的数据包。该位要设置为1,才能实现tcp/ip协议。

PHY跟地址有关:
为接收的情况报告。

[size=+1]参考:IP组播地址转换为以太网组播地址
二、组播地址

    大家知道,IP地址空间被划分为A、B、C三类。第四类即D类地址被保留用做组播地址。在第四版的IP协议(IPv4)中,从224.0.0.0到239.255.255.255间的所有IP地址都属于D类地址。
    组播地址中最重要的是第24位到27位间的这四位,对应到十进制是224到239,其它28位保留用做组播的组标识,如下图所示:
         
                 图1 组播地址示意图

    IPv4的组播地址在网络层要转换成网络物理地址。对一个单播的网络地址,通过ARP协议可以获取与IP地址对应的物理地址。但在组播方式下ARP协议无法完成类似功能,必须得用其它的方法获取物理地址。在下面列出的RFC文档中提出了完成这个转换过程的方法:
    RFC1112:Multicast IPv4 to Ethernet physical address correspondence
    RFC1390:Correspondence to FDDI
    RFC1469:Correspondence to Token-Ring networks
    在最大的以太网地址范围内,转换过程是这样的:将以太网地址的前24位最固定为01:00:5E,这几位是重要的标志位。紧接着的一位固定为0,其它23位用IPv4组播地址中的低23位来填充。该转换过程如下图所示:

                 
                        图2 地址转换示意图

   
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

14
 

回复 13楼 的帖子

例如,组播地址为224.0.0.5其以太网物理地址为01:00:5E:00:00:05。
还有一些特殊的IPv4组播地址:
    224.0.0.1:标识子网中的所有主机。同一个子网中具有组播功能的主机都是这个组的成员。
    224.0.0.2:该地址用来标识网络中每个具有组播功有的路由器。
    224.0.0.0----224.0.0.255范围内的地址被分配给了低层次的协议。向这些范围内的地址发送数据包,有组播功能的路由器将不会为其提供路由。
    239.0.0.0----239.255.255.255间的地址分配用做管理用途。这些地址被分配给局部的每一个组织,但不可以分配到组织外部,组织内的路由器不向在组织外的地址提供路由。
    除了上面列出的部分组播地址外,还有许多的组播地址。在最新版本的RFC文档“Assinged Numbers”中有完整的介绍。
    下面的表中列出了全部的组播地址空间,同时还列出了相应的地址段的常用名称及其TTL(IP包的存活时间)。在IPv4组播方式下,TTL有双重意义:正如大家所知的,TTL原本用来控制数据包在网络中的存活时间,防止由于路由器配置错误导致出现数据包传播的死循环;在组播方式下,它还代表了数据包的活动范围,如:数据包在网络中能够传送多远?这样就可以基于数据包的分类来定义其传送范围。
    范围 TTL 地址区间 描述
节点(Node) 0 只能向本机发送的数据包,不能
                                         向网络中的其它接口传送
链路(Link) 1 224.0.0.0-224.0.0.255 只能在发送主机所在的一个子网内的
                                        传送,不会通过路由器转发。
部门 32 239.255.0.0-239.255.255.255 只在整个组织下的一个部门内
(Department) 传送
组织 64 239.192.0.0--239.195.255.255 在整个组织内传送
(Organization)
全局(Global)255 224.0.1.0--238.255.255.255 没有限制,可全局范围内传送


三、组播的工作过程
  
    在局域网内,主机的网络接口将到目的主机的数据包发送到高层,这些数据包中的目的地址是物理接口地址或广播地址。
    如果主机已经加入到一个组播组中,主机的网络接口就会识别出发送到该组成员的数据包。
    因此,如果主机接口的物理地址为80:C0:F6:A0:4A:B1,其加入的组播组为224.0.1.10,则发送给主机的数据包中的目的地址必是下面三种类型之一:
    接口地址:80:C0:F6:A0:4A:B1
    广播地址:FF:FF:FF:FF:FF:FF
    组播地址:01:00:5E:00:01:0A
    广域网中,路由器必须支持组播路由。当主机中运行的进程加入到某个组播组中时,主机向子网中的所有组播路由器发送IGMP(Internet分组管理协议)报文,告诉路由器凡是发送到这个组播组的组播报文都必须发送到本地的子网中,这样主机的进程就可以接收到报文了。子网中的路由器再通知其它的路由器,这些路由器就知道该将组播报文转发到哪些子网中去。
    子网中的路由器也向224.0.0.1发送一个IGMP报文(224.0.0.1代表组中的全部主机),要求组中的主机提供组的相关信息。组中的主机收到这个报文后,都各将计数器的值设为随机值,当计数器递减为0时再向路由器发送应答。这样就防止了组中所有的主机同时向路由器发送应答,造成网络拥塞。主机向组播地址发送一个报文做为对路由器的应答,组中的其它主机一旦看到这个应答报文,就不再发送应答报文了,因为组中的主机向路由器提供的都是相同的信息,所以子网路由器只需得到组中一个主机提供的信息就可以了。
    如果组中的主机都退出了,路由器就收不到应答,因此路由器认为该组目前没有主机加入,遂停止到该子网报文的路由。IGMPv2的解决方案是:组中的主机在退出时向224.0.0.2 发送报文通知组播路由器。
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

15
 

(十四)以太网组播地址过滤寄存器的计算

终于找到关于RTL8019AS里的 MAR0-MAR7的计算的程序,源程序是80x86的汇编,我把它转换成了在keil c51里的程序,以便可以在51单片机里使用。

跟组播地址有关的寄存器:

为8个寄存器,提供对组播地址的过滤。跟crc的逻辑有关。MAR0-7 全部设置为0xff时,将接收所有的组播数据包,将MAR0-7 全部设置为0x00时,将不接收所有组播地址的数据包。在windows98里,该值被设置为:
MAR0=0x00;
MAR1=0x41;
MAR2=0x00;
MAR3=0x80;
MAR4=0x00;
MAR5=0x00;
MAR6=0x00;
MAR7=0x00;

用户在嵌入式的应用当中,可以设置为全部0xff,也可以对特定的组播地址(比如你用在网络电台广播)进行计算,生成一个你需要的过滤参数。建议该过滤的算法不写在单片机里,最好是先算好,存储在单片机里,用的时候直接调用,以节省单片机的程序空间。


这8个寄存器的值是根据组播地址数组的值生成的,提供对组播地址的过滤,过滤掉一些不属于自己接收组播数据包。
以下是在80x86 里的汇编程序:
;注解: laogu  http://www.laogu.com
;这是一段在80x86里的汇编源程序,用来生成多播地址过滤的 MAR0-MAR7(以太网卡里的多播地址过滤寄存器)
;多播也叫组播。程序调用的时候 将组播地址列表的地址传递到ds:si ,
;列表相当于c语言里的二维数组 unsigned char multicast_addresses[ax][6];
;   因为每个地址的长度为6,总共有ax个组播地址。
; ds:si 相当于c语言里的指针 unsigned char *multicast_addresses ;
;将地址总数传递到ax,字节数(=地址总数*6)传递到        cx里(在这个程序里,没有用到cx传递的值)



;程序运算的结果放在mcast_list_bits里,相当于c语言里的unsigned char mcast_list_bits[8];
;程序里的di相当于c语言里的指针 unsigned char *mcast_list_bits;
;mcast_list_bits[8]对应于地址过滤寄存器MAR[8],即MAR0---MAR7

;函数 set_hw_multi        ; Set the multicast mask bits in chip是将mcast_list_bits[8]写入到MAR0--MAR7
;的一个函数调用,这里没有写。

        public        set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
;  cx = number of bytes.
;入口调用: 将list of multicast addresses 组播地址列表(可以有多个组播地址)的地址放在
;ds:si  指针里。ax为多播地址的个数。cx为字节数

;return nc if we set all of them, or cy,dh=error if we didn't.
;设置成功返回c=0,失败c=1(c就是cy,cpu标志位)
        assume ds:code

        mov        cx,ax                        ;keep a count of addresses in cx.
               ;cx=多播地址的个数
        mov        di,offset mcast_list_bits ;di=64位的多播地址crc
        xor        ax,ax
        mov        [di+0],ax
        mov        [di+2],ax
        mov        [di+4],ax
        mov        [di+6],ax   ;将多播地址8个字节的crc全部设置为0
        jcxz        set_mcl_2   ;cx=0 跳到set_mc1_2,将多播地址crc设置为全部0
set_mcl_1:
        call        add_mc_bits  ;调用crc计算
        loop        set_mcl_1
set_mcl_2:
        call    set_hw_multi        ; Set the multicast mask bits in chip
                                ;将mcast_list_bits[8]  8个字节分别写入到MAR0--MAR7
                                ;mcast_list_bits[0]对应于MAR0   .
        clc
        ret
;=================
add_mc_bits:  开始计算
;entry:        ds:si -> multicast address, di-> sixty-four bit multicast filter.
;preserve cx, di, increment si by EADDR_LEN
        push        cx ;保存cx,就是保存多播地址的个数
        mov        cx,EADDR_LEN  ;EADDR_LEN就是以太网地址的长度=6
        mov        dx,0ffffh                        ; this is msw.
        mov        bx,0ffffh                        ; set 32 bit number
add_mcb_1:
        lodsb  ;将一个字节的数(地址为si指向的数)装到AL里,同时使si地址+1
        call        upd_crc                        ; update crc
        loop        add_mcb_1                ; and loop.
;=============
  ifdef MULTICRC_REVERSE  ;ifdef 到endif这段函数是产生CRC过滤的反顺序码的,
                          ;例如 0000001 反顺序就是 1000000
                          ;就是高位和低位反过来。
                          ;程序的执行将dh里的数反顺序排列
                          ;这段程序应该是没有使用,也就是说我们用的是正顺序码。而不是反顺序码。
        mov        cl,8
add_mcb_2:
        shl        dh,1    ;逻辑左移1位,高位进c,地位补0
        rcr        dl,1       ;带进位的循环右移,c进高位,低位进c
        loop        add_mcb_2
        mov        dh,dl
  endif
;====================
        mov        al,dh                        ; get ms 8 bits,
        rol        al,1     ;循环左移,高位进c和低位,
        rol        al,1
        rol        al,1                        ; put 3 bits at bottom
        and        al,7
        mov        bl,al                        ; save in bl
        xor        bh,bh                        ; make bx into an index to the byte.

        mov        al,dh                        ; get ms 8 bits,
        ror        al,1         ;循环右移,低位进c和高位
        ror        al,1                        ; but at bottom
        and        al,7
        mov        cl,al                        ; save in cl
        mov        al,1
        shl        al,cl                        ; set the correct bit,
       
                         ;逻辑左移1位,高位进c,地位补0
           or        [bx+di],al
        pop        cx
        ret

;
;        dx is high,
;        bx is low.
;        al is data
;======================
upd_crc:
        push        cx
        mov        cx,8                ; do 8 bits;cx=次数
        mov        ah,0
upd_crc1:
        shl        bx,1                ; shift bx  ;bx在最开始时被设置为0xffff
                       ;逻辑左移1位,高位进c,地位补0
        rcl        dx,1                ; through dx;dx最开始被设置为0xffff
                   ;带进位循环左移,高位进c,c进低位
        rcl        ah,1                ; carry is at bottom of ah
                    ;带进位循环左移,高位进c,c进低位
        xor        ah,al                ; xor with lsb of data
                  ;逻辑异或,结果放在左边的ah里,相同为0,不同为1
        rcr        ah,1                ; and put in carry bit
                  ;带进位的循环右移,c进高位,低位进c
        jnc        upd_crc2
;
;        autodin is x^32+x^26+x^23x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1
;
        xor        dx,0000010011000001b
        xor        bx,0001110110110110b + 1        ;plus one for end-around carry.
upd_crc2:
        shr        al,1                ; shift the data
          ; 循环右移,高位补0,低位进c
        loop        upd_crc1
        pop        cx
        ret

以下是在keil c51里的c语言程序,为斑竹所写
//作者laogu  http://www.laogu.com//程序的功能是根据多播地址multicast_address[6]的值,计算出MAR0-MAR7,就是multicast_filter[8];//本程序指计算一个多播地址。如果有多个多播地址,将每个多播地址生成的multicast_filter[8]相或就可以了,//例如根据多播地址 01:00:5e:00:00:01生成的 value1=multicast_filter[8];//根据多播地址     01:00:5e:00:00:02生成的 value2=multicast_filter[8];//那么对这两个多播地址生成的multicast_filter[8]=value1  |  value2 ;将两个值相或//很容易从这里得到如果要接收所有多播地址的数据包,MAR0--MAR7必须设置为0xff,就是说//multicast_filter[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};#define al ax_value.bytes.low#define bl bx_value.bytes.low#define cl cx_value.bytes.low#define ah ax_value.bytes.high#define bh bx_value.bytes.high#define dh dx_value.bytes.high#define ax ax_value.word#define bx bx_value.word#define cx cx_value.word#define dx dx_value.word#define shl_bx if((bx&0x8000)!=0){cf=1;}else{cf=0;};bx=bx<<1;#define shl_al if((al&0x80)!=0){cf=1;}else{cf=0;};al=al<<1;#define shr_al if((al&0x01)!=0){cf=1;}else{cf=0;};al=al>>1;#define rcl_dx if((dx&0x8000)!=0){cf_temp=1;}else{cf_temp=0;};dx=dx<<1;if(cf){dx=dx+1;};cf=cf_temp;#define rcl_ah if((ah&0x80)!=0){cf_temp=1;}else{cf_temp=0;};ah=ah<<1;if(cf){ah=ah+1;};cf=cf_temp;#define rcr_ah if((ah&0x01)!=0){cf_temp=1;}else{cf_temp=0;};ah=ah>>1;if(cf){ah=ah+0x80;};cf=cf_temp;#define rol_al if((al&0x80)!=0){cf=1;}else{cf=0;};al=al<<1;if(cf){al=al+1;};#define ror_al if((al&0x01)!=0){cf=1;}else{cf=0;};al=al>>1;if(cf){al=al+0x80;};union u {unsigned int word;         struct{unsigned char high;unsigned char low;}bytes;//字节顺序为高位在前的2byte结构                 };union u ax_value;union u bx_value;union u cx_value;union u dx_value;bit cf;bit cf_temp;unsigned char multicast_address[6]={0x01,0x00,0x5e,0x00,0x00,0x00};//unsigned char multicast_address[6]={0x00,0x00,0x00,0x5e,0x00,0x01};  //只计算一个多播地址//unsigned char multicast_address[6]={0x01,0x80,0xc2,0x00,0x00,0x00};unsigned char multicast_filter[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};                                      //结果放在这里,就是MAR0--MAR7的值//;;0x41,0x00,0x00,0x80,0x00,0x00,0x00,0x00;void up_crc(unsigned char al_byte){al=al_byte;ah=0;for (cx=0;cx<8;cx++){shl_bx;rcl_dx;rcl_ah;ah=ah^al;rcr_ah;if(cf){   dx=dx^0x04c1;//        0000,0100,1100,0001b   bx=bx^0x1db7; //0001,1101,1011,0110b + 1        ;plus one for end-around carry.      }shr_al;}}void add_mc_bits(){unsigned char i;bx=0xffff;dx=0xffff;for(i=0;i<6;i++){up_crc(multicast_address);}cl=8;al=dh;rol_al;rol_al;rol_al;al=al&0x07;bl=al;bh=bh^bh;al=dh;ror_al;ror_al;al=al&0x07;cl=al;al=1;for(i=0;i
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

16
 

(16)对93C46编程

如果RTL8019AS使用了93C46,那么如何通过单片机对它进行编程呢?
93C46是一个有128字节的eeprom,可以是8位或16位的存储模式,在RTL8019AS中,用的是16位的模式,也就是总共有64个16位的存储单元.16位方式下,存储地址为0---63 .每个地址存储两个字节,低位字节在前,高位字节在后(这跟单片机的存储相反,单片机是高位在前,低位在后).
下表是93c46存储的内容,地址是用字节表示的.


设置为跳线方式,i/o地址 240h 的时候,00h-03h的内容如下:
config2 01H: 0x00
config1 00H: 0x96
config4 03H: 0x01
config3 02H: 0x10
04h-09h 是6个字节的网卡地址,也可以修改.

如果我们不使用Plug and Play方式,那么从12h到7fh地址空间可以用来存储用户自己的数据.用户可以在12-7f里写入任何的数据.这样就可以节省用户自己的eeprom(比如24c02).
对93c46读或写要用到两个寄存器,一个是RTL8019AS的命令寄存器CR,一个是第3页的9346CR寄存器.
先向CR写入0xE2选择第3页的寄存器,然后就可以通过存取9346CR来进行93c46的读或者写了.
读93C46的程序:
1.移位输出8位数据的子程序:

注解:
uchar 为unsigned char
reg01即9346CR
reg00为CR
关于reg00 reg01的定义见我前面的相关文章.
9346CR含义:

对93C46读或者写必须使EEM1=1 EEM0=0.
EECS控制93C46的CS脚, RTL8019AS的输出,93C46的输入.
EESK控制93c46的SK脚, RTL8019AS的输出,93C46的输入.
EEDI控制93c46的DI脚, RTL8019AS的输出,93C46的输入.
EEDO是93c46的DO脚的状态,为RTL8019AS的输入,93C46的输出.
93C46引脚图:

93C46的操作的命令:
93C46读操作的时序:

93C46读的程序:

注解:
address为地址,为0---63,字地址,而不是字节地址.
字节地址:00 ,01 用字地址为0
字节地址:02,03 用字地址为1
....
最后一句reg01=0x00,表示向9346CR写入0,退出93C46的读写. 这句不能忽略
返回值为16位的uint(unsigned int).返回值中的高字节为位0--7,低字节为8-15,注意跟单片机的相反.
操作命令为上面的Instution Set里的read.
时序为上面的Read Timing.


93C46的写程序:

注解:
写程序中,address为地址0---63,value为16位(两个字节),必须一次性写入2个字节.
wait for write finish里的for循环是为了不至于程序死锁,比如出错时,可能引起93c46一直处于忙的状态.
这样最多执行查询1万次就退出.这是用户必须注意的,当你编写类似的程序,比如IIC总线的写操作,也要这样做,否则你的单片机可能死在那里.
93C46写入一次的时间为1毫秒左右,最大不超过10毫秒.
93C46允许最大的sk时钟为2Mhz,因为单片机的总线速度不超过2Mhz ,所以每两条指令之间不用插入延时.如果你用比较快的cpu,比如AVR或DSP,可能要插入延时.
reg01=0x00,表示向9346CR写入0,每完成一个93C46的命令,都以它结束.这句不能忽略
写需要执行3个93c46命令:
1.EWEN command写使能
2.WRITE command写数据
3.EWDS command禁止写
三个命令的时序图:


将3个命令结合在一起,才能写入93C46.
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

17
 

单片机的TCP/IP的实现与UNIX的不同

TCP/IP最先是在UNIX系统里实现的,后来的LINUX、DOS、WINDOWS也实现了TCP/IP,随后TCP/IP协议也被移植到其它嵌入式的处理器上,例如8位的MCS51单片机、AVR单片机,16位的ARM、C166以及32位的MIPS、ARM等芯片上。 TCP/IP协议的最底层IP层,很多定义都是16位或32位的,例如源IP地址(32位)目的IP地址(32位),校验值(16位),特别是较验值,是以16位为单位进行计算的,这样使得能够处理16位、32位运算的CPU,比如80286、80386……,ARM、MIPS、DSP,就有很大的速度上的优势。而8位机MCS51处理则会慢很多。
  由于指令的原因,以及资源上的原因,在UNIX上实现的TCP/IP协议的原代码并不能够直接移植到8位的单片机上。最早期的LINUX1.0版的内核是最小的实现TCP/IP的操作系统,它的程序的大小大概在1兆字节。而现在的红旗LINUX,红帽子LINUX,内核多达几十兆,整个系统要几张光盘来装。早期的LINIX因为小,而被移植到掌上电脑,PDA等产品中。 单片机的程序空间是极为有限的,直接寻址的空间仅64K字节,这跟电脑的存储空间相比要差几个数量级。除了程序空间小之外,可用的内存RAM也是非常小的,最多只能扩64K的RAM,而电脑的RAM至少在1兆以上。单片机的运算速度也极为有限,一般只有2MIPS,而电脑上的处理能力在100MIPS以上。
  有些人提到有没有必要在单片机上实现TCP/IP的问题。因为TCP/IP是一种标准,以太网也成为局域网的标准。在很多情况下运用以太网和TCP/IP,能够简化结构。比如目前较热的智能小区,因为布线的原因,不能为每个家庭布很多线,而以太网的8芯双绞是一定有的。例如宽带上网,是直接通过以太网的,如果你制造的设备,比如安全产品,远程抄表产品,家居智能产品能够走以太网的话,可以利用现成的以太网络。但如果走其它网络,比如RS485、CAN单线、LONWORKS等,那么需要另外布线。布线是复杂的,还涉及到消防安全等。从成本看,用以太网实现联网要比CAN、LONWORKS等更为便宜,集线器、交换机现在都非常便宜,而且将来有三网合一的趋势,电话、电视、计算机三网合一。将来的趋势可能是高速的以太网的天下,电话信号、电视信号、联网都在以太网上跑。尽管目前还未能实现,但是这种趋势是不可避免的。
   有网友提到就算要利用以太网,也没有必要跑TCP/IP。那么为什么要跑TCP/IP呢? TCP/IP是一标准,这个标准使得数据传输不一定是要局域网,而可以在互联网、跨地区跨国界。例如你在某一区域安装了很多监控产品,但数据中心可能不设在那个区域,而设在其他地区。TCP/IP有两种协议TCP和UDP;TCP保证了数据传输的正确性,(如果你的数据只跑以及网层,那么你的数据完整性是要你的编程来保证的,校验的计算。数据包的丢失需要你手工处理,而TCP把这些所有你要处理细节都帮你处理了。UDP可以面向广播的、视频的、音频的等方面的应用。实现TCP/IP的协议的好处是可以统一平台,比如智能小区的产品,如果大家都遵守TCP/IP的协议,那么大家的产品才能兼容,假设一个大型的智能社区,这个社区可能由多家设备供应商进行建设,可能有某些厂商做平台、做软件,一些厂商做硬件。如果大家遵守TCP/IP协议,各自的远程抄表产品,智能防盗产品就有可能兼容,对地产开发商来说,可以选择多个供应商,有利于竞争,也避免某个厂家倒闭造成重大影响。
   题外话说的多了,还是回到本章要谈的内容吧。由于单片机与电脑的差别很大,两者的实现有很大的不同。在电脑里编写TCP/IP程序,你可以不考虑代码大小、代码速度,但在单片机上这些都是你要考虑的问题。 综合来说,单片机实现与UNIX实现TCP/IP有如下区别:   (1)、操作系统。不论是WINDOWS、UNIX、LINUX,它们都有一个多任务操作系统,这使得代码编写简单化,而在单片机上,因为资源的原因而无法使用多任务操作系统,这使得代码结构变为顺序执行+硬件中断的方式,而在电脑里却可以并发地执行。对程序执行结构,单片机要考虑更多。
   (2)、内存分配。WINDOWS或UNIX的内存分配是动态的,根据需要随时分配,随时撤消 。我们阅读一些关于LINUX、UNIX的书,它们都是mbuf的存储结构。mbuf是一个存储链,这个链可以动态地增加和减小。比如在数据包很少的情况下,UNIX分配一个2K字节的缓冲区可能就够用了,但如果数据包很多,就有可能要分配64K甚至更多的缓冲区,可分配的内存要根据CPU的可用内存来调整。 但是在单片机却不能够这样做。一个最大的以太网数据包有1500多个字节,分配一包的缓冲区就要1.5K字节,而一般实现TCP/IP的单片机只外接一块32K字节的RAM。而这32K字节的RAM要被各个协议所用,而不仅仅是存放收到的数据包。一般的做法是分配一个256×6=1536个字节的RAM来存放收到的以太网数据包。收到一包就处理一包。而UNIX却可以收很多包才处理。在单片机里,存放收到的以太网数据包的RAM是固定的,而不是动态分配的。所有UNIX关于内存管理、内存分配、mbuf的结构在单片机里并不适用。这些代码对单片机是无用的。
   (3)、指针。在电脑里,指针只有一种,就是指向某一地址的RAM,而在单片机里指针有几种:
   1、 指向外部RAM的指针 例uchar xdata *p 使用指令 movx @dptr 占二个字节
   2、 指向程序ROM的指针 例uchar code *p 使用指令 movc 占二个字节
   3、 指向内部的RAM的指针 例uchar data *p 使用指令 mov @ri 占一个字节
   4、 指向外部RAM的分页指针 例uchar pdata *p 使用指令 movx @ri 占一个字节
   5、 一般指针,可以指向以上的任何一种 占三个字节
   6. 还有其它用于分组切换的指针。
  在电脑里,所有程序都必须先放在RAM里才能运行,所以它的指针只有一种情况,就是指向RAM。而单片机的结构和电脑的结构有很大差别,指针类型很多,对指针运算的速度也不一样,由于第5种指针"一般指针"运算很慢,同时又需要占用很多程序空间,这使得指针运算不能从UNIX源代码直接移植到单片机上,而UNIX实现TCP/IP的源代码中,用的最多的就是指针,而在单片机里一般要求少用指针,或使用特定类型的指针。这使用UNIX的源代码需要作很多的改动。
  (4)、参数传递。在UNIX实现的TCP/IP源代码中,一般有很多的参数传递,而在单片机里允许传递的参数是有限的(因为受到内部RAM的限制),同时参数传递的过程要浪费程序代码空间,也降低单片机执行速度。所以在单片机的实现里,一般不要做太多的参数传递,而多使用公共的全局变量来实现调用的过程。这种情况下,UNIX的一般源程序是相对独立的,受其它函数或变量的影响很小,而单片机里各程序的相互依赖程度要大。因为在单片机里往往共享某一数据、某一变量。
  (5)变量定义。UNIX和KEIL C51虽然都是C语言,但两者又有所不同,对于一些变量的定义,两者却不能通用。例如,单片机的特殊寄存器定义,sfr sfr16 sbit等,在标准C里是没有的。在标准C里支持的结构,在KEIL C里也有可能不支持,比如一些C++的语法。在处理上的特殊性,也可能不一样,比如IP地址类型,在UNIX里一般将IP地址定义为数组:
uchar ip[4]; 而在单片机里,我的定义是
union IP_address_type{uchar bytes[4];
uint words[2];
ulong dwords;}
IP 被定义为共用体,而不是简单的一个数组。为什么要这样做,是因为单片机处理的特殊性,例如比较两个IP地址IP1,IP2是否相等,如果使用数组,比较是麻烦的: 要写成 if(IP1[0]==IP2[1])**IP1[1]=IP2[1]**…… 用共用体可以简化为
if(IP1.dwords==IP2.dwords)…… 有时候,我们又要把IP地址按16位来计算,比如较验和计算,那么IP地址按16位加可以写成: IP.dwords[0]+ IP.dwords[1], 有时,我们又要对IP地址按字节赋值,比如IP地址从24C02里读出来,需要按字节赋值:可以为 IP.bytes[0]=×× IP.bytes[1]=×× IP.bytes[2]=×× IP.bytes[3]=××
如果不作这样的定义,运算将复杂很多。而且一些编译会认为类型混乱而无法编译。 在单片机里使用共用体会简化很多。而在UNIX里要对这些值作改变,一般是利用指针进行的。在电脑里,用指针运算是方便的,而且速度也快,但在单片机里,却不能够方便地使用指针。 在UNIX里的一些结构类型的定义都要被改写。这样也使得UNIX的源代码不能直接用在单片机上。
   (6)、协议支持。在UNIX里可支持比较完整的TCP/IP协议,但在单片机里无法做到,这是因为单片机根本没有足够的代码空间来支持这些协议。一般在单片机里实现与需要有关的部分,而不使用的协议则一概不支持。例如文件共享SMB协议,在UNIX、WINDOWS都支持,但单片机上却没有必要。一般只能在单片机中实现:ARP、IP,ICMP、TCP、UDP这些协议,而更高层的协议,http、smtp、ftp一般是不需要支持的。虽然有些单片机例如AVR上网方案实现了http、smtp、ftp协议,但我们认为实用性不太,因为AVR上网方案用的是MEGA103,而该芯片要150元左右,高昂的造价使得AVR上网方案没有得到广泛的应用。单片机应用的TCP/IP协议大多是为了完成数据采集和数据传输,而不是网页浏览、文件传输这些功能。就对某一协议而言,例如ARP协议,UNIX系统支持以太网、令牌环等网络的ARP,但单片机里只支持以太网,也就是说,对于某一协议,也有可能要作简化。IP包最大可以为65K,可以分段传输,而在单片机里根本无法容纳如此大的数据包,因此一般是不支持分段的。单片机一般采用发送小数据包的方式,以避免分段。
   (7)、硬件接口。在UNIX或WINDOWS里,对网卡驱动无一例外都是采用中断方式。而在单片机的应用中,大部份的方案都是查询式的。因为电脑的处理速度快,一次中断的处理时间也很短,不会影响系统内的其它中断。但在单片机里就不行了,处理一次中断,收取一个数据包一般要几毫秒的时间,这将封锁其它中断的产生(只有高优先级的中断可以执行),而单片机往往还存在其它一些中断,比如串口按收中断,A/D条件中断、键盘中断等需要被执行,这就使得消耗时间长的网卡中断改为查询式执行。在电脑里,对网卡的驱动相对简单,而在单片机里需要处理的事情更多。比如缓冲区溢出,阅读一些驱动程序源代码,你可能发现在电脑里的一些程序根本没有处理溢出的代码。因为电脑执行快,网卡缓冲区的溢出几乎是不会发生的,不要说10M网卡,就是100M网卡,电脑也能够很快处理。电脑往往采用即插即用方式来驱动网卡,而单片机却不能这样做,因为即插即用要很多代码来实现,而使用跳线方式,电脑里驱动NE2000的网卡,一般都是用16位DMA的方式,而在单片机里却只能用8位DMA方式。这也使用UNIX对网卡驱动的代码不能直接移植。
此帖出自单片机论坛
 
 
 

回复

229

帖子

0

TA的资源

纯净的硅(初级)

18
 
呵呵 不错 支持
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

19
 

(15)RTL8019AS一体化电路图

近日做出了一体化的电路图,并通过了测试。主CPU为W78E58,网卡芯片为RTL8019AS。该一体化的电路图直接使用网卡芯片,而不再使用ISA网卡。电路图比较大,由下面的4个图片拼成,有部分电路重叠,请仔细分辨。图片较大,请耐心下载
1.

2.

3.

4.


注:电路是使用跳线方式,电路图中画了93C46,但实际上没有使用93C46,93C46可以不用。如果没有使用中断方式的话,74HC04也可以不用。
24C02可用可不用。使用双绞网线,不使用同轴电缆。IO地址为240H,中断IRQ为2/9 。
此帖出自单片机论坛
 
 
 

回复

1098

帖子

0

TA的资源

至上芯片

20
 

如何使用以太网解决方案中的调试代码

在我们提供的以太网开发板的源代码中,有包含部分调试用的代码,以帮助用户调试和设计过程中出现的问题.调试代码是将一些运行中的状态,变量,数据包内容等信息通过串口发送出来.比如下面的:#ifdef debug
send_string("\r\nTCP: tcp ack");
#endif



包含在#ifdef debug 和#endif 中的代码是调试用的,最终目标代码可以不包含该代码,也就是该代码在不用来调试时,是不需要的,多余的代码.#ifdef 是条件编译开关,控制编译器编译还是不编译该段代码的.在我们提供给用户的代码中,默认的设置是不编译该代码.如果用户需要使用该代码进行调试用,按以下步骤设置:
用鼠标右键点击 target 1:
这将弹出上面的菜单,选择第一项:Options for Target'Target1' :并选择到c51栏的设置(下图是没有使用调试代码的设置):


在第一个输入栏中输入debug=1,如下图所示(下图是使用调试代码的设置):

重新编译连接项目,将会在编译的时候,编译调试代码.然后将生成的ne2000.hex文件写入到芯片中,运行,你可以从超级终端(串口)看到一些调试信息,比如下面的:

而没有使用调试信息时(也就是没有填写debug=1时)的运行情况如下:
此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表