⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enc28j60._c

📁 网卡控制器ENC28J60的AVR单片机ATmega16程序源代码(c),实现232toUDP功能,有非常详细的注释.
💻 _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 + -