DS1302 は、米国 DALLAS 社が発売した、トリクル電流充電機能を備えた低電力リアルタイム クロック チップです。年、月、日、週、時、分、秒の計時が可能で、うるう年補正など多彩な機能を搭載
RTC (リアルタイム クロック): リアルタイム クロックは、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 を使用するには、左側の 2 つに黄色のジャンパー キャップを忘れずに挿入してください。
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 つの 2 進数を使用して 1 つの 10 進数を表現します。
- 例: 0001 0011 は 13 を意味し、1000 0101 は 85 を意味し、0001 1010 は不正です。上位 8 ビットと下位 8 ビットはそれぞれ 10 進法の 10 と 1 を表します。
- 16 進数: 0x13 は 13 を意味し、0x85 は 85 を意味し、0x1A は不正です
BCD コードを 10 進数に変換: DEC=BCD / 16 * 10 + BCD % 16;
(2 桁の BCD)
10 進数から 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;
}