📄 enc28j60.c
字号:
#include "reg51.H"
#include "REGISTER.h"
#include "uip.h"
#include "uipopt.h"
//SPTCL寄存器
#define NUM 8
#define SPTCL_SSIG 0x80
#define SPTCL_SPEN 0x40
#define SPTCL_MSTR 0x10
#define SPTCL_CPOL 0x08
#define SPTCL_CPHA 0x04
#define SPTCL_SPR1 0x02
#define SPTCL_SPR0 0x01
//SPSTAT寄存器
#define SPSTAT_SPIF 0x80
#define SPSTAT_WCOL 0x40
sbit P10 = P1^0;
sbit P11 = P1^1; //add1
sbit P12 = P1^2; //add1
sbit CS = P1^3;
sbit SS = P1^4;
sfr BRT = 0x9c; //add7
#define RELOAD 0xF1
extern unsigned char xdata STAT_AB ; //ADD8
//extern unsigned char xdata UARTtimer;
extern unsigned char tick_count; //add7
extern unsigned char ab_count;
static unsigned int NextPacketPtr = 0;
static unsigned char Enc28j60Bank;
typedef unsigned int INT16U;
typedef unsigned char INT8U;
void delay_ms(unsigned char num) //延时num个毫秒
{unsigned char i,j;
if(num>1)
{for (i=0;i<200;i++)
for(j=0;j<200;j++);
num--;}
}
void init_SPI(void)
{ P1M0 =0xb8;
P1M1 =0x40;
SS=1;
SPSTAT=0xC0;
SPCTL = SPTCL_SPEN | SPTCL_MSTR; //选择为主机模式,SPI使能,SPI 口只能工作在00模式下
}
void System_Reset(void)
{ CS = 0;
// write data
SPDAT = ENC28J60_SOFT_RESET;
while(!(SPSTAT & SPSTAT_SPIF));
//SPSTAT&=~SPSTAT_SPIF;
SPSTAT=0xC0;
CS = 1;
}
/*==========================================================
// function: write data to addr
==========================================================*/
void encWriteOp(unsigned char op,unsigned char addr,unsigned char outdata)
{
CS = 0;
// send write command
SPDAT = op | (addr & ADDR_MASK);
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT=0xC0; //写1的时候进行清零操作
// write data
SPDAT = outdata;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT=0xC0;
CS = 1;
}
/*==========================================================
// function: read data from addr
==========================================================*/
unsigned char encReadOp(unsigned char op,unsigned char addr)
{
unsigned char indata;
CS = 0;
// send read command
SPDAT = op | (addr & ADDR_MASK);
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT=0xC0;
// read data
SPDAT = 0x00;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT=0xC0;
// do dummy read if needed
if(addr & 0x80)
{
SPDAT = 0x00;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT=0xC0;
}
indata = SPDAT;
CS = 1;
return (indata);
}
/*==========================================================
// function: set enc28j60 register bank
==========================================================*/
void encSetBank(unsigned char addr)
{
// set the bank (if needed)
if((addr & BANK_MASK) != Enc28j60Bank)
{
// clear the set
encWriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
// set the bank
encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (addr & BANK_MASK)>>5);
Enc28j60Bank = (addr & BANK_MASK);
}
}
/*==========================================================
// function: read regsiter
==========================================================*/
unsigned char encRead(unsigned char addr)
{
// set the bank
encSetBank(addr);
// do the read
return encReadOp(ENC28J60_READ_CTRL_REG, addr);
}
/*==========================================================
// function: read data buffer form enc28j60
==========================================================*/
void encReadBuffer(unsigned int temp_len,unsigned char *indata)
{
CS = 0;
// send read command
SPDAT = ENC28J60_READ_BUF_MEM;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT = 0xC0;
while(temp_len--)
{
// read data
SPDAT = 0x00;
while(!(SPSTAT & SPSTAT_SPIF));
*indata++ = SPDAT;
SPSTAT = 0xC0;
}
CS = 1;
}
/*==========================================================
// function: write regsiter
==========================================================*/
void encWrite(unsigned char addr,unsigned char outdata)
{
// set the bank
encSetBank(addr);
// do the write
encWriteOp(ENC28J60_WRITE_CTRL_REG, addr, outdata);
}
/*==========================================================
// function: set MAC address
==========================================================*/
void nicSetMacAddress(void)
{
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
encWrite(MAADR0, UIP_ETHADDR5);
encWrite(MAADR1, UIP_ETHADDR4);
encWrite(MAADR2, UIP_ETHADDR3);
encWrite(MAADR3, UIP_ETHADDR2);
encWrite(MAADR4, UIP_ETHADDR1);
encWrite(MAADR5, UIP_ETHADDR0);
}
/*==========================================================
// function: write PHY regsiter
==========================================================*/
void encPhyWrite(unsigned char addr, unsigned int outdata)
{
// set the PHY register address
encWrite(MIREGADR, addr);
// write the PHY data
encWrite(MIWRL, outdata);
encWrite(MIWRH, outdata>>8);
// wait until the PHY write completes
while(encRead(MISTAT) & MISTAT_BUSY);
}
/*==========================================================
// function: chip init
==========================================================*/
void encInit(void)
{
// initialize I/O
init_SPI();
// perform system reset
System_Reset();
// check CLKRDY bit to see if reset is complete
delay_ms(NUM);
while(!(encRead(ESTAT) & ESTAT_CLKRDY));
// do bank 0 stuff
// initialize receive buffer
// 16-bit transfers, must write low byte first
// set receive buffer start address
encWrite(ERXSTL, RXSTART_INIT&0xFF);
encWrite(ERXSTH, RXSTART_INIT>>8);
// set receive pointer address
encWrite(ERXRDPTL, RXSTART_INIT&0xFF);
encWrite(ERXRDPTH, RXSTART_INIT>>8);
// set receive buffer end
// ERXND defaults to 0x1FFF (end of ram)
encWrite(ERXNDL, RXSTOP_INIT&0xFF);
encWrite(ERXNDH, RXSTOP_INIT>>8);
//set send buffer end
encWrite(ETXNDL,RXSTART_INIT&0xFF);
encWrite(ETXNDH,RXSTART_INIT>>8);
if(encRead(ERXNDL)==0xff) //add1
{ P11=0;
}
//bank 1 滤波器的设置
encWrite(ERXFCON,0x60); //1:and,0:or the second bit
// do bank 2 stuff
// enable MAC receive
encWrite(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
// bring MAC out of reset
encWrite(MACON2, 0x00);
if((encRead(MACON1)==(MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS))&&(encRead(MACON2)==0x00))
{ P12=0; //add1
}
// enable automatic padding and CRC operations //改,只能对ETH类进行位操作
encWrite(MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
// set inter-frame gap (non-back-to-back)
encWrite(MAIPGL, 0x12);
encWrite(MAIPGH, 0x0C);
// set inter-frame gap (back-to-back)
encWrite(MABBIPG, 0x12);
// Set the maximum packet size which the controller will accept
encWrite(MAMXFLL, MAX_FRAMELEN&0xFF);
encWrite(MAMXFLH, MAX_FRAMELEN>>8);
// do bank 3 stuff
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
nicSetMacAddress();
// no loopback of transmitted frames
encPhyWrite(PHCON2, PHCON2_HDLDIS);
encPhyWrite(PHCON1, PHCON1_PDPXMD);
encPhyWrite(PHLCON,0x07b0);
// switch to bank 0
encSetBank(ECON1);
encWrite(EIE,0x00);
encWrite(EIR,0x00);
// enable packet reception
encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
// Stop timer/ counter 0.
Timer0off();
// Set timer/ counter 0 as mode 1 16 bit timer.
// TMOD &= 0xF0;
TMOD |= 0x11;
// Preload for 0.5s periodic interrupt.
TH0 = ETH_T0_RELOAD >> 8;
TL0 = ETH_T0_RELOAD;
TH1 = ETH_T1_RELOAD >> 8;
TL1 = ETH_T1_RELOAD;
AUXR=0x00; //设置为12个时钟周期
//UART initialize add7
AUXR=AUXR|0x05;
BRT=RELOAD;
SCON=0x50;
PCON=0x00;
AUXR=AUXR|0x10; //启动计数
ES=1;
// Enable timer/ counter 0 overflow interrupt.
ET0 = 1;
ET1 = 1;
EA = 1;
}
/***********************发送接受函数********************/
void EthdevSPI_Sendpack(void)
{
INT8U len,leno;
INT8U *ptr;
EA=0;
ptr = uip_buf; //将指针指向发送数据的首地址
//是否要判断接受忙,发送未完成,DMA操作?
//写发送缓冲区首地址
encWrite(ETXSTL, TXSTART_INIT&0xFF);
encWrite(ETXSTH, TXSTART_INIT>>8);
// Set the write pointer to start of transmit buffer area
encWrite(EWRPTL, TXSTART_INIT);
encWrite(EWRPTH, TXSTART_INIT>>8);
len = UIP_TCPIP_HLEN + UIP_LLH_LEN; //UIP_LLH_LEN=14,UIP_TCPIP_HLEN=40
leno=uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN;
CS = 0;
SPDAT = ENC28J60_WRITE_BUF_MEM;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT = 0xc0;
SPDAT = 0x0e; //包发送方式控制量,该控制量不存放在uip_buf中
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT = 0xC0; // 发送一个包控制字0e,确定发送方式为MACON3中设置
/****** 通过SPI口写进ENC28J60的缓冲区 UIP_LLH_LEN=14,UIP_TCPIP_HLEN=40 *****/
while(len--)
{
// write data
SPDAT = *ptr++;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT = 0xC0;
}
ptr = (unsigned char *)uip_appdata; //指向应用数据区
while(leno--)
{ // write data
SPDAT = *ptr++;
while(!(SPSTAT & SPSTAT_SPIF));
SPSTAT = 0xC0;
}
CS = 1;
// Set the TXND pointer to correspond to the packet size given
encWrite(ETXNDL, (TXSTART_INIT+uip_len));
encWrite(ETXNDH, (TXSTART_INIT+uip_len)>>8);
encWriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); //ECON1.TXRTS=1,开发送请求位
EA=1;
}
/************************读缓冲器中数据****************************/
unsigned int EthdevSPI_read(void)
{ INT8U i=0,*ptr;
INT16U tlen,rxstat;
// check if a packet has been received and buffered (encReadOp(ENC28J60_READ_CTRL_REG, EIR) & EIR_PKTIF)!=0)|| ||(encRead(EPKTCNT)==0)
if(encRead(EPKTCNT)>0)
{ EA=0;
// encWriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF); //清0
// Set the read pointer to the start of the received packet
encWrite(ERDPTL, (NextPacketPtr));
encWrite(ERDPTH, (NextPacketPtr)>>8);
// read the next packet pointer
NextPacketPtr = encReadOp(ENC28J60_READ_BUF_MEM, 0);
NextPacketPtr |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
// read the packet length 接受状态字的内容
tlen = encReadOp(ENC28J60_READ_BUF_MEM, 0); //有效数据+填充+CRC
tlen |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
tlen=tlen-4;
// read the receive status
rxstat = encReadOp(ENC28J60_READ_BUF_MEM, 0);
rxstat |= encReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
ptr = uip_buf;
if(tlen>UIP_BUFSIZE) //此包太大,将丢弃
{
P1=P1&0xfe; //add1
tlen = 0; //return 0; 错误
}
else{
encReadBuffer(tlen,ptr);
}
// Move the RX read pointer to the start of the next received packet
// This frees the memory we just read out 前移接收缓冲器读指针ERXRDPT
encWrite(ERXRDPTL, (NextPacketPtr));
encWrite(ERXRDPTH, (NextPacketPtr)>>8);
// decrement the packet counter indicate we are done with this packet
//encWrite(EPKTCNT,(encread(EPKTCNT)-1));
encWriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
EA=1;
}
else{
tlen=0;
}
return tlen;
}
static void etherdev_timer0_isr(void) interrupt 1 using 1
{ struct uip_conn xdata *uip_connr_temp= uip_conn;
unsigned char xdata k;
Timer0off();
// Reload timer/ counter 0 for 0.1s periodic interrupt.
TH0 = ETH_T0_RELOAD >> 8;
TL0 = ETH_T0_RELOAD;
k++;
if(k>=40)
{ k=0;
uip_connr_temp->timer--;
if(uip_connr_temp->timer==0) { Timer0off();
return;
}
}
Timer0on();
return;
}
static void etherdev_timer1_isr(void) interrupt 3 using 3
{ struct datatrans_state *ts;
unsigned char xdata k;
ts = (struct datatrans_state xdata *)(uip_conn->appstate);
Timer1off();
TH1 = ETH_T1_RELOAD >> 8; //和k形成1s的延时
TL1 = ETH_T1_RELOAD;
k++;
if(k>=50)
{ k=0;
// UARTtimer++;
tick_count++; //更新ARP表的
if(STAT_AB==1){
ts->count++; //连接时间计数
if(ts->count==ab_count) //不同s时延
return;
}
}
Timer1on();
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -