访问电脑版页面

导航:老古开发网手机版其他

I2C读写心得(DS1307)

导读:
关键字:
由于是个初学者,对I2C总线从来没有接触过,看了几遍I2C总线规则后,有了点了解,觉的在单片机这样IO口资源不是相对充足的芯片上,来扩展总线接口,I2C是最好的选择了,他只占用单片机的两个IO口,还可以将不同和相同的I2C器件挂接在相同的总线上,
但好的东西,简洁的东西,操作起来不是那么简单的,因为他只有两根线,SDA和SCL,所有的读写都要通过这两根线的不同电平来控制,看了几遍总线规则,对他的读写时序还是不懂.最叫人郁闷的是对AT24C02的读写,我写了一个晚上的程序,竟然读不出来,时序什么好像都没有错,到现在我还是不知道什么原因,后来换了一个DS1307来试,还好这次可以了,对DS1307的读写,当每次向I2C总线写时,要等待从器件的应答位,我在这里就是这样处理,用时间的延迟来代替对应答位的检测,实践证明这样完全是可以的
#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
 
 /*************************以下是函数的申明部分*************************/
 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);
 /*********************结束***********************************************/
/***************************DS1307开始*****************************************************************/
#define    Wait1us        _nop_();
#define    Wait2us        {_nop_();_nop_();}
#define    Wait4us        {Wait2us;Wait2us;}
#define    Wait8us        {Wait4us;Wait4us;}
#define    Wait10us    {Wait8us;Wait2us;}
#define  WRITEDS1307    0xD0
#define     READDS1307    0xD1
  sbit SDA=P2^7;      //DS1307 Serial-Data Input    pin 5
  sbit SCL=P2^6;     //DS1307 Serial-Clock Input    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 Write1307(unsigned char add,unsigned char dat);//write information to ds1307
unsigned char Read1307(unsigned char add);//read information from ds1307
void Read_RTC(void);//read RTC
void Set_RTC(void);//set RTC
/***********************************************************************/
code unsigned char set_rtc_code[7]={0,30,7,4,20,4,6};
code unsigned char rtc_address[7]={0x00,0x01,0x02,0x03,0x04,0x05,0x06};
code unsigned char *day[7]={"Mon","Tue","Wen","Thu","Fri","Sat","Sun"};
unsigned char read_rtc_code[7];
/***********************************************************************/
void Initial(void);//system initize function
void Display(void);//RTC display function
/***********************************************************************/
/***********************************************************************/
void main(void)
{
 Initial();
 while(1)
 {  
  Read_RTC();
  Display();
 }
}
/***********************************************************************/
void Initial(void)      
{
 LCD_init();
 Set_RTC();   
}
/***********************************************************************/
void I2C_start(void)
{
  SDA=1;
  SCL=1;
  Wait8us;
  SDA=0;
  Wait8us;
  SCL=0;
 
}
/***********************************************************************/
void I2C_stop(void)
{
  SDA=0;
  SCL=1;
  Wait8us;
  SDA=1;
  Wait4us;
  SCL=0;
}
/***********************************************************************
void I2C_send_ack(void)
{
  SDA=0;
  SCL=1;
  Wait4us;
  SCL=0;
}
*************************************************************************/
void I2C_send_noack(void)
{
 SDA=1;
 SCL=1;
 Wait4us;
 SCL=0;
}
/***********************************************************************/
void I2C_write_byte(unsigned char IIC_data)
{
     unsigned char i;
     for(i=0;i<8;i++)
  {
          SCL=0;
           if((IIC_data<<i) & 0x80)
     SDA=1;                   //判断发送位
           else SDA=0;
           Wait2us;
            SCL=1;
            Wait4us;
            SCL=0;
        }
            Wait4us;
            SDA=1; //发送完8bit,释放总线准备接收应答位
            Wait2us;
            SCL=1;
            Wait4us; //sda上数据即是从应答位
            SCL=0; //不考虑从应答位 但要控制好时序
 }
/***********************************************************************/
unsigned char I2C_read_byte(void)
{
  unsigned char i,dat;
       dat=0;
     SDA=1;
   for (i=0;i<8;i++)
    {
      dat=dat<<1;
      SCL=1;
       Wait2us;
    if(SDA==1)
    {
      dat++;
  }
    
       SCL=0; 
    } 
   return (dat);
}
/***********************************************************************/
/******************************** DS1307 PART START  ****************/
void Write1307(unsigned char add,unsigned char dat)
{
  I2C_start();
  I2C_write_byte(WRITEDS1307);
  I2C_write_byte(add);
  I2C_write_byte(dat);
  I2C_stop();
}
 
/***********************************************************************/
unsigned char Read1307(unsigned char add)
{
 
  unsigned char dat;
  I2C_start();
  I2C_write_byte(WRITEDS1307);
  I2C_write_byte(add);
  I2C_start();
  I2C_write_byte(READDS1307);
  dat=I2C_read_byte();
  I2C_send_noack();
  I2C_stop();       
  return (dat);
   }
/****************************读DS1307的寄存器*******************************************/
void Read_RTC(void)
{
 unsigned char i,*p;
 p=rtc_address;
 for(i=0;i<7;i++)
 {
  read_rtc_code[i]=Read1307(*p);
  p++;
  }
}
/***************************DS1307的初始化********************************************/
void Set_RTC(void)
{
 unsigned char i,*p;
 p=rtc_address;
 for(i=0;i<7;i++)
 {
  Write1307(*p,set_rtc_code[i]);
  p++; 
 }
/********************  OTHER PART   ******************************/
void Display(void)     
{
 LCD_write_char(0x0f,LINE2,(read_rtc_code[0]%10) 0x30);
 LCD_write_char(0x0e,LINE2,(read_rtc_code[0]/10) 0x30);
 LCD_write_char(0x0c,LINE2,(read_rtc_code[1]%10) 0x30);
 LCD_write_char(0x0b,LINE2,(read_rtc_code[1]/10) 0x30);
 LCD_write_char(0x09,LINE2,(read_rtc_code[2]%10) 0x30);
 LCD_write_char(0x08,LINE2,(read_rtc_code[2]/10) 0x30);
 LCD_write_char(0x09,LINE1,(read_rtc_code[4]%10) 0x30);
 LCD_write_char(0x08,LINE1,(read_rtc_code[4]/10) 0x30);
 LCD_write_char(0x06,LINE1,(read_rtc_code[5]%10) 0x30);
 LCD_write_char(0x05,LINE1,(read_rtc_code[5]/10) 0x30);
 LCD_write_char(0x03,LINE1,(read_rtc_code[6]%10) 0x30);
 LCD_write_char(0x02,LINE1,(read_rtc_code[6]/10) 0x30);
 
 LCD_write_string(0x0d,LINE1,day[read_rtc_code[3]-1]);
 LCD_write_string(0x0d,LINE2,":");
 LCD_write_string(0x0a,LINE2,":");
 LCD_write_string(0x07,LINE1,"-");
 LCD_write_string(0x04,LINE1,"-");
 LCD_write_string(0x00,LINE1,"20");
}
 /*********************************************************/
 /**************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
栏目: [ ]

相关阅读

安森美推出新的高功率图腾柱PFC控制器,满足具挑战的能效标准

动态功耗低至60μA/MHz!助力设备超长续航,首选国民技术低功耗MCU!