📄 enc28j60._c
字号:
#include "head.h"
uchar PHY_H=0;
uchar PHY_L=0;
//################################延时程序################################//
void delay(uchar k)//
{uint i=0;
while(k--){for(i=0;i<8000;i++);}
}
//##########################串行通信##########################//
void putchar(uchar c)
{while(!(UCSRA&(1<<UDRE)));//判断上次发送有没有完成
UDR=c;}
//##############################选通SPI器件###############################//
void Set_CS(uchar level) //
{if(level) PORTB |=0x10; //
else PORTB &=0xef; //
}
//################################28J60复位#####################################
void Reset_28J60(void)
{uchar clear;
Set_CS(0); //使能SPI器件
SPDR=0xFF; //复位指令
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
Set_CS(1); //关SPI器件
}
//#########################读28J60控制寄存器#################################
uchar Read_Control_Register(uchar EM,uchar address)
//EM=0表示读的是ETH,EM=1表示读的是MAC和MII控制寄存器
{uchar clear;
Set_CS(0); //使能SPI器件
SPDR=address; //送地址,28J60中控制寄存器读操作前3位为0后5位为地址
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=0xc0;//随便送个数以起动时钟以接收从28J60控制寄存器里传来的数据,
//这里因为28J60中没有用到0xc0指令固先用0xc0作为随便一个数
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
if(EM==1){
SPDR=0xc0;//随便送个数以起动时钟以接收从28J60控制寄存器里传来的数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
}//因为读MAC和MII寄存器时读出来的第一个字节是无效的,因此要读两次
Set_CS(1); //关SPI器件
return clear;
}
//###########################写28J60控制寄存器##################################
void Write_Control_Register(uchar address,uchar date)
{uchar clear;
address=address+0x40;//28J60中控制寄存器写操作前3位为010后5位为地址
Set_CS(0); //使能SPI器件
SPDR=address; //送地址,28J60中控制寄存器写操作前3位为010后5位为地址
while(!(SPSR&0x80)); //等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=date;
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
Set_CS(1); //关SPI器件
}
//#########################读缓冲存储器#################################
void Read_Buffer_Memory_order(void)//送读缓冲存储器命令,连续读时用到
{uchar clear;
Set_CS(0); //使能SPI器件
SPDR=0x3A; //送命令,28J60中读缓冲存储器操作前3位为001后5位为常量11010
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
}
uchar Read_Buffer_Memory_date(void)//收到读到的数据,连续读时用到此函数
{uchar clear;
SPDR=0xc0;//随便送个数以起动时钟以接收从28J60控制寄存器里传来的数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
return clear;//返回读到的数据
}
void Read_Buffer_Memory_END(void)//读结束
{Set_CS(1); //关SPI器件
}
//#########################读缓冲存储器#################################
uchar Read_Buffer_Memory(void)//只读一次,地址是由ERDPT指向的存储器中的数据将从SO脚移出
{uchar clear;
Set_CS(0); //使能SPI器件
SPDR=0x3A; //送命令,28J60中读缓冲存储器操作前3位为001后5位为常量11010
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=0xc0;//随便送个数以起动时钟以接收从28J60控制寄存器里传来的数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
Set_CS(1); //关SPI器件
return clear;
}
//#########################写缓冲存储器#################################
void Write_Buffer_Memory_date(uchar date)//写入缓冲存储器数据
{uchar clear;
SPDR=date;
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
}
void Write_Buffer_Memory_once(uchar date)//只写一次,地址是由EWRPT指向的存储器
{uchar clear;
Set_CS(0); //使能SPI器件
SPDR=0x7A; //送命令,28J60中写缓冲存储器操作前3位为011后5位为常量11010
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=date;
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
Set_CS(1); //关SPI器件
}
//#################################位域置1命令#################################
void Bit_Field_Set(uchar Address,uchar date)//指定地址的ETH控制寄存器的内容与date进行位逻辑或操作
{uchar clear;
Address=Address+0x80;
Set_CS(0); //使能SPI器件
SPDR=Address; //送命令,28J60中位域置1命令前3位为100后5位为地址
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=date; //送数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
Set_CS(1); //关SPI器件
}
//#################################位域置清0命令#################################
void Bit_Field_Clear(uchar Address,uchar date)//指定地址的ETH控制寄存器的内容与date进行位逻辑非与操作
//将所提供数据取反,并接着与指定寄存器的内容进行D0位的逻辑与运算
{uchar clear;
Address=Address+0xa0;
Set_CS(0); //使能SPI器件
SPDR=Address; //送命令,28J60中位域置1命令前3位为101后5位为地址
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=date; //送数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR; //接收到控制寄存器里的数据
Set_CS(1); //关SPI器件
}
//#################################寄存器组选择#################################
void enc28j60SetBank(uchar group)//0,1,2,3
{
Bit_Field_Clear(0x1f,0x03);//先将BSEL1,BSEL0清0
switch(group){
case 0:break;
case 1:Bit_Field_Set(0x1f,0x01);break;
case 2:Bit_Field_Set(0x1f,0x02);break;
case 3:Bit_Field_Set(0x1f,0x03);break;
}
}
//#################################写PHY寄存器#################################
void Write_PHY_Register(uchar Address,uchar dateH,uchar dateL)
{uchar flag=0x01;
enc28j60SetBank(0x02);//通过ECON1先选中当前控制寄存器组是Bank2,因为接下来的MIREGADR寄存器在Bank2。
Write_Control_Register(0x14,Address);//将PHY地址写入MIREGADR寄存器0x14
Write_Control_Register(0x16,dateL);//将dateL写入MIWRL
Write_Control_Register(0x17,dateH);//将dateH写入MIWRH
enc28j60SetBank(0x03);//通过ECON1先选中当前控制寄存器组是Bank3,因为接下来的MISTAT寄存器在Bank3。
while((flag&0x01)!=0)flag=Read_Control_Register(MII,0x0a);//查询MISTAT.BUSY,等待它清0
}
//#################################读PHY寄存器#################################
void Read_PHY_Register(uchar Address)
{uchar flag=0x01;
enc28j60SetBank(0x02);//通过ECON1先选中当前控制寄存器组是Bank2,因为接下来的MIREGADR寄存器在Bank2。
Write_Control_Register(0x14,Address);//将PHY地址写入MIREGADR寄存器0x14
Write_Control_Register(0x12,0x01);//将MICMD.MIIRD置1
enc28j60SetBank(0x03);//通过ECON1先选中当前控制寄存器组是Bank3,因为接下来的MISTAT寄存器在Bank3。
Write_Control_Register(0x0a,0x01);//将MISTAT.BUSY置1
while((flag&0x01)!=0)flag=Read_Control_Register(MII,0x0a);//查询MISTAT.BUSY,等待它清0
enc28j60SetBank(0x02);//通过ECON1先选中当前控制寄存器组是Bank2,因为接下来的MIREGADR寄存器在Bank2。
Write_Control_Register(0x12,0x00);//将MICMD.MIIRD清0
PHY_H=Read_Control_Register(MII,0x19);//从MIRDH中读取PHY中的高8位数据
PHY_L=Read_Control_Register(MII,0x18);//从MIRDL中读取PHY中的低8位数据
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -