歡迎您光臨本站 登入註冊首頁

I2C讀寫心得(AT24C02篇)

admin @ 2014-03-14 , reply:0

概述

困擾我幾的程序終於搞定了,前幾天我對AT24C02一直讀不準確,找了N長時間的程序都沒有頭緒,後來在板哥的指點下,一下子明白了,原因很簡單,我在AT24C02_read()最後沒有加延時,主要還是對時……

困擾我幾的程序終於搞定了,前幾天我對AT24C02一直讀不準確,找了N長時間的程序都沒有頭緒,後來在板哥的指點下,一下子明白了,原因很簡單,我在AT24C02_read()最後沒有加延時,
主要還是對時序沒有控制好呀,用板哥的一句話是我們對器件的了解還不很熟,我現在也感到,一定要先了解了器件的特性,我們才能遊刃有餘把握住每一個容易疏忽的細節,在這裡,板哥確實教會了我好多東西,在我剛學單片機時,他就對我說時序很重要,現在終於是看到了.
好了不羅嗦了,最後得出一點,最好在每個讀寫結束時加個延時,如果對時間要求不是很重要的話,加的長一點無所謂,如果要求比較高的話,那先加長延時,然後慢慢的減.
#include
#include

//輸入方式設置
#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++)
    ;
}

[admin via 研發互助社區 ] I2C讀寫心得(AT24C02篇)已經有3588次圍觀

http://cocdig.com/docs/show-post-371.html