DS1302

  • 实时时钟 DS1302
    • 一、实时时钟芯片DS1302
    • 二、 注意:DS1302内部寄存器存储的数据类型是BCD码!!!
    • 三、简易时钟代码

实时时钟 DS1302

一、实时时钟芯片DS1302

1、DS1302的主要性能指标
(1) DS1302实时时钟能够计算2100年之前的秒、分、时、日、日期、星期、月、年(闰年可自动调整)。 还可以通过配置AM/PM来决定采 用24小时格式还是12小时格式。
(2)内部含有31个字节静态数据存储RAM。
(3)串行I/O通信方式,使得管脚少,简单SPI仅3线接口。
(4)工作电压范围教宽:2.0~5.5V。
(5)工作电流小,功耗低:工作电压为2.0V时,小于300nA。
(6)时钟或RAM数据的读/写有两种传送方式:单字节传送和多字节传送方式。
(7)采用8脚DIP封装(双列直插式封装)或SOIC封装。
(8)供电电压Vcc=5V时,与标准TTL兼容,可与单片机通信。
(9)具有涓流充电能力。
(10)采用主电源和备份电源双电源供应。备用电源可以是电池或者大电容,确保在系统掉电的情况下,时钟还可以走。

DS1302封装图:

2、DS1302的硬件信息
DS1302引脚图:
各引脚功能:

引脚编号 引脚名称 引脚功能
1 Vcc2 主电源引脚,当Vcc2比Vcc1高0. 2V以上时,DS1302由 Vcc2供电,当Vcc2低于Vcc1时,由Vcc1供电。
2 X1 这两个引脚需要接- -个32. 768K的晶振,给DS1302提供一个基准 。
3 X2 特别注意,要求这个晶振的引脚负载电容必须是6pF,而不是要加6pF的电容。如果使用有源晶振的话,接到X1上即可,X2悬空。
4 GND 接地即可
5 CE DS1302的使能输入引脚。当读写DS1302的时候,这个引脚必须是高电平,DS1302这个引脚内部有一个40k的下拉电阻。
6 I/O 这个引脚是一个双向通信引脚,读写数据都是通过这个引脚完成。DS1302这个引脚的内部含有一个40k的下拉电阻。
7 SCLK 输入引脚。SCLK是用来作为通信的时钟信号。DS1302这个引脚.的内部含有- -个40k的下拉电阻。
8 Vcc1 备用电源引脚

其中只有5脚(CE使能)、6脚(I/O)、7脚(SCLK时钟)需要接到单片机的I/O口上。
DS1302的典型电路如下:

需要注意的是晶振电路。它使用的是32.768K的晶振,晶振外部不需要额外添加其他电容或者电阻。时钟的精度首先取决于晶振的精度以及晶振的引脚负载电容。如果晶振不准或者负载电容过大(小),就会导致时钟误差过大。其次需要考虑晶振的温漂。晶振的精度会随着温度的变化而变化。在实际系统中,常通过校对来减少这种误差的影响。

3、DS1302寄存器介绍
(1) 命令字节
DS1302一条指令一个字节共8位。第7位(最高位)固定为1(0无效);第6位是RAM/CLOCK选择端,这里主要学习CLOCK时钟的使用,所以第6位为0;第5位到第1位是寄存器的地址;第0位是读写控制位,1读0写。命令字节如下:

(2) 寄存器
DS1302有8个和时钟有关的寄存器,如下:

(表格从上到下依次为寄存器0到寄存器7)

  • 寄存器0:最高位CH是时钟停止标志位。通过该位判断时钟在单片机系统掉电后是否正常运行(0为有备用电源,正常运行)。剩余7位的高3位是秒的十位,低4位是秒的个位。由于DS1302内部是BCD码,秒的十位最大是5,所以3个二进制位足够。
  • 寄存器1:最高位未使用,剩余7位的高3位是分钟的十位,低4位是分钟的个位。
  • 寄存器2:bit7为1代表采用12小时制,为0表示24小时制;bit6固定为0;bit5在12小时制下,0表示上午,1表示下午,在24小时制下,和bit4一起表示小时的十位;低4位表示小时的个位。
  • 寄存器3:高两位固定是0,bit5 和 bit4是日期的十位,低4位是日期的个位。
  • 寄存器4:高3位固定是0,bit4 是月的十位,低4位是月的个位。
  • 寄存器5:高5位固定是0,低3位表示星期
  • 寄存器6:高4位表示年的十位,低4位表示年的个位。00 ~ 99指的是2000年~2099年。
  • 寄存器7:最高位为写保护位。如果此位为1,则禁止给任何其它的寄存器或者31个字节的RAM写数据。因此在写数据之前,此位必须写成0。

4、DS1302通信时序介绍
(1) 单字节写操作时序 (单片机向DS1302内写入)

  • 先写入寄存器地址,再写入待写字节

    (2)单字节读操作时序(单片机从DS1302读取数据)
  • 先写入寄存器地址,再读取该寄存器的数据

注:
①该时序图上的箭头方向都是针对DS1302而言的。
②应该先读取I/O线上的数据,再拉高SCK(时钟线)产生上升沿。

5、Burst 模式
DS1302寄存器中,与时间相关的寄存器有7个,分别依次对应秒、分、时、日期、月、星期、年。在读取这7个寄存器的过程中,无论怎样读,都会有时间差,在极端的情况下就会出现错误。例如当前时间是00:00:59,先读秒,读到的秒是59,然后再去读分钟。但是在读完秒准备去读分钟的这段时间内,刚好时间进位了,变成了00:01:59,这个错误就很明显了。

为了解决这个问题,芯片厂家提供了Burst的模式。这里主要学习时钟突发模式(RAM突发模式暂时忽略)。

当向DS1302内写入寄存器地址时,只要将写的5位地址都写1,即读操作用0xBF,写操作用0xBE,这时DS1302就能识别出是Burst模式,马上把所有的8个字节同时锁存到另外的8个字节的寄存器缓冲区内,这样时钟继续走,而我们读取的是另一个缓冲区内的数据。写数据同理,Burst模式下,我们是先把数据写到这个缓冲区内,最终DS1302会把这个缓冲区内的数据一次性送到它的时钟寄存器内。

从以上叙述不难看出,在DS1302时钟的Burst模式下,必须一次性读或者写8个字节,要把时钟的寄存器全部读出来或者完全写进去。

二、 注意:DS1302内部寄存器存储的数据类型是BCD码!!!

BCD码介绍

  • 我们时钟日历寄存器使用的是8421码型的BCD码,BCD码还有5421码、2421码等,其中8421码型的BCD码最最常用;
  • BCD码是用四位二进制数表示一位十进制数的0-9这十个数简称BCD码;
  • 8421码型BCD码最小值为0000 (二进制),最大值为1001 (二进制) : 9
  • 一个字节的8421码型BCD码中的低四位用于表示十进制的个位,高四位用于表示十进制的十位,如10 (十进制)的8421码型BCD码=00010000;

BCD码转换
例:把十进制数45转换为8421型的BCD码

unsigned char data1,data2 = 45;//声明两个无符号类型的char型变量data1和data2 并data2赋初值45
data1 = data2/10; // data1 = 4;
data2 = data2%10; // data2 = 5;
data2 = data2 + data1*16; // data2 = 5 + 4*16 = 69 即69为转换的BCD码

把69这个8421型的BCD码换算回十进制数:

data1 = data2/16; // data1 = 4;
data2 = data2%16; // data2 = 5;
data2 = data2 + data1*10; // data2 = 5 + 4*10 = 45

三、简易时钟代码

ds1302.h

#ifndef _DS1302_H_
#define _DS1302_H_
#include <STC15F2K60S2.H>
#define u8 unsigned char struct sTime{unsigned char hour;unsigned char min;unsigned char sec;
};
sbit DS1302_IO = P2^3;
sbit DS1302_CLK = P1^7;
sbit DS1302_CE = P1^3;void DS1302Write(unsigned char reg,unsigned char dat);
unsigned char DS1302Read(unsigned char reg);
void DS1302BurstWrite(unsigned char *dat);
void DS1302BurstRead(unsigned char *dat);
void BCD_TO_DAT(unsigned char *dat);
void DAT_TO_BCD(unsigned char *dat);
void GetRealTime(struct sTime *time);
void SetRealTime(struct sTime *time);
void DS1302Init();
#endif

ds1302.c

#include "ds1302.h"//发送一个字节到DS1302通信总线上
void DS1302ByteWrite(u8 dat)
{    u8 i;for(i=0;i<8;i++){DS1302_CLK = 0;DS1302_IO = dat & 0x01;DS1302_CLK = 1;dat>>=1;}
}//从DS1302通信总线上读取一个字节
u8 DS1302ByteRead()
{u8 i;u8 dat = 0;for(i=0;i<8;i++){DS1302_CLK = 0;//拉低时钟总线,写数据dat >>= 1;//先读的数据依次右移至最低位if(DS1302_IO){dat |= 0x80;}DS1302_CLK = 1;//拉高时钟总线,让IO读走一位}return dat;
}//向某一寄存器写入一个字节
void DS1302Write(u8 reg,u8 dat)
{DS1302_CLK = 0; //拉低使能端DS1302_CLK = 0; //拉低数据总线DS1302_CE = 1; //拉高使能端 产生上升沿 准备发送数据DS1302ByteWrite(reg);DS1302ByteWrite(dat);DS1302_CE = 0; //拉低使能端,以便下次产生上升沿
}
//从某一寄存器读取一个字节
u8 DS1302Read(u8 reg)
{u8 dat = 0;DS1302_CE = 0;DS1302_CLK = 0;DS1302_CE = 1; //产生上升沿 准备发送寄存器指令DS1302ByteWrite(reg);dat = DS1302ByteRead();DS1302_CE = 0;return dat;
}
//用Burst突发模式连续写入8个寄存器数据
void DS1302BurstWrite(u8 *dat)
{u8 i;DS1302_CE = 0;DS1302_CLK = 0;DS1302_CE = 1;DS1302ByteWrite(0xBE);for(i=0;i<8;i++){DS1302ByteWrite(dat[i]);}DS1302_CE = 0;
}
//用Burst突发模式连续读取8个寄存器数据
void DS1302BurstRead(u8 *dat)
{u8 i;DS1302_CE = 0;DS1302_CLK = 0;DS1302_CE = 1;DS1302ByteWrite(0xBF);for(i=0;i<8;i++){dat[i] = DS1302ByteRead();}DS1302_CE = 0;
}
//将BCD码转换为十进制数
void BCD_TO_DAT(u8 *dat)
{u8 i;unsigned char Temp = 0;for(i=0;i<sizeof(dat);i++){Temp = dat[i]/16;dat[i] = dat[i]%16;dat[i] = dat[i]+Temp*10;}
}
//将十进制数转换为BCD码
void DAT_TO_BCD(u8 *dat)
{u8 i;unsigned char Temp = 0;for(i=0;i<sizeof(dat);i++){Temp = dat[i]/10;dat[i] = dat[i]%10;dat[i] = dat[i] + Temp*16;}
}//获取时间
void GetRealTime(struct sTime *time)
{unsigned char buf[8];DS1302BurstRead(buf);BCD_TO_DAT(buf);time ->sec = buf[0];time ->min = buf[1];time ->hour = buf[2];
}
//设置时间
void SetRealTime(struct sTime *time)
{unsigned char buf[8];buf[0] = time -> sec;buf[1] = time -> min;buf[2] = time -> hour;DAT_TO_BCD(buf);DS1302BurstWrite(buf);
}
//DS1302初始化
void DS1302Init()
{struct sTime InitTime;//初始化设置 8点59分0秒InitTime.sec = 0;InitTime.min = 59;InitTime.hour = 8;DS1302Write(0x8e,0x00);//关闭写保护SetRealTime(&InitTime);
}

main.c

#include "sys.h"
#include "ds1302.h"
struct sTime time;
bit DS1302_READ_FLAG;
void main()
{ALL_Init();Timer0Init();DS1302Init();while(1){DS1302Write(0x8e,0x00);//关闭写保护if(DS1302_READ_FLAG)//每100ms获取一次时ds1302数据{DS1302_READ_FLAG = 0;GetRealTime(&time);DS1302Write(0x8e,0x80);//打开写保护}Nixie_Drive(&time);//将ds1302数据通过数码管显示}}

nixie.c

#include "sys.h"
#include "ds1302.h"// 0    1    2    3    4    5    6    7
uchar code nixie[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,// 8 9    a    b    c    d     e    f    u0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xc1}; //共阳数码管码字uchar NixieBuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};uchar smg1,smg2,smg3,smg4,smg5,smg6,smg7,smg8;
uchar code Symbol[] = {0xff,0xbf}; //全灭,-void Nixie_Scan()
{static u8 index;HC138_Set(7);P0 = 0xff;HC138_Set(6);P0 = 0x01 << index;HC138_Set(7);P0 = NixieBuff[index];HC138_Set(0);index++;index &= 0x07;
}void Nixie_Show()
{NixieBuff[0] = nixie[smg1];NixieBuff[1] = nixie[smg2];NixieBuff[2] = Symbol[smg3];NixieBuff[3] = nixie[smg4];NixieBuff[4] = nixie[smg5];NixieBuff[5] = Symbol[smg6];NixieBuff[6] = nixie[smg7];NixieBuff[7] = nixie[smg8];
}void Nixie_Drive(struct sTime *time)
{smg1 = time->hour/10;smg2 = time->hour%10;smg4 = time->min/10;smg5 = time->min%10;smg7 = time->sec/10;smg8 = time->sec%10;if(time->sec%2==0){smg3 = smg6 = 1;}else{smg3 = smg6 = 0;}
}

注意:
1、本程序采用了结构体、指针,让程序显得更为复杂,不采用也一样能实现该功能,代码也会更少。
2、 本程序是直接用的burst模式一次性读写7个寄存器

蓝桥杯单片机设计与开发⑪ --- DS1302相关推荐

  1. 第十一届 蓝桥杯 单片机设计与开发项目 决赛

    第十一届 蓝桥杯 单片机设计与开发项目 决赛 题目 源码 赛题总结 1.界面切换 2.参数生效 3.LED显示 题目 源码 #include <STC15F2K60S2.H> #inclu ...

  2. 蓝桥杯——单片机设计与开发初学者必备资料

    蓝桥杯--单片机设计与开发初学者必备资料 国信长天 大赛官方指定电子类比赛硬件提供方,可能大家只知道他们提供硬件,殊不知还有一些免费的视频讲解(只是老师可能说话带一点方言,嘻嘻),感兴趣的可以去看看, ...

  3. 第十一届蓝桥杯 单片机设计与开发省赛试题

    第十一届蓝桥杯 单片机设计与开发 省赛 在昨天举办了第一波11届蓝桥杯比赛,第2波大概在10月份左右,看了看比赛题目,这次题目对于我来说,程序设计题简单,客观题全靠蒙! 本次比赛涉及: 1.数码管显示 ...

  4. 蓝桥杯单片机设计与开发_标准模板

    蓝桥杯单片机设计与开发_标准模板 一.前言 首先,这篇文章是笔者第一次在 CSDN 上写博文,较为生疏,读者若有任何意见,欢迎大家在评论区交流! 笔者目前为一名大二学生,参加了2021年蓝桥杯单片机设 ...

  5. 蓝桥杯单片机设计与开发历届客观题答案

    该页面由pdf转换而来,阅读效果不佳,你可以在这里下载pdf原件:https://download.csdn.net/download/dvs_dn/19373128 你也可以在百度文库免费下载该文档 ...

  6. 最新 2021年 第十二届 蓝桥杯 单片机设计与开发 省赛 客观试题 个人答案

    第十二届蓝桥杯单片机设计与开发项目省赛 第一部分客观试题(30分) 不定项选择(3分/题) (1)MCS-51单片机外部中断1的中断请求标志是( B ).     A.ET1        B.IE1 ...

  7. 蓝桥杯单片机设计与开发题目分析与源码(智能门锁)

    蓝桥杯单片机设计与开发(智障门锁) 内附完整工程 代码仅供参考,如有建议疑问欢迎留言讨论 程序设计部分 智能门锁-任务指导书 开发环境 Keil5 Stc-isp 国兴天长开发板 任务分析 任务逻辑梳 ...

  8. 蓝桥杯单片机设计与开发笔记(一)

    近期和我们实验室的小伙伴一起参加了第七届蓝桥杯单片机开发与设计组省赛,在这里将备赛期间的一些资料和经验总结一下,并分享给大家. 蓝桥杯单片机开发板是国信长天的CT107D单片机综合训练平台,个人感觉这 ...

  9. 蓝桥杯单片机设计与开发⑫ ---超声波模块

    一.基本原理 超声波发射模块向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时. 二.计算公式 距离 = 声速 × 发 ...

最新文章

  1. John细说PHP的验证码
  2. 【MM配置】Purchasing 采购配置
  3. leetcode 525. Contiguous Array | 525. 连续数组(Java)
  4. 不缓存调用js的方法
  5. 2 分支语句——《Swift3.0 从入门到出家》
  6. 视频直播推流攻略(整理的各大平台推流界面)
  7. MVG 为 SGS 提供汽车天线测量和 OTA 测试设备
  8. 边框盒子 box-sizing 的 content-box 和 border-box属性
  9. 知名互联网公司校招 Java 开发岗面试知识点解析
  10. 2 MyBatis Sql映射文件
  11. 4016: 辉夜的夜空明珠(moon)
  12. Hive启动报错:java.net.URISyntaxException: Relative path in absolute URI: ${system:user.name%7D
  13. Web全栈~34.CAS
  14. 计算雅思成绩C语言,终于发现【官方】雅思考试分数计算方法
  15. 【哲学问题】-《哲学家们都干了些什么?》
  16. 比Postman还好用的API神器Eolink,效率担当
  17. 赵小楼《天道》《遥远的救世主》深度解析(83)形式主义的典范,辩证逻辑的障碍
  18. label-studio批量上传本地数据
  19. 创建数据库表格的方法
  20. WebView 生成长图,截图

热门文章

  1. 【某航】队列模型(MM1)设计与仿真
  2. R绘图lattice包
  3. 香港地面数字电视发展
  4. 使用Metasploit查找漏洞
  5. c语言超市选址问题实验报告,邮局选址问题 (C语言代码)
  6. iPhone 激光雷达与地球科学应用程序
  7. 反编译工具jad下载、安装及使用(无需集成环境一键使用)
  8. 【网络流量识别】【深度学习】【二】RNN和ANN—深度学习入侵检测方法:ANN和RNN在NSL-KDD上的新性能
  9. 基于C++的简单深度学习ANN(人工神经网络)模型
  10. 在uCGUI中添加汉字库