(基于江协科技)51单片机入门:8.DS1302
DS1302
DS1302是具有眷细电流充电能力的低功耗实时时钟芯片
DS1302可自带一块电池,以保证掉电计时
RTC(real time clock):实时时钟,是一种集成电路,通常称为时钟芯片
CE 为芯片使能:作用为控制从DS1302中获取数据,给以0获取不了,给1有可能获取
IO:数据输入和输出
SCLK:串行时钟
命令字
第 7 位固定为1
第 6 位选择是 RAM 还是 CK
第 0 为选择是 读 还是 写
字母上加一横表示为 0有效 或低电频有效
写入
RTC
读出
根据写入和读出去写DS1302函数
源文件
#include <REGX52.H>sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;void DS1302_Init()
{DS1302_CE = 0;DS1302_SCLK = 0;
}void DS1302_Wr(unsigned char c,d)
{unsigned char i = 0; DS1302_CE = 1;// 命令字for(i = 0 ; i < 8; i++){DS1302_IO = c&(0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}// 写入数据for(i = 0 ; i < 8; i++){DS1302_IO = d&(0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}DS1302_CE = 0;}unsigned char DS1302_Rd(unsigned char c)
{unsigned char ret = 0;unsigned char i = 0; DS1302_CE = 1;// 命令字for(i = 0 ; i < 8; i++){DS1302_IO = c&(0x01<<i);DS1302_SCLK = 0;DS1302_SCLK = 1;}// 读取数据 这里的写法和上面不同for(i = 0; i < 8; i++){DS1302_SCLK = 1; DS1302_SCLK = 0; // 命令字结束后的第一个下降沿要先进行,将io赋值if(DS1302_IO){ret|=(0x01<<i);} // 表示读出值为1 就在相对应的位赋1} // 为0,ret初始化就是0,所以相对应的位也为0return ret;
}
头文件
#ifndef __DS1302_H_
#define __DS1302_H_void DS1302_Init();void DS1302_Wr(unsigned char c,d);unsigned char DS1302_Rd(unsigned char c);
#endif
注意在主函数里利用函数时,DS1302初始化后
要跟哥DS1302_Wr(0x8e,0x00)关闭写入保护
BCD码
用4位二进制来表示1位十进制
BCD码转十进制:BCD/16*10 + BCD%16;(2位BCD)
十进制转BCD码:BCD = DEC/10*16 + DEC%10;(2位BCD)
DS1302内部已经限制了相对应内容的最大值
例如:秒 60 分钟 60 小时 24(会自动从新计数)、
后加2函数的思路是:利用数组将DS1302内部初始化(DS1302_SetTime),利用数组将DS1302内部数据读出存入数组中(DS1302_ReadTime),在主函数中调用一次DS1302_SerTime,在循环中调用DS1302_ReadTime(实现数据更新)
DS1302函数:
源文件
#include <REGX52.H>sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;unsigned char arr[] = {19,11,16,12,59,55,6};// 写入地址
#define DS1302_S 0x80
#define DS1302_M 0x82
#define DS1302_H 0x84
#define DS1302_Date 0x86
#define DS1302_Month 0x88
#define DS1302_Day 0x8a
#define DS1302_Year 0x8c
#define DS1302_WP 0x8evoid DS1302_Init()
{DS1302_CE = 0;DS1302_SCLK = 0;
}void DS1302_Wr(unsigned char c,d)
{unsigned char i = 0; DS1302_CE = 1;// 命令字for(i = 0 ; i < 8; i++){DS1302_IO = c&(0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}// 数据for(i = 0 ; i < 8; i++){DS1302_IO = d&(0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}DS1302_CE = 0;
}unsigned char DS1302_Rd(unsigned char c)
{unsigned char ret = 0;unsigned char i = 0; c |=0x01;DS1302_CE = 1;// 命令字for(i = 0 ; i < 8; i++){DS1302_IO = c&(0x01<<i);DS1302_SCLK = 0;DS1302_SCLK = 1;}for(i = 0; i < 8; i++){DS1302_SCLK = 1; DS1302_SCLK = 0; if(DS1302_IO){ret|=(0x01<<i);} } DS1302_CE = 0;return ret;
}void DS1302_SetTime(void)
{DS1302_Wr(DS1302_WP,0X00); // 关闭写保护DS1302_Wr(DS1302_Year,arr[0]/10*16+arr[0]%10); // DS1302数据是以BCD码存入// 所以要10进制转化DS1302_Wr(DS1302_Month,arr[1]/10*16+arr[1]%10);DS1302_Wr(DS1302_Date,arr[2]/10*16+arr[2]%10);DS1302_Wr(DS1302_H,arr[3]/10*16+arr[3]%10);DS1302_Wr(DS1302_M,arr[4]/10*16+arr[4]%10);DS1302_Wr(DS1302_S,arr[5]/10*16+arr[5]%10);DS1302_Wr(DS1302_Day,arr[6]/10*16+arr[6]%10);DS1302_Wr(DS1302_WP,0X80); // 打开写保护
}
void DS1302_ReadTime(void)
{unsigned char tmp = 0;tmp = DS1302_Rd(DS1302_Year);arr[0]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_Month);arr[1]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_Date);arr[2]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_H);arr[3]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_M);arr[4]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_S);arr[5]=tmp/16*10 + tmp%16;tmp = DS1302_Rd(DS1302_Day);arr[6]=tmp/16*10 + tmp%16;}
头文件
#ifndef __DS1302_H_
#define __DS1302_H_extern unsigned char arr[];void DS1302_Init();void DS1302_Wr(unsigned char c,d);unsigned char DS1302_Rd(unsigned char c);void DS1302_SetTime(void);void DS1302_ReadTime(void);
#endif
1.时钟主函数文件
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"int main()
{DS1302_Init();LCD_Init();DS1302_SetTime();while(1){DS1302_ReadTime();LCD_ShowString(1,1," _ _");LCD_ShowNum(1,1,arr[0],2);LCD_ShowNum(1,4,arr[1],2);LCD_ShowNum(1,7,arr[2],2);LCD_ShowString(2,1," : :");LCD_ShowNum(2,1,arr[3],2);LCD_ShowNum(2,4,arr[4],2);LCD_ShowNum(2,7,arr[5],2);}return 0;
}