DS1307 在 IIC 總線上是從器件,地址固定為”11010000” DS1307 寫操作 TWI 被控接收模式 主控器件按如下順序將數據寫入到DS1307 寄存器或內部RAM 中:
第一步.START 信號
第二步。寫SLA+W(0xd0)字節,DS1307 應答(ACK)
第三步。寫1 字節內存地址(在以下第四步寫入的第一字節將存入到DS1307 內該地址處),DS1307應答。
第四步。寫數據(可寫多個字節,每一字節寫入后DS1307 內部地址計數器加一,DS1307 應答)
第五步.STOP 信號
由于是個初學者,對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++)
;
}
*********************************************************************/
評論
查看更多