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

📄 main._c

📁 网卡控制器ENC28J60的AVR单片机ATmega16程序源代码(c),实现232toUDP功能,有非常详细的注释.
💻 _C
📖 第 1 页 / 共 2 页
字号:


//##############################28J60初始化程序###########################//
void ENC28J60_Initialize(void)
{uchar state=0;
 Reset_28J60();//软复位
 delay(2);//28J60复位要一定的时间
 while((state&0x01)==0)state=Read_Control_Register(ETH,0x1D);
 //读状态寄存器ESTAT,确认CLKRDY时钟就绪位置1,确保已稳定,才能进行对MAC和PHY修改
 
 Write_Control_Register(0x08,0x00);//ERXSTL
 Write_Control_Register(0x09,0x08);//ERXSTH,ERXST指针指定接收数据包放在RAM中的开始位置
 Write_Control_Register(0x0C,0x00);//ERXRDPTL
 Write_Control_Register(0x0D,0x08);//ERXRDPTH,与ERXST值要保持相同
 Write_Control_Register(0x00,0x00);//ERDPTL
 Write_Control_Register(0x01,0x08);//ERDPTH,读数据包指针起始位置
  
 Write_Control_Register(0x0A,0xff);//ERXNDL
 Write_Control_Register(0x0B,0x1f);//ERXNDH,ERXND指针指定接收数据包放在RAM中的结束位置
 //指定接收缓冲区,起始处接收缓冲区要预留至少7个字节,将接收到的数据包放入0x0800-0x1fff
 
 Write_Control_Register(0x04,0x00);//ETXSTL
 Write_Control_Register(0x05,0x00);//ETXSTH  
  
 enc28j60SetBank(0x01);//通过ECON1先选中当前控制寄存器组是Bank1,因为ERXFCON寄存器在Bank1。
 Write_Control_Register(0x18,0x83);//将ERXFCON设定接收单播,广播的帧,丢掉CRC无效的数据包
  
 enc28j60SetBank(0x02);//通过ECON1先选中当前控制寄存器组是Bank2,因为MAC相关寄存器在Bank2。
 Bit_Field_Clear(0x01,0x80);//将MACON2中的MARST位清零,使MAC退出复位状态。
 Write_Control_Register(0x00,0x0d);
 //对MACON1进行配置,使能接收数据帧,如果是双工模式的话还要将TXPAUS和RXPAUS置1
 Write_Control_Register(0x02,0x33);//对MACON3进行配置,配置MACON3中的PADCFG、TXCRCEN、FRMLNEN.
//大多数应用应使能自动填充(达到至少60字节),并始终追加一个有效的CRC.为了方便起见,许多应用可能还希望将FRMLNEN位置1
//使能帧长度状态报告.如果应用连接到全双工远程节点,则应将FULDPX置1,否则应保持该位清零。
 Write_Control_Register(0x06,0x12);//配置非背对背包间间隔寄存器的低字节MAIPGL.大多数应用使用12h编程该寄存器。
 //Write_Control_Register(0x07,0x0c);//如果使用半双工模式,应编程非背对背包间间隔寄存器的高字节MAIPGH.
 //大多数应用使用0Ch编程该寄存器.
 Write_Control_Register(0x04,0x15);//配置背对背包间间隔寄存器MABBIPG.
 //当使用全双工模式时,大多数应用使用15h编程该寄存器,而使用半双工模式时则使用12h进行编程.
 Write_Control_Register(0x0a,0xf0);//MAMXFLL
 Write_Control_Register(0x0b,0x00);//MAMXFLH
 //用允许接收或发送的最大帧长度编程MAMXFL寄存器.网络节点一般被设计为处理不大于1518字节的数据包.这里最大240
   
 //如果使用半双工模式,还需编程重发和冲突窗口寄存器MACLCON1 和MACLCON2。
 //大多数应用不需要更改默认的复位值。在网络线缆特别长的情况下,需要增加MACLCON2的默认值
 
 enc28j60SetBank(0x03);//通过ECON1先选中当前控制寄存器组是Bank3,因为MAADR相关寄存器在Bank3.
 
 Write_Control_Register(0x01,MACHead[6]);//MAADR0,将本地MAC地址写入MAADR0:MAADR5寄存器.
 Write_Control_Register(0x00,MACHead[7]);//MAADR1
 Write_Control_Register(0x03,MACHead[8]);//MAADR2
 Write_Control_Register(0x02,MACHead[9]);//MAADR3
 Write_Control_Register(0x05,MACHead[10]);//MAADR4
 Write_Control_Register(0x04,MACHead[11]);//MAADR5
//接下去对PHY进行初始化//
Write_PHY_Register(0x00,0x01,0x00);//将PHCON1.PDPXMD置1,工作在全双工模式.
Write_PHY_Register(0x10,0x01,0x00);//将PHCON2.HDLDIS置1,禁止发送数据的自动环回。 
Write_PHY_Register(0x14,0x04,0x72);//PHLCON寄存器配置LEDA,LEDB;LEDA显示链接状态,LEDB显示发送和接收活动

Bit_Field_Set(0x1e,0x80);//ECON2寄存器中的AUTOINC位置1,写缓冲器命令时自动指向下一个地址
Bit_Field_Set(0x1B,0xc0);//将EIE.INTIE位和EIE.PKTIE置1允许接收产生中断。
Write_Control_Register(0x1f,0x04);//接收使能
}
//##############################中断服务程序##################################//
void INT1_17(void)//接外部按键
{uchar i=0;
GICR &=0xbf;
//Transmit_Packets();//起动发送数据包
GICR |=0x40;
 }
void INT0_16(void)
{uchar temp=0x00;//
 GICR &=0x7f;
 temp=Read_Control_Register(ETH,0x1f);//读取ECON1的值,先保护起来
 
 do Receive_Packets();
 while(EPKTCNT!=0);
 Write_Control_Register(0x1f,0x00);//关接收使能
 enc28j60SetBank(0x00);//通过ECON1先选中当前控制寄存器组是Bank0
 Write_Control_Register(0x08,0x00);//ERXSTL
 Write_Control_Register(0x09,0x08);//ERXSTH,ERXST指针指定接收数据包放在RAM中的开始位置
 Write_Control_Register(0x0C,0x00);//ERXRDPTL
 Write_Control_Register(0x0D,0x08);//ERXRDPTH,与ERXST值要保持相同
 Write_Control_Register(0x00,0x00);//ERDPTL
 Write_Control_Register(0x01,0x08);//ERDPTH,读数据包指针起始位置
 Write_Control_Register(0x0A,0xff);//ERXNDL
 Write_Control_Register(0x0B,0x1f);//
 
 Write_Control_Register(0x1f,0x04);//接收使能
 
 Write_Control_Register(0x1f,temp);//恢复ECON1的值
 GICR |=0x80;
}

//####################################
void Usart_receive(void)//定义接收中断服务程序
{Rec232[usart_number]=UDR;
 usart_number++;
 TIMSK=0x01;//打开T1,T0中断屏蔽
 TCCR0=0x05;//设T0分频数为1024
 TCNT0=0xf0;//设T0时间常数,波特率数据流结束所对应的间隔
 }
//##############定时器中断0,串行数据流控制
void Timer0(void)
{uchar i=0;
 TIMSK=0x00;//关T0中断屏蔽
 TCNT0=0x00;//
 TCCR0=0x00;//T0停止计数
 usart_number=usart_number-1;
 DateLen=usart_number-42;//
 if(Rec232[0]==0x04 && Rec232[1]==0x05 && Rec232[2]==0x06){
 					putchar(0x4F);putchar(0x4B);putchar(0x21);
					}//连接成功回答OK!
 if(Rec232[0]==0x4c && Rec232[1]==0x48 && Rec232[2]==0x46){//是不是LHF,是则发送
 					for(i=3;i<15;i++)MACHead[i-3]=Rec232[i];
 					for(i=15;i<35;i++)IpHead[i-15]=Rec232[i];
 					for(i=35;i<usart_number+1;i++)UDPpacket[i-23]=Rec232[i];
  					Transmit_Packets();}//发送数据
 if(Rec232[0]==0x4d && Rec232[1]==0x41 && Rec232[2]==0x43){//配置28J60
 					for(i=3;i<15;i++)MACHead[i-3]=Rec232[i];
 					for(i=15;i<35;i++)IpHead[i-15]=Rec232[i];
					ENC28J60_Initialize();
					delay(50);
					putchar(0x4C);
 					putchar(0x48);
 					putchar(0x46);//发送"LHF"通知上位机,
					for(i=0;i<12;i++)putchar(i);//配置成功则返回0,1,2,3,...11
					}
					usart_number=0;
 }
//##############################USART初始化程序###########################//
void usart_init(void)
{
 UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//允许发送和接收
 UBRRL=(fosc/16/(bps+1))%256;
 UBRRH=(fosc/16/(bps+1))/256;
 UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8位数据+1位STOP位
} 
//##############################系统初始化程序################################//
void AVR_Initialize(void)         //初始化
{
 DDRA=0xff;	 //
 PORTA=0xff;
 DDRB=0xff;	 //
 PORTB=0xff;
 DDRC=0xc3;	 //
 PORTC=0x00; //
 DDRD=0xf0;	 //
 PORTD=0x7f;

 SPCR=0b01010000;
//关中断(SPIE=0),使能SPI(SPE=1),MSB首先发送(DORD=0),选择微机为主机模式(MSTR=1)
//空闲时SCK为低电平(CPOL=0),在SCK的上升沿采样(CPHA=0)ENC28J60要求SPI工作在模式0
//SPR1=0和SPR0=0,SCK=fosc/4
 SPSR |=0x01;//SPI的速度加倍
	  
 MCUCR=0x0a;//设置外部中断的中断触发方式为下降沿触发
 GICR=0xc0;	//通用中断控制寄存器设置,打开中断INT0和INT1
 SREG=0x80; //开全局中断
}
//##################################主程序####################################//
void main()
{delay(5);
 AVR_Initialize();               //I/O口及中断初始化
 usart_init();
 //ENC28J60_Initialize();
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -