ds1307的iic读写心得

编程实验

72人已加入

描述

DS1307 在 IIC 总线上是从器件,地址固定为”11010000”   DS1307 写操作 TWI 被控接收模式 主控器件按如下顺序将数据写入到DS1307 寄存器或内部RAM 中:

第一步.START 信号

第二步。写SLA+W(0xd0)字节,DS1307 应答(ACK)

第三步。写1 字节内存地址(在以下第四步写入的第一字节将存入到DS1307 内该地址处),DS1307应答。

第四步。写数据(可写多个字节,每一字节写入后DS1307 内部地址计数器加一,DS1307 应答)

第五步.STOP 信号

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!=‘’‘’;x++)

{

LCD_send_data(*(Data++));

}

if(*Data!=‘’‘’)

{

x=0;

y=LINE2;

}

}

}

if(y==LINE2)

{

LCD_send_command(LINE2_HEAD+x);

for(;x《LINE_LENGTH&&*Data!=‘’‘’;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++)

;

}

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

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分