目前家用的數字電子鐘,多數只能顯示小時、分鐘等信息,功能單一,而且大都采用LED數碼管作為顯示器件,功耗大,不能令消費者滿意。
DS1307簡介
AM/PM 標志位決定時鐘工作于24小時或12小時模式,芯片有一個內置的電源感應電路,具有掉電檢測和電池切換功能。
是一款低功耗,具有56字節(jié)非失性RAM的全BCD碼時鐘日歷實時時鐘芯片,地址和數據通過兩線雙向的串行總線的傳輸,芯片可以提供秒,分,小時等信息,每一個月的天數能自動調整。并且有閏年補償功能
特點:
可對秒,時,分,每月的天數,月份,每周的天數進行計數,并具有閏年補償功能。計年上限2100。
56字節(jié)非失性的RAM
兩線串行接口
可編程方波輸出
自動掉電檢測和切換電路
在電池備份模式下,功耗小于500nA
工業(yè)級的工作溫度: -40 到80
8腳DIP和SOIC封裝
下面分享一下基于DS1307的簡易時鐘顯示程序給大家:
* Coder:NUIST_XKFYT
* E-mail:weilun_fong@nuist.edu.cn(Welcome to get help info about this program)
* Date:2016-7-17
*
* Device:STC89C54RD,DS1307Z+
* Function:簡易時鐘顯示
* Note:
* 1.DS1307四位固定地址位為1101,三位可編程地址位為000
*/
#include 《STC89C5xRC.h》 /* 可更換為《reg52.h》或《AT89x52.h》 */
#include 《intrins.h》
//#include 《time.h》 /* Keil v4中無法調用該標準庫函數 */
#define uchar unsigned char
#define uint unsigned int
/* DS1307操作指令 */
#define DS1307_WRITE 0xD0
#define DS1307_READ 0xD1
#define DS1307_DISABLE 0x80
#define DS1307_ENABLE 0x7F
#define DS1307_12HOUR_MODE 0x20
#define DS1307_24HOUR_MODE 0xDF
/* DS1307內部寄存器地址 */
#define ADDR_SEC 0x00
#define ADDR_MIN 0x01
#define ADDR_HOUR 0x02
#define ADDR_DAY 0x03
#define ADDR_DATE 0x04
#define ADDR_MONTH 0x05
#define ADDR_YEAR 0x06
#define ADDR_COR 0x07
/* 模塊自帶AT24C02》》預留接口 */
//#define AT24C02_WRITE 0xA0
//#define AT24C02_READ 0xA1
sbit I2C_SCL = P1^0;
sbit I2C_SDA = P1^1;
uchar min = 0;
uchar sec = 0;
uchar code tab[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
/* 重新自定義《time.h》中的tm結構體 */
struct tm
{
uchar tm_sec; /* 秒 – 取值區(qū)間為[0,59] */
uchar tm_min; /* 分 - 取值區(qū)間為[0,59] */
uchar tm_hour; /* 時 - 取值區(qū)間為[0,23] */
uchar tm_mday; /* 一個月中的日期 - 取值區(qū)間為[1,31] */
uchar tm_mon; /* 月份(從一月開始,0代表一月) - 取值區(qū)間為[1,12] */
uchar tm_year; /* 年份 */
uchar tm_wday; /* 星期 – 取值區(qū)間為[1,7] */
};
/* delay 5us */
void delay_5us(void)
{
_nop_();
}
/* delay par*1ms */
void delay_ms(uint par)
{
uchar cnt = 0;
while(par--)
for(cnt = 120;cnt 》 0;cnt--);
}
void I2C_Start(void)
{
I2C_SDA = 1;
I2C_SCL = 1;
delay_5us(); /* 實際延時4.7us即可 */
I2C_SDA = 0; /* SCL為高電平時,SDA為下降沿表示起始信號 */
delay_5us();
}
void I2C_Stop(void)
{
I2C_SDA = 0;
I2C_SCL = 1;
delay_5us();
I2C_SDA = 1; /* SCL為高電平時,SDA為上升沿表示結束信號 */
delay_5us();
}
void I2C_Ack(void)
{
uchar cnt = 0;
I2C_SCL = 0; /* 在SCL為高電平期間等待應答 */
delay_5us();
while((I2C_SDA == 1)&&(cnt 《 250)) /* 若為應答0即退出,從機向主機發(fā)送應答信號 */
cnt++; /* 等待一段時間 */
I2C_SCL = 0;
delay_5us();
}
void I2C_noAck(void)
{
I2C_SCL = 1; /* 在scl為高電平期間,由主機向從機發(fā)送一個1,非應答信號 */
delay_5us();
I2C_SDA = 1;
I2C_SCL = 0;
delay_5us();
}
void I2C_sendByte(uchar dat)
{
uchar cnt = 0;
uchar dat_buf = 0;
dat_buf = dat;
for(cnt = 0;cnt 《 8;cnt++)
{
dat_b
uf = dat_buf 《《 1;/* 將數據的最高位移入到PSW中的CY位中 */
I2C_SCL = 0;
delay_5us();
I2C_SDA = CY; /* 將CY里的數據發(fā)送到sda數據線上 */
delay_5us();
I2C_SCL = 1; /* 在scl為高電平時,不允許sda上的數據變化,使數據穩(wěn)定 */
delay_5us();
I2C_SCL = 0; /* 允許sda數據線的數據變化,等待下一個數據的傳輸 */
delay_5us();
}
/* wait ack */
I2C_SCL = 0; /* 允許SDA變化 */
delay_5us();
I2C_SCL = 1;
delay_5us(); /* SDA拉高等待應答,當SDA = 0時,表示從機的應答 */
}
uchar I2C_receiveByte(void)
{
bit bit_buf = 0;
uchar cnt = 0;
uchar dat = 0;
I2C_SCL = 0; /* 讀之前允許SDA變化 */
delay_5us();
for(cnt = 0;cnt 《 8;cnt++)
{
I2C_SCL = 1; /* 拉高SCL禁止SDA變化 */
delay_5us();
bit_buf = I2C_SDA; /* 讀出SDA上的數據 */
dat = (dat 《《 1)|bit_buf;
I2C_SCL = 0; /* 允許SDA變化等待下次數據的到來 */
delay_5us();
}
return dat;
}
void I2C_Init(void)
{
I2C_SDA = 1;
delay_5us();
I2C_SCL = 1;
delay_5us();
}
void DS1307_writeByte(uchar addr,uchar dat) /* 讀取單字節(jié) */
{
I2C_Start();
I2C_sendByte(DS1307_WRITE);
I2C_Ack();
I2C_sendByte(addr); /* addr為目標地址 */
I2C_Ack();
I2C_sendByte(dat);
I2C_Ack();
I2C_Stop();
}
void DS1307_writeData(uchar addr_st,uchar dat[],uint num) /* num為要傳入的字節(jié)數 */
{
uchar cnt = 0;
I2C_Start();
I2C_sendByte(DS1307_WRITE);
I2C_Ack();
I2C_sendByte(addr_st); /* addr_st為起始地址 */
I2C_Ack();
for(cnt = 0;cnt 《 num;cnt++)
{
I2C_sendByte(dat[cnt]);
I2C_Ack();
}
I2C_Stop();
}
uchar DS1307_readByte(uchar addr)
{
uchar dat_buf = 0;
I2C_Start();
I2C_sendByte(DS1307_WRITE);
I2C_Ack();
I2C_sendByte(addr);
I2C_Ack();
I2C_Start(); /* 再次啟動I2C傳送數據 */
I2C_sendByte(DS1307_READ);
I2C_Ack();
dat_buf = I2C_receiveByte();
I2C_noAck();
I2C_Stop();
return dat_buf;
}
void DS1307_setTime(struct tm setValue)
{
DS1307_writeByte(ADDR_SEC,setValue.tm_sec);
DS1307_writeByte(ADDR_MIN,setValue.tm_min);
DS1307_writeByte(ADDR_HOUR,setValue.tm_hour);
DS1307_writeByte(ADDR_DAY,setValue.tm_wday);
DS1307_writeByte(ADDR_MONTH,setValue.tm_mon);
DS1307_writeByte(ADDR_YEAR,setValue.tm_year);
}
void DS1307_setEnableStatus(uchar setValue)
{
uchar buf = 0;
buf = DS1307_readByte(ADDR_SEC);
if(setValue == DS1307_ENABLE)
{
buf = buf&DS1307_ENABLE;
DS1307_writeByte(ADDR_SEC,buf);
}
else if(setValue == DS1307_DISABLE)
{
buf = buf|DS1307_DISABLE;
DS1307_writeByte(ADDR_SEC,buf);
}
else
buf = 0;
}
void DS1307_setHourMode(uchar setValue)
{
uchar buf = 0;
buf = DS
1307_readByte(ADDR_HOUR);
if(setValue == DS1307_12HOUR_MODE)
{
buf = buf|DS1307_12HOUR_MODE;
DS1307_writeByte(ADDR_HOUR,buf);
}
else if(setValue == DS1307_24HOUR_MODE)
{
buf = buf&DS1307_24HOUR_MODE;
DS1307_writeByte(ADDR_HOUR,buf);
}
else
buf = 0;
}
uchar DS1307_readSecond(void)
{
uchar sec_buf = 0;
uchar sec_l = 0;
uchar sec_h = 0;
sec_buf = DS1307_readByte(ADDR_SEC);
sec_h = (sec_buf 》》 4)&0x0F;
sec_l = sec_buf&0x0F;
return (sec_h*10 + sec_l);
}
uchar DS1307_readMinute(void)
{
uchar min_buf = 0;
uchar min_l = 0;
uchar min_h = 0;
min_buf = DS1307_readByte(ADDR_MIN);
min_h = (min_buf 》》 4)&0x0F;
min_l = min_buf&0x0F;
return (min_h*10 + min_l);
}
uchar DS1307_readHour(void)
{
uchar hour_buf = 0;
uchar hour_h = 0;
uchar hour_l = 0;
hour_buf = DS1307_readByte(ADDR_HOUR);
hour_h = (hour_buf 》》 4)&0x10;
hour_l = hour_buf&0x0f;
return (hour_h*10 + hour_l);
}
uchar DS1307_readDay(void)
{
uchar day_buf = 0;
day_buf = DS1307_readByte(ADDR_DAY);
return day_buf;
}
uchar DS1307_readDate(void)
{
uchar date_buf = 0;
uchar date_h = 0;
uchar date_l = 0;
date_buf = DS1307_readByte(ADDR_DATE);
date_h = (date_buf 》》 4)&0x0F;
date_l = date_buf&0x0F;
return (date_h*10 + date_l);
}
uchar DS1307_readMonth(void)
{
uchar month_buf = 0;
uchar month_h = 0;
uchar month_l = 0;
month_buf = DS1307_readByte(ADDR_MONTH);
month_h = (month_buf 》》 4)&0x0F;
month_l = month_buf&0x0F;
return (month_h*10 + month_l);
}
uchar DS1307_readYear(void)
{
uchar year_buf = 0;
uchar year_h = 0;
uchar year_l = 0;
year_buf = DS1307_readByte(ADDR_YEAR);
year_h = (year_buf 》》 4)&0x0F;
year_l = year_buf&0x0F;
return (year_buf*10 + year_l);
}
//struct tm DS1307_readTime(void)
void display(void)
{
P0 = tab[min/10]; /* P0為段選口 */
P2 = 0xFE; /* P2低四位為位選口 */
delay_ms(1);
P2 = 0xFF;
P0 = tab[min%10]&0x7F;
P2 = 0xFD;
delay_ms(1);
P2 = 0xFF;
P0 = tab[sec/10];
P2 = 0xFB;
delay_ms(1);
P2 = 0xFF;
P0 = tab[sec%10];
P2 = 0xF7;
delay_ms(1);
P2 = 0xFF;
}
void main(void)
{
uchar cnt = 0;
struct tm Init_t;
/* 初始時間全部置0(必須初始化!此步不可少!) */
Init_t.tm_sec = 0;
Init_t.tm_min = 0;
Init_t.tm_hour = 0;
Init_t.tm_wday = 0;
Init_t.tm_mon = 0;
Init_t.tm_year = 0;
I2C_Init();
DS1307_setTime(Init_t); /* 必須初始化!此步不可少! */
/* 主程序可根據需求自由修改 */
while(1)
{
sec = DS1307_readSecond();
min = DS1307_readMinute();
display();
}
}
評論
查看更多