📄 rtl8019.c
字号:
/**************************************************************************
**
** 文件: RTL8019.c
** 描述: 该文件完成以太网卡的初始化和收发程序
**
**************************************************************************/
//include library files
#include <stdio.h>
#include <string.h>
#include <iom128v.h>
#include <macros.h>
//include user defined files
#include "Define.h"
#include "Global_Variable.h"
#include "RTL8019.h"
/**************************************************************************
**
** 函数: void Delay(uchar)
** 描述: 该函数完成整数倍的5ms软件延时
**
**************************************************************************/
void Delay(uchar N5ms) //5ms
{
uchar i,j;
for(;N5ms>0;N5ms--)
{
for(i=200;i>0;i--)
{
for(j=200;j>0;j--)
;
}
}
}
/**************************************************************************
**
** 函数: void RTL8019_Init(void)
** 描述: 该函数完成以太网卡的初始化
**
**************************************************************************/
void RTL8019_Init(void)
{
//enable output pin for resetting the RTL8019
sbi(RTL8019_RESET_DDR,RTL8019_RESET_PIN);
//硬复位
sbi(RTL8019_RESET_PORT,RTL8019_RESET_PIN);
Delay(1);
cbi(RTL8019_RESET_PORT,RTL8019_RESET_PIN);
//软复位
writeRTL(ISR,readRTL(ISR));
Delay(1);
writeRTL(CR,0x21); //选择Page 0,停止模式,进行初始化
Delay(2); //延时10ms,确保进入停止模式
while(readRTL(CR) !=0x21)
writeRTL(CR,0x21);
writeRTL(ISR,0xff); //清除中断状态
writeRTL(IMR, 0x00); //不允许中断,查询模式
writeRTL(DCR,0xC8); //数据配置寄存器,字节DMA模式
writeRTL(TCR,0xe0); //正常模式
writeRTL(RCR,0xc4); //正常模式,接收广播包,但不接收组播包
writeRTL(PSTART,RXSTART_INIT); //接收起始页
writeRTL(PSTOP,RXSTOP_INIT); //接收停止页
writeRTL(BNRY,RXSTART_INIT); //边界指针,指向接收缓冲环中第一个还未被主机读取的页面
writeRTL(TPSR,TXSTART_INIT); //发送起始页
writeRTL(RBCR0,0x00); //远程DMA字节计数寄存器清零
writeRTL(RBCR1,0x00);
writeRTL(CR,0x61); //选择Page 1
writeRTL(CURR,RXSTART_INIT); //当前页寄存器,记录第一个用于包接收的缓冲环的页地址
//设置本地MAC地址
writeRTL(PAR0,My_MAC[0]);
writeRTL(PAR1,My_MAC[1]);
writeRTL(PAR2,My_MAC[2]);
writeRTL(PAR3,My_MAC[3]);
writeRTL(PAR4,My_MAC[4]);
writeRTL(PAR5,My_MAC[5]);
}
/**************************************************************************
**
** 函数: void Page_Select(uchar)
** 描述: 该函数完成以太网卡页面的选择,入口参数选择0、1、2
**
**************************************************************************/
void Page_Select(uchar pagenumber)
{
uchar VAR;
VAR = readRTL(CR);
VAR &= 0x3b; //TXP清零
pagenumber = pagenumber<<6;
VAR |= pagenumber;
writeRTL(CR, VAR);
}
/**************************************************************************
**
** 函数: void Over_Run(void)
** 描述: 该函数完成以太网卡接收缓冲环溢出的处理
**
**************************************************************************/
void Over_Run(void)
{
uchar dataL,resend=0;
dataL = readRTL(CR);
writeRTL(CR,0x21);
Delay(1);
writeRTL(RBCR1,0x00);
writeRTL(RBCR0,0x00);
if(dataL&0x04) //正在发送
{
dataL = readRTL(ISR);
if((dataL&0x02)||(dataL&0x08))
resend=0;
else
resend=1;
}
writeRTL(TCR,0x02);
writeRTL(CR,0x22);
writeRTL(BNRY,RXSTART_INIT);
writeRTL(CR,0x62);
writeRTL(CURR,RXSTART_INIT);
writeRTL(CR,0x22);
writeRTL(ISR,0x10);
writeRTL(TCR,0x00);
writeRTL(ISR,0xff);
}
/**************************************************************************
**
** 函数: void Send_Packet(uchar *,uint)
** 描述: 该函数完成以太网包的发送,
入口参数分别为指向发送缓冲区的指针和发送的包长度
**
**************************************************************************/
void Send_Packet(uchar *sendbuffer,uint length)
{
uchar i,sendLength;
uint count;
Page_Select(0);
sendLength=(length>=ETHERNET_MIN_PACKET_LENGTH) ? length : ETHERNET_MIN_PACKET_LENGTH;
//等待发送结束,TXP位为1说明正在发送,为0表示发完或出错
for(count=1000;count>0;count--)
if((readRTL(CR)&(1<<CR_TXP))==0)
break;
writeRTL(ISR,(1<<ISR_PTX)); //清除发送的中断标志
writeRTL(RBCR1,(uchar)(length>>8)); //远程计数高字节
writeRTL(RBCR0,(uchar)(length&0xff)); //远程计数低字节
writeRTL(TPSR,TXSTART_INIT); //发送起始页
writeRTL(RSAR1,0x40);
writeRTL(RSAR0,0x00); //发送的起始地址
writeRTL(CR,0x12); //远程写DMA,Page0
//远程DMA写
for(i=0;i<length;i++)
writeRTL(RDMARORT,sendbuffer[i]);
//以下为终止DMA操作
count=5000;
while(((readRTL(ISR)&(1<<ISR_RDC))==0)&&count)
count--;
writeRTL(ISR,(1<<ISR_RDC)); //清除DMA完成的中断标志
writeRTL(RBCR1,0x00);
writeRTL(RBCR0,0x00);
writeRTL(CR,0x22); //完成DMA
//启动包发送
writeRTL(TBCR1,(uchar)(sendLength>>8)); //发送计数高字节
writeRTL(TBCR0,(uchar)(sendLength&0xff)); //发送计数低字节
writeRTL(CR,0x3e);
}
/**************************************************************************
**
** 函数: void Receive_Packet(uchar *,uint)
** 描述: 该函数完成以太网包的接收,
入口参数分别为指向接收缓冲区的指针,返回接收到的数据的长度
**
**************************************************************************/
uint Receive_Packet(uchar *MCU_Receivebuffer)
{
volatile uchar bnry,curr=0;
uchar pageheader[4]; //远程DMA接收头4B的接收状态
uint i=0,rxlen=0;
uchar nextPage;
curr= readRTL(ISR);
if(curr & (1<<ISR_OVW)) //判断接收缓冲环是否溢出
Over_Run(); //执行接收缓冲环溢出处理函数
writeRTL(CR,0x62); //选择Page 1
curr = readRTL(CURR); //读当前页寄存器
writeRTL(CR,0x22); //选择Page 0
bnry = readRTL(BNRY); //读边界寄存器
if((bnry>=RXSTOP_INIT)||(bnry<RXSTART_INIT)) //边缘指针无效,复位缓存区并退出
{
writeRTL(BNRY,RXSTART_INIT);
Page_Select(1);
writeRTL(CURR,RXSTART_INIT);
Page_Select(0);
return 0;
}
if((curr>=RXSTOP_INIT)||(curr<RXSTART_INIT)) //边缘指针无效,复位缓存区并退出
{
Page_Select(1);
writeRTL(CURR,RXSTART_INIT);
Page_Select(0);
return 0;
}
if(bnry==curr) //没有数据包,返回
return 0;
writeRTL(ISR,(1<<ISR_PRX)); //有数据,清除接收的中断标志
//初始化DMA,远程DMA接收头4B的接收状态
writeRTL(RBCR1,0x00);
writeRTL(RBCR0,0x04); //设置远程DMA字节计数器
writeRTL(RSAR1,bnry);
writeRTL(RSAR0,0x00); //设置远程DMA起始地址寄存器
writeRTL(CR,0x0a); //远程读
for(i=0;i<4;i++)
pageheader[i] = readRTL(RDMARORT);
writeRTL(CR,0x22);//结束DMA操作
Delay(1);
for(i=20;i>0;i--)
if(readRTL(ISR)&(1<<ISR_RDC)) //远程DMA操作完成则跳出循环
break;
writeRTL(ISR,(1<<ISR_RDC)); //清除远程DMA操作完成中断标志
//接收状态错误或接收的包长度>1500b,或下一页指针无效
if(((pageheader[0]&0x01)==0)||(pageheader[3]>0x06)||\
(pageheader[1]>=RXSTOP_INIT)||(pageheader[1]<RXSTART_INIT))
{
Page_Select(1);
bnry=readRTL(CURR);
Page_Select(0);
writeRTL(BNRY,bnry);
writeRTL(ISR,0xff);
return 0;
}
//MCU接收数据包
rxlen=(pageheader[packetLenH]<<8)+pageheader[packetLenL];
nextPage=pageheader[nextblock];
rxlen -=4;
if(rxlen>Max_Size)
{
Page_Select(1);
bnry=readRTL(CURR);
Page_Select(0);
writeRTL(BNRY,bnry);
writeRTL(ISR,0xff);
return 0;
}
writeRTL(RBCR1,(uchar)(rxlen>>8));
writeRTL(RBCR0,(uchar)(rxlen&0xff));
writeRTL(RSAR1,bnry);
writeRTL(RSAR0,4);
writeRTL(CR,0x0a); //远程读
for(i=0;i<rxlen;i++)
MCU_Receivebuffer[i] = readRTL(RDMARORT);
//结束DMA操作
writeRTL(RBCR1,0x00);
writeRTL(RBCR0,0x00);
writeRTL(CR,0x22);
for(i=20;i>0;i--)
if(readRTL(ISR)&(1<<ISR_RDC))
break;
writeRTL(ISR,(1<<ISR_RDC));
writeRTL(BNRY,nextPage);
return rxlen;
}
/******************* End Of File **********************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -