?? ethernet_51.c
字號:
#include "51Ethernet.h"
/************** 主函數 ***********************/
void main(void)
{
delay(1000); //延時1s,保證電源和網卡自身的上電完成
ClearISR(); //上電后清除中斷狀態寄存器ISR子程序
NICRst(); // RTL8019AS熱復位寄存器
RTL8019Init(); // 初始化RTL8019AS
while(1)
{
SendPacket(union netcard *txdnet,uint length);
RecvPacket(union netcard *rxdnet);
}
}
/* ***************延時t毫秒 *********************/
void delay(uint t)
{
uint i;
while(t--)
{
/************* 對于12M時鐘,約延時1ms ***********/
for (i=0;i<125;i++)
}
}
/* *****************RTL8019AS熱復位 ******************/
void NICRst()
{
uchar i,tmp;
tmp=REG1f; // 讀RTL8019AS的復位端口
REG1f=tmp; // 寫RTL8019AS的復位端口
for(i=0;i<250;i++); //適當延時
}
/**********通過CR寄存器的PS1和PS0設置寄存器頁**********/
void SelectPage(uchar pagenum)
{
uchar tmp;
tmp=REG00;
tmp=tmp&0x3B; // 注意不是0x3F,TXP位在不發送時要置0
pagenum=pagenum<<6;
tmp=tmp|pagenum;
REG00=tmp;
}
/***********初始化RTL8019AS,設置PAGE0、PAGE1*******************/
/**使用0x40-0x4b為網卡的發送緩沖區,共12頁,剛好存儲2個最大的以太網數據包。
使用0x4c-0x7f為網卡的接收緩沖區,共52頁。因此PSTART=0x4c,PSTOP=0x80
(0x80為停止頁,接收緩沖區直到0x7f,不包括0x80)。剛開始時,網卡沒有接收
到任何數據包,因此BNRY設置為指向第一個接收緩沖區的頁0x4c)**/
void RTL8019Init()
{
REG00=0x21; // 選擇頁0的寄存器,網卡停止運行,因為還沒有初始化
REG01=0x4c; // 寄存器PSTART,設置接收緩沖區的起始頁的地址
REG02=0x80; // 寄存器PSTOP,設置接收緩沖區的結束頁的地址
REG03=0x4c; // 寄存器BNRY,設置為指向第一個接收緩沖區的頁0x4c(用作讀指針)
REG04=0x40; // 寄存器TPSR,發送起始頁地址初始化為指向第一個發送緩沖區的頁
REG0c=0xcc; /* 接收配置寄存器RCR,設置為僅接收自己地址的數據包以及廣播地址
和多點播送地址數據包,小于64字節的包丟棄,校驗錯的數據包不接收 */
REG0d=0xe0; // 發送配置寄存器TCR,設置為啟用CRC自動生成和校驗,正常模式工作
REG0e=0xc8; /* 數據配置寄存器DCR,設置為使用FIFO緩存,普通模式,8位數據傳輸,
字節順序為高位字節在前,低位字節在后 */
REG0f=0x00; // 中斷屏蔽寄存器IMR,設置為屏蔽所有中斷
SelectPage(1); // 選擇頁1的寄存器
REG07=0x4d; // 寄存器CURR,設置為指向當前正在寫的頁的下一頁(用作寫指針)
/******** 多址地址寄存器MAR0-MAR7均設置為0x00************/
REG08=0x00; // MAR0
REG09=0x00; // MAR1
REG0a=0x00; // MAR2
REG0b=0x80; // MAR3
REG0c=0x00; // MAR4
REG0d=0x00; // MAR5
REG0e=0x00; // MAR6
REG0f=0x00; // MAR7
GetPhyAddr(); // 獲取以太網物理地址
REG00=0x22; // 選擇頁0寄存器,執行命令。
}
/********************上電后清除ISR寄存器***********************/
void ClearISR()
{
SelectPage(0);
REG07=REG07|0xff;
}
/* 獲取以太網物理地址 */
void GetPhyAddr()
{
uchar tmp;
SelectPage(0); // 選擇頁0
REG08=0; // 遠程DMA起始地址低位寄存器RSAR0,設置為0
REG09=0; // 遠程DMA起始地址高位寄存器RSAR1,設置為0
REG0a=12; // 遠程DMA計數器低位寄存器RBCR0,設置為12
REG0b=0; // 遠程DMA計數器高位寄存器RBCR1,設置為0
REG00=0x0a; // 遠程DMA,啟動命令
SelectPage(1); // 選擇頁1
tmp=REG10; // 讀取一個字節
REG01=tmp; // 寫入PAR0
tmp=REG10; // 讀取一個重復的字節,這個字節被丟棄
tmp=REG10; // 讀取一個字節
REG02=tmp; // 寫入PAR1
tmp=REG10; // 讀取一個重復的字節,這個字節被丟棄
tmp=REG10; // 讀取一個字節
REG03=tmp; // 寫入PAR2
tmp=REG10; // 讀取一個重復的字節,這個字節被丟棄
tmp=REG10; // 讀取一個字節
REG04=tmp; // 寫入PAR3
tmp=REG10; // 讀取一個重復的字節,這個字節被丟棄
tmp=REG10; // 讀取一個字節
REG05=tmp; // 寫入PAR4
tmp=REG10; // 讀取一個重復的字節,這個字節被丟棄
tmp=REG10; // 讀取一個字節
REG06=tmp; // 寫入PAR5
}
void SendPacket(union netcard *txdnet,uint length)//發送數據包子程序
/*發送一個數據包的命令,長度最小為60字節,最大1514字節需要發送的數據包要先存放在txdnet緩沖區*/
{
uchar i;
uint ii;
SelectPage(0);
if(length<60) length=60;
for(i=0;i<3;i++)
txdnet->etherframe.sourcenodeid[i]=my_ethernet_address.words[i];
txd_buffer_select=!txd_buffer_select;
if(txd_buffer_select)
REG09=0x40 ; //遠程開始地址的高位
else
REG09=0x46 ; //遠程開始地址的高位
REG08=0x00; //遠程開始地址的低位
REG0b=length>>8; //遠程字節計數器的高位
REG0a=legth&0xFF; //遠程字節計數器的低位;
REG00=0x12; //寫DMA
for(ii=4;ii reg10=txdnet->bytes.bytebuf[ii]);
for(i=0;i<6;i++){ //最多重發6次
for(ii=0;ii<1000;ii++) //檢查TXP是否為低
if((REG00&0x04)==0) break;
if((REG04&0x01)!=0) break;//表示發送成功
REG00=0x3E;
}
if(txd_buffer_select) REG04=0x40; //開始發送數據包
else REG04=0x46; //開始發送數據包
REG06=length>>8; //發送字節計數器高字節
REG05=length&0xFF; //發送字節計數器低字節
REG00=0x3E; //發送數據
}
bit RecvPacket(union netcard *rxdnet) //接收數據包子程序
{
unsigned char i;
unsigned int ii;
unsigned char bnry,curr;
SelectPage(0);
REG07=0xFF;
bnry=REG03; //邊界指針
SelectPage(1);
curr=REG07; //當前緩沖器頁指針
SelectPage(0);
if(curr==0)
return 0; //緩沖器內沒有新的數據包
bnry=bnry++;
if(bnry>0x7F) bnry=0x4C;
if(bnry!=curr){
/***此時表示有新的數據包在緩沖區里讀取一包的前18個字節:4字節的8019頭部,
6字節目的地址,6字節原地址,2字節協議,在任何操作都最好返回page0*****/
SelectPage(0);
REG09=bnry; //當前遠程DMA地址高8位
REG08=0x00; //當前遠程DMA地址高8位
REG0b=0x00; //字節計數器高8位
REG0a=18; //字節計數器低8位
REG00=0x0A; //遠程DMA讀命令
for(i=0;i<18;i++)
rxdnet->bytes.bytebuf[i]=REG10;
i=rxdnet->bytes.bytebuf[3]; //將長度字段的高低字節互換
rxdnet->bytes.bytebuf[3]=rxdnet->bytes.bytebuf[2];
rxdnet->bytes.bytebuf[2]=i;
rxdnet->etherframe.length=rxdnet->etherframe.length-4;//去掉4個字節的CRC
//表示讀入的數據包有效
if(((rxdnet->bytes.bytebuf[0]&0x01)==0)||(rxdnet->bytes.bytebuf[1]>0x7F)||(rxdnet->bytes.bytebuf[1]<0x4C)||(rxdnet->bytes.bytebuf[2]>0x06)){
//接收狀態錯誤,或者next_page_start錯誤或者長度錯誤,將丟棄所有數據包
SelectPage(1);
curr=REG07;
SelectPage(0); //切換回page0
bnry=curr-1;
if(bnry<0x4C) bnry=0x7F;
REG03=bnry; //write to bnry
return 0;
}
else{ //表示數據包是完好的.讀取剩下的數據
if((rxdnet->etherframe.protocal==0x0800)||(rxdnet->etherframe.protocal==0x0806)){
REG09=bnry;
REG08=4;
REG0b=rxdnet->etherframe.length>>8;
REG0a=rxdnet->etherframe.length&0xFF;
REG00=0x0A;
for(ii=4;iietherframe.length+4;ii++)
rxdnet->bytes.bytebuf[ii]=REG10;
}
bnry=rxdnet->bytes.bytebuf[1]-1; //開始新的一頁
if(bnry<0x4C) bnry=0x7F;
REG03=bnry;
return 1; //開始接收一個新的數據包
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -