DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片,如DS1302、DS3231、DS12C887
sbit DS1302_SCLK = P3^6; // 时钟
sbit DS1302_IO = P3^4; // 输入输出
sbit DS1302_CE = P3^5; // 使能开关
void DS1302_Init(){
DS1302_CE = 0;
DS1302_SCLK = 0;
}
/**
* @brief 单字节写入
* @param
* @retval
*/
void DS1302_WriteByte(unsigned char command, Data){
unsigned char i;
DS1302_CE = 1; // 开启使能开关
for(i = 0;i < 8;i++){
DS1302_IO = command & (0x01 << i); // 取出命令字第i位
DS1302_SCLK = 1; // 写入一位命令字
DS1302_SCLK = 0; // 恢复
}
for(i = 0;i < 8;i++){
DS1302_IO = Data & (0x01 << i); // 取出数据第i位
DS1302_SCLK = 1; // 写入一位数据
DS1302_SCLK = 0; // 恢复
}
DS1302_CE = 0; // 关闭
}
/**
* @brief 单字节读取
* @param
* @retval
*/
unsigned char DS1302_ReadByte(unsigned char command){
unsigned char i, Data = 0x00;
command |= 0x01; // 保证是读操作,这样可以直接传入define的值
DS1302_CE = 1;
for(i = 0;i < 8;i++){
DS1302_IO = command & (0x01 << i); // 取出命令字第i位
DS1302_SCLK = 0; //
DS1302_SCLK = 1; //
}
for(i = 0;i < 8;i++){
DS1302_SCLK = 1;
DS1302_SCLK = 0; // 读取到IO
if(DS1302_IO){
Data |= (0x01 << i); // 若IO非0,将Data的i位置1
}
}
DS1302_CE = 0;
DS1302_IO = 0; // IO清零
return Data;
}
注意,记得把黄色跳帽插到左边两个上,才能使用LCD
void main(){
unsigned char Sec = 0x00;
LCD_Init();
DS1302_Init();
DS1302_WriteByte(0x8e,0x00); // 在写寄存器之前必须先将写保护位给清零
DS1302_WriteByte(0x80, 0x00); // 写入00秒
while(1){
Sec = DS1302_ReadByte(0x81);
LCD_ShowNum(1, 1, Sec, 2);
Delay(50);
}
}
在DS1302中并不是以二进制来表示时间的,而是以BCD码表示:
BCD码(Binary Coded Decimal),用4位二进制数来表示1位十进制数
- 例:0001 0011表示13,1000 0101表示85,0001 1010不合法,高8位和低8位分别表示十进制的十位和个位
- 在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法
BCD码转十进制:DEC=BCD / 16 * 10 + BCD % 16;
(2位BCD)
十进制转BCD码:BCD = DEC / 10 * 16 + DEC % 10;
(2位BCD)
//寄存器写入地址/指令定义
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
/**
* @brief 将time数组里的时间写入时钟
* @param
* @retval
*/
void DS1302_SetTime(){
DS1302_WriteByte(DS1302_WP, 0x00); // 关闭写保护
DS1302_WriteByte(DS1302_YEAR, time[0]/10*16 + time[0]%10); // 十进制转BCD后写入
DS1302_WriteByte(DS1302_MONTH, time[1]/10*16 + time[1]%10);
DS1302_WriteByte(DS1302_DATE, time[2]/10*16 + time[2]%10);
DS1302_WriteByte(DS1302_HOUR, time[3]/10*16 + time[3]%10);
DS1302_WriteByte(DS1302_MINUTE, time[4]/10*16 + time[4]%10);
DS1302_WriteByte(DS1302_SECOND, time[5]/10*16 + time[5]%10);
DS1302_WriteByte(DS1302_DAY, time[6]/10*16 + time[6]%10);
DS1302_WriteByte(DS1302_WP, 0x80);
}
/**
* @brief 读出时钟的时间
* @param
* @retval
*/
void DS1302_ReadTime(){
unsigned char Temp;
Temp=DS1302_ReadByte(DS1302_YEAR);
time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
Temp=DS1302_ReadByte(DS1302_MONTH);
time[1]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DATE);
time[2]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_HOUR);
time[3]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_MINUTE);
time[4]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_SECOND);
time[5]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DAY);
time[6]=Temp/16*10+Temp%16;
}