访问手机版页面
你的位置:老古开发网 > 其他 > 正文  
I2C读写心得(AT24C02篇)(转)
内容导读:
困扰我几的程序终于搞定了,前几天我对AT24C02一直读不准确,找了N长时间的程序都没有头绪,后来在板哥的指点下,一下子明白了,原因很简单,我在AT24C02_read()最后没有加延时,
主要还是对时序没有控制好呀,用板哥的一句话是我们对器件的了解还不很熟,我现在也感到,一定要先了解了器件的特性,我们才能游刃有余把握住每一个容易疏忽的细节,在这里,板哥确实教会了我好多东西,在我刚学单片机时,他就对我说时序很重要,现在终于是看到了.
好了不罗嗦了,最后得出一点,最好在每个读写结束时加个延时,如果对时间要求不是很重要的话,加的长一点无所谓,如果要求比较高的话,那先加长延时,然后慢慢的减.
#include <reg51.h>
#include <intrins.h>
/*********************************LCD定义部分********************************/
//输入方式设置
#define LCD_AC_AUTO_INCREMENT     0x06         //数据读、写操作后,AC自动增一
#define LCD_AC_AUTO_DECREASE      0x04         //数据读、写操作后,AC自动减一
#define LCD_MOVE_ENABLE           0x05         //数据读、写操作,画面平移
#define LCD_MOVE_DISENABLE        0x04         //数据读、写操作,画面不动
#define LCD_GO_HOME               0x02         //AC=0,光标、画面回HOME位
//设置显示、光标及闪烁开、关
#define LCD_DISPLAY_ON            0x0C         //显示开
#define LCD_DISPLAY_OFF           0x08         //显示关
#define LCD_CURSOR_ON             0x0A         //光标显示
#define LCD_CURSOR_OFF            0x08         //光标不显示
#define LCD_CURSOR_BLINK_ON       0x09         //光标闪烁
#define LCD_CURSOR_BLINK_OFF      0x08         //光标不闪烁
//光标、画面移动,不影响DDRAM
#define LCD_LEFT_MOVE             0x18         //LCD显示左移一位
#define LCD_RIGHT_MOVE            0x1C         //LCD显示右移一位
#define LCD_CURSOR_LEFT_MOVE      0x10         //光标左移一位
#define LCD_CURSOR_RIGHT_MOVE     0x14         //光标右移一位
//工作方式设置
#define LCD_DISPLAY_DOUBLE_LINE   0x38         //两行显示
#define LCD_DISPLAY_SINGLE_LINE   0x30         //单行显示
#define LCD_CLEAR_SCREEN  0X01   //清屏
/***********************LCD1602地址相关******************************/
#define LINE1_HEAD    0x80   // 第一行DDRAM起始地址
#define LINE2_HEAD    0xc0   //  第二行DDRAM起始地址
#define LINE1         0      //第一行
#define LINE2         1      //第二行
#define LINE_LENGTH   16     //每行的最大字符长度
/***********************LCD1602接线引脚定义**************************
**********************可根据实际电路改变*******************************/
#define LCDIO     P2         //定义P2口与LCD1602的数据口相接
  sbit   LCD_RS=P1^4;        
  sbit   LCD_RW=P1^3;        
  sbit   LCD_EN=P1^2;
  sbit  LCD_BUSY=LCDIO^7;
 /**********************另外相关的定义*********************************/
 #define HIGH               1
 #define LOW                0  
 #define TURE               1
 #define  FALSE             0
 #define  uchar unsigned char
 #define  uint  unsigned int
 #define NUM 10
 /*************************以下是函数的申明部分*************************/
 void LCD_init(void);                    //LCD1602初始化
 void LCD_send_command(uchar command);   //
 void LCD_send_data(uchar dat);
 void LCD_write_char(uchar x,uchar y,uchar dat);
 void LCD_write_string(uchar x,uchar y,char *Data);
 void delay_ms(uint n);
 void LCD_check_busy(void);
 /*********************结束***********************************************/
//at24c02 part
#define  WRITE24C02    0xA0
#define     READ24C02    0xA1
//I2C part
#define    Wait1us        _nop_();
#define    Wait2us        {_nop_();_nop_();}
#define    Wait4us        {Wait2us;Wait2us;}
#define    Wait8us        {Wait4us;Wait4us;}
#define    Wait10us    {Wait8us;Wait2us;}
sbit SDA=P2^7;      //AT24C02 serial data    pin 5
sbit SCL=P2^6;     //AT24C02 serial clock    pin 6
/********************************************************************/
void I2C_start(void);//I2C start function
void I2C_stop(void);//I2C stop function
//void I2C_send_ack(void);//I2C send responsion function
void I2C_send_noack(void);
void I2C_write_byte(unsigned char IIC_data);//I2C bus write byte function
unsigned char I2C_read_byte(void);//I2C bus read byte function
/********************************************************************/
void AT24C02_write(unsigned char address,unsigned char *buf,unsigned char n);//write 24c02 information function
void AT24C02_read(unsigned char address,unsigned char *buf,unsigned char n);//read 24c02 information function
/********************************************************************/
void Mcu_init(void);//system initize funcition
void I2C_init(void);
unsigned char count[2];
unsigned char sharebuf[NUM];
/********************************************************************/
void main()
{
 unsigned char temp; 
 Mcu_init();
 while(1)   
 {
     sharebuf[0]=count[1];
  sharebuf[1]=count[0];
     AT24C02_write(0x00,sharebuf,2);
 
     AT24C02_read(0x00,sharebuf,2);
  temp=sharebuf[0];
      LCD_write_string(0x00,LINE1,"AT24C02 TEST");
     LCD_write_char(0x0e,LINE1,(temp/10) 0x30);
     LCD_write_char(0x0f,LINE1,(temp%10) 0x30);
     LCD_write_string(0x00,LINE2,"TIMER0 JISHU");
     LCD_write_char(0x0e,1,(count[1]/10) 0x30);
     LCD_write_char(0x0f,1,(count[1]%10) 0x30);
    
 }
}
/***********************************************************************/
void timer0(void) interrupt 1 using 1
{
 TH0=-(12000/256);
    TL0=-(12000%256);
 count[0]=count[0]+1;
 if(count[0]==100)
    { 
  count[0]=0;
  count[1]=count[1]+1;
  if(count[1]==99)
   count[1]=0;
 }
}         
/***********************************************************************/
void Mcu_init(void)
{
 TMOD=0x01;
 TH0=-(12000/256);
 TL0=-(12000%256);
 EA=HIGH;
 ET0=HIGH;
 TR0=HIGH;
 LCD_init();
}
/***********************************************************************/
/******************************** I2C PART **************************/
void I2C_start(void)
{
  SDA=1;
 SCL=1;
 SDA=0;
 SCL=0;
 
 
}
/***********************************************************************/
void I2C_stop(void)
{
 SCL=0;
 SDA=0;
 SCL=1;
 SDA=1;
 
}
/***********************************************************************/
void I2C_send_ack(void)
{
 SDA=0;
 SCL=1;
 SCL=0;
 SDA=1;
}
/*************************************************************************/
void I2C_send_noack(void)
{
 SDA=1;
 SCL=1;
 SCL=0;
}
/*****************************************************************************/
  bit TestAck()
  {
 bit ErrorBit;
 SDA=1;
 SCL=1;
 ErrorBit=SDA;
 SCL=0;
 return(ErrorBit);
}
/***********************************************************************/
void I2C_write_byte(unsigned char input)
{
     unsigned char temp;
 for(temp=8;temp!=0;temp--)
  {
  SDA=(bit)(input&0x80);
  SCL=1;
  SCL=0;
  input=input<<1;
        }
 }
/***********************************************************************/
unsigned char I2C_read_byte(void)
{
  unsigned char temp,rbyte=0;
 for(temp=8;temp!=0;temp--)
  {
     SCL=1;
     rbyte=rbyte<<1;
      rbyte=rbyte ((unsigned char)(SDA));
      SCL=0;
 }
 return(rbyte);
}
/************************************************************************/
void AT24C02_write(unsigned char address,unsigned char *buf,unsigned char Nbyte)
{
 
    I2C_start();
 I2C_write_byte(WRITE24C02);
  TestAck();
    I2C_write_byte(address);
 TestAck();
 for(;Nbyte!=0;Nbyte--)
 { 
 I2C_write_byte(*buf);
    TestAck();
    buf++;
 
  }
 I2C_stop();             
 delay_ms(10);//这个很重要,调了几天问题就是出在h里的,最好在每个函数之间加延时

/************************************************************************/
void AT24C02_read(unsigned char address,unsigned char *buf,unsigned char Nbyte)
{
 
     I2C_start();
  I2C_write_byte(WRITE24C02);
   TestAck();
  I2C_write_byte(address);
   TestAck();
  
   I2C_start();
  I2C_write_byte(READ24C02);
       TestAck(); 
   while(Nbyte!=1)
    {
        *buf=I2C_read_byte();
             I2C_send_ack();
              buf++;
             
   Nbyte--;
         }
 *buf=I2C_read_byte();
I2C_send_noack();
 I2C_stop();
 
 
 
 
}
/**************LCD1602的初始化***************************/
void LCD_init(void)
{
 LCD_send_command(LCD_DISPLAY_DOUBLE_LINE);
 LCD_send_command(LCD_AC_AUTO_INCREMENT LCD_MOVE_DISENABLE);
 LCD_send_command(LCD_DISPLAY_ON LCD_CURSOR_OFF);
 LCD_send_command(LCD_CLEAR_SCREEN);
}
/***********************检测LCD状态*********************************/
 
void LCD_check_busy(void)  
{
 do
  {
   LCD_EN=0;
   LCD_RS=0;
   LCD_RW=1;
   LCDIO=0xff;
   LCD_EN=1;
   }
   while(LCD_BUSY==1);
 
    LCD_EN=0;
}
/************LCD1602写命令*******************************/
void LCD_send_command(uchar command)
{
 LCD_check_busy();
 LCD_RS=LOW;
 LCD_RW=LOW;
 LCD_EN=HIGH;
 LCDIO=command;
 LCD_EN=LOW;
}
/********************************************************/
/*****************LCD1602写数据**************************/
void LCD_send_data(uchar dat)
{
 LCD_check_busy();
 LCD_RS=HIGH;
 LCD_RW=LOW;
 LCD_EN=HIGH;
 LCDIO=dat;
 LCD_EN=LOW;
}
/***********************LCD1602显示字符*********************************/
void LCD_write_char(uchar x,uchar y,uchar dat)
{
     unsigned char address;
     if (y == LINE1)
         address = LINE1_HEAD + x;
     else
        address = LINE2_HEAD + x;
     LCD_send_command(address);
    LCD_send_data(dat);
}
/******************LCD1602显示字符串*********************/
void LCD_write_string(uchar x,uchar y,uchar *Data)
{
 if(y==LINE1)
 {
  if(x<LINE_LENGTH)
  {
   LCD_send_command(LINE1_HEAD+x);
   for(;x<LINE_LENGTH&&*Data!=''''\0'''';x++)
   { 
    LCD_send_data(*(Data++));
   }
   if(*Data!=''''\0'''')
   {
    x=0;
    y=LINE2;
   }
  }
 }
 if(y==LINE2)
 {
  LCD_send_command(LINE2_HEAD+x);
  for(;x<LINE_LENGTH&&*Data!=''''\0'''';x++)
  {
   LCD_send_data(*(Data++));
  }
 }
}
/****************************************************************/
/********************延时函数***********************************/
 
/***************************************************************/
void delay_ms(uint n)
{
 uint i,j;
 for(i=n;i>0;i--)
    for(j=0;j<1140;j++)
    ;
}
/*********************************************************************/
标签:
来源: 作者: 时间:2006/9/25 16:50:53
相关阅读
推荐阅读
阅读排行
最近更新
商品推荐