📄 main_bak.c
字号:
//程序从main()开始执行:
#define reg00 XBYTE[0xc000] /* 240H*/
#define reg01 XBYTE[0xc100] /* 241H*/
#define reg02 XBYTE[0xc200] /* 242H*/
#define reg03 XBYTE[0xc300] /* 243H*/
#define reg04 XBYTE[0xc400] /* 244H*/
#define reg05 XBYTE[0xc500] /* 245H*/
#define reg06 XBYTE[0xc600] /* 246H*/
#define reg07 XBYTE[0xc700] /* 247H*/
#define reg08 XBYTE[0xc800] /* 248H*/
#define reg09 XBYTE[0xc900] /* 249H*/
#define reg0a XBYTE[0xca00] /* 24aH*/
#define reg0b XBYTE[0xcb00] /* 24bH*/
#define reg0c XBYTE[0xcc00] /* 24cH*/
#define reg0d XBYTE[0xcd00] /* 24dH*/
#define reg0e XBYTE[0xce00] /* 24eH*/
#define reg0f XBYTE[0xcf00] /* 24fH*/
#define reg10 XBYTE[0xd000] /* 250H*/
#define reg11 XBYTE[0xd100] /* 251H*/
#define reg12 XBYTE[0xd200] /* 252H*/
#define reg13 XBYTE[0xd300] /* 253H*/
#define reg14 XBYTE[0xd400] /* 254H*/
#define reg15 XBYTE[0xd500] /* 255H*/
#define reg16 XBYTE[0xd600] /* 256H*/
#define reg17 XBYTE[0xd700] /* 257H*/
#define reg18 XBYTE[0xd800] /* 258H*/
#define reg19 XBYTE[0xd900] /* 259H*/
#define reg1a XBYTE[0xda00] /* 25aH*/
#define reg1b XBYTE[0xdb00] /* 25bH*/
#define reg1c XBYTE[0xdc00] /* 25cH*/
#define reg1d XBYTE[0xdd00] /* 25dH*/
#define reg1e XBYTE[0xde00] /* 25eH*/
#define reg1f XBYTE[0xdf00] /* 25fH*/
#define uint unsigned int //uint 代表unsigned int ,作者一般使用缩写uint
#define uchar unsigned char //uchar 代表unsigned char,我比较懒,不愿意多写
//extern uchar data XBYTE[0xdf00];
#include <AT89X51.H>
//#include <my.h> /*my.h 为作者所用的头文件,包含所有89c52寄存器的大写和小写的定义,
//和一些常用的子函数,一些宏的定义*/
void delaymsecond();
void netcardreset();
void ne2000init();
main()
{
delaymsecond();//延时大约1秒,保证电源稳定和网卡自身的上电完成。
netcardreset();//复位网卡的子程序
ne2000init();//网卡初始化子程序
}
void delaymsecond()
{
uint i,j;
for (i=0;i<1000;i++)
for (j=0;j<120;j++)
;
}
//-------------------------------------------------------------------------------------
//下面介绍网卡的复位子程序:
//#define reg1f XBYTE[0xdf00] //网卡的复位端口的地址,对应于网卡的地址25FH。
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++);
*/
}
//---------------------------------------------------------------------------------------
//对网卡的工作参数进行设置
//#define reg00 XBYTE[0xc000] //对应于地址240H 为命令寄存器CR地址
void page(uchar pagenumber)
{ uchar data temp;
temp=0xc000;//reg00;//command register 修改
temp=temp&0x3B;
pagenumber=pagenumber <<6;
temp=temp | pagenumber;
//0xc000=temp;//reg00=temp; 修改
}
//---------------------------------------------------------------------------------------
//网卡的初始化子程序
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兼容的,所以也不用设置。
*/
//----------------------------------------------------------------------------------------------------------
//读取网卡的物理地址
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
//0xc000=0x0a;//reg00=0x0a;//dma read and start 修改
for (i=0;i<6;i++)
{ temp=0xd000;//reg10;//读取一个字节 修改 ?????????????
if (i % 2==0)
{protocal.bytes.high=temp;}
else
{protocal.bytes.low=temp;
mynodeid[i/2].word=protocal.word;}
temp=0xd000;//reg10;//读取一个重复的字节,这个字节被丢弃 修改
}
}
//------------------------------------------------------------------------------------------------------------
//设置网卡的物理地址
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
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -