专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

AVR单片机驱动24c02的C51程序

作者:佚名   来源:本站原创   点击数:  更新时间:2012年02月10日   【字体:
*******************************************************************/
 //24c02-- SCL接PD4 , SDA接PD5 。单片机PA口接8路指示灯,开始时 72个花样灯
 //表示将程序写入24c02,过10秒后, 再从24c02中读出,显示在指示灯上
#include <iom16v.h>
#define _BV(k) (1<<k)
#define uchar unsigned char
#define uint unsigned int
#define  SCL   PD4                   //I2总线时钟线
#define  SDA   PD5                   //I2总线数据线 
#define SCL_L  PORTD &=~_BV(SCL) 
#define SCL_H  PORTD |= _BV(SCL)     
#define SDA_L  PORTD &=~_BV(SDA)     
#define SDA_H  PORTD |= _BV(SDA)     
#define SDA_IN  DDRD&=~_BV(SDA)     //设数据线位输入
#define SDA_OUT DDRD|= _BV(SDA) //设数据线位输出
#define SDA_RD    (PIND&_BV(SDA))    //读电平
#define  FREQ  1                     //芯片工作频率
#define  Slave  0xa0
uchar  temp=0xff;
uchar  display[72]={ 0};
uchar const IN_data[72]={
0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
    0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,
    0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,
    0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,
    0xFC,0xF9,0xF3,0xE7,0xCF,0x9F,0x3F,
    0x9F,0xCF,0xE7,0xF3,0xF9,0xFC,0xFF,
    0xE7,0xDB,0xBD,0x7E,0xBD,0xDB,0xE7,0xFF,
    0xE7,0xC3,0x81,0x00,0x81,0xC3,0xE7,0xFF,
    0xAA,0x55,0x18,0xFF,0xF0,0x0F,
    0x00,0xFF,0x00,0xFF};
/********************************************************
*                                                       *
* N*ms延时函数                                          *
*                                                       *
********************************************************/    
void delayms(uint n)        
   { 
      uint i=0,j ; 
      for (i=0 ;i<n ;i++) 
      for(j=0;j<250*FREQ;j++) ;
   }
 
/********************************************************
*                                                       *
* y*us延时函数                                          *
*                                                       *
********************************************************/   
void  delay(uint y)
  { 
  int j;
     for(j=0;j<250*FREQ;j++) ;
  }
/**********************************************************

 起始信号

 在 SCL 高电平期间 SDA 发生负跳变
 
**********************************************************/
void I2C_start(void)
{   
    SDA_H; 
    SCL_H; 
delay(5);
    SDA_L;
    delay(5);
    SCL_L; 
}
/**********************************************************

  停止信号
  
  在 SCL 高电平期间 SDA 发生正跳变
  
**********************************************************/
void I2C_stop(void)
{       
    SDA_L; 
    SCL_H; 
    delay(5);
    SDA_H; 
    delay(5);
SCL_L; 
delay(5);
}

/**********************************************************

把一个字节数据输入器件,并以收到应答信号为止

发送一个字节子程序

**********************************************************/
void I2C_Send(uchar W_data)
{   
    uchar i;
for(i=0;i<8;i++)
    {   
      if((W_data&0x80)) 
      SDA_H;                 
      else 
      SDA_L; 
 SCL_H; 
 delay(5);
 SCL_L; 
 delay(5);
      W_data <<=1;
    }
}

/**********************************************************

**********************************************************/
void  Wait_Ack(void) 
{           
   SDA_IN;                   //置SDA为输入
   SDA_H;
   delay(5);
   do
   {
      SCL_L;
      SDA_H;
      delay(50);
 SCL_H;
 delay(50);       
   } 
   while(SDA_RD);        
   SDA_L;
   SCL_L;
   SDA_OUT;                //置SDA为输出           
}  
/**********************************************************

读一个字节子程序

**********************************************************/
uchar I2C_REV(void)
{   
   uchar i;
   
   SDA_H;                 //开上拉
   SDA_IN;                //置SDA为输入
   delay(5);
for(i=0;i<8;i++)
   { 
      SCL_H;
 delay(5);
   temp<<=1;
   if(SDA_RD)
 temp=(temp | 0x01);
 else
 temp=(temp & 0xfe);
 SCL_L; 
   }
   SDA_OUT;                //置SDA为输出  
   return(temp);
}

/**********************************************************

  发送应答位子函数

  在 SDA 低电平期间 SCL 发生一个正脉冲

**********************************************************/
void  I2C_Ack(void)
{
   SCL_L; delay(4);
   SDA_L; delay(4);
   SCL_H; delay(4);
   SCL_L; delay(4);
   SDA_H; delay(4);
}

/**********************************************************

 发送非应答位子函数

 在 SDA 高电平期间 SCL 发生一个正脉冲

**********************************************************/
void  I2C_NAck(void)
{
   SDA_H; 
   delay(4);
   SCL_H; delay(4);
   SCL_L; delay(4);
   SDA_L;
}

/**********************************************************

  从MCU移出数据到AT24C02
  
  在指定地址addr处写入一个字节子程序

**********************************************************/
void  Write_byte(uchar Addr,uchar in_Data)
{
   I2C_start();
   I2C_Send(Slave);
   Wait_Ack();
   I2C_Send(Addr);
   Wait_Ack(); 
   I2C_Send(in_Data);
   Wait_Ack();
   I2C_stop();
   delay(10);
}

/**********************************************************

  在指定地址addr处读出一个字节子程序从AT24C04读数据到MCU
  
**********************************************************/
void  Read_byte(uchar Addr)
{     
   I2C_start();
   I2C_Send(Slave);
   Wait_Ack();
   I2C_Send(Addr);
   Wait_Ack(); 
   I2C_start();
   I2C_Send(Slave+1);
   Wait_Ack();
   
   I2C_REV();  
   I2C_NAck();  
   I2C_stop();
   delay(10);
}

/**********************************************************

  主函数

**********************************************************/
int  main(void)
{
    uchar m;
    DDRA=0xff;
PORTA=0xff;
DDRC=0xff;
PORTC=0xff;
DDRD=0xff;
PORTD=0xff;
    for(m=0;m<72;m++)   
{                            //写数据
    Write_byte(m,IN_data[m]);
PORTA= IN_data[m];
}

for(m=0;m<72;m++)            //读数据
{ 
     Read_byte(m); 
 display[m]=temp;
}
while(1)
{
 for(m=0;m<72;m++)         //显示数据
 {   
PORTA= display[m];
delayms(60);
 }
} 
}
关闭窗口

相关文章