讨论一款老掉牙的实时时钟芯片DS1302

今天我们来讨论一款老掉牙的实时时钟芯片 ds1302 。什么是实时时钟(realtime clock, rtc)呢?为什么我们需要它呢?假设你使用单片机实现万年历应用,一般的做法是这样的:设置中断后判断1秒是否到来,如果到来就将秒数加1,然后再考虑一些进位处理,例如,每60秒则分钟加1,每60分则小时加1, 24小时或12小时制也要区分对待,每12个月则年加1,还要考虑闰月闰年。虽然考虑的事情好像有些多,但是在资讯非常发达的今天,从网络上搜索出现成的代码也绝不是难事。
当然,利用代码来实现这些算法并不是惟一途径,你也可以使用实时时钟芯片来减轻编程负担,只要我们把芯片内的年月日时分秒等参数设置为当前时间,启动后内部会自动开始计数,理论上芯片记录的时间将与我们的时间 实时同步 ,进位的问题也由芯片自行处理,我们只需要在必要的时候从芯片中读取一些时间值即可,实在不要太简单。
ds1302就是一款使用广泛的rtc芯片,我们来看看与时间相关的寄存器有哪些,如下图所示(ds1302内部另外还有31个字节的ram,本文不涉及):
首先我们关注一下地址,可能不少人会想:这些地址怎么这么怪呢?你这个厂家设计芯片时就不能靠谱点吗?地址从0x00开始连续增加会死呀?竟然还分为不同的读写地址,我看这个芯片设计者是闲得“淡”疼,简单的问题复杂化!
然而实际上,这9个寄存器地址的确是 0x0 ~0x8 ,并且读写的也确实是同一个地址的数据,只不过数据手册在标记这些地址时,把发送串行数据中的其它一些位也考虑进来了。我们来看看如何往ds1302中写入一个字节的数据,相应的时序如下图所示:
可以看到,单个字节数据写入到ds1302需要两个字节,前一个字节用来确定写数据的目的地址。后一个字节就是需要写入的数据。请注意: 两个字节都是以低位先行的方式发送 ,正常情况下确定地址的前一个字节如下图所示
读写数据时最高位(第7位)必须为1,最低位用来表示读(rd=1)还是写( **wr=0** )数据。我们刚刚提过,ds1302内部额外还有31个字节的ram,可作为通用的ram使用,第6位表示往ram(ram=1)还是rtc( **ck=0** )中写入(或读取)数据,**前面表格中标注的写或读地址就是把这****8** **位都考虑进来了** 。
如果你往rtc中写入数据,第7位总是1,第6位与第0位总是0,所以写的地址总是偶数,读的地址总是奇数。是不是闲得“淡”疼呢?还真不是,因为从本质上来讲,读写信号以及访问区域(ram/ck)选择位也可以算是地址线。例如,以前讨论的hd44780有一个rs引脚表示写入的是数据还是指令,但是你也可以认为它是一条地址线,它决定你将代码写入数据寄存器还是指令寄存器。
好吧!地址的事情已经谈妥了,咱们来一一介绍ds1302内部与时间有关的寄存器:
(1 )【地址0x80 】秒钟寄存器(seconds ) :ds1302中rtc寄存器都是以bcd码来保存的,也就是说,个位与十位分别占用一些位。在8位秒钟寄存器中,bit3~0用来保存秒钟的个位,bit6~4用保存秒钟的十位,因为秒数是不可能大于5的,所以用3位已然足够,而最高位bit7表示时钟挂起位( clockhalt, ch ) ,当ch=1时,时钟暂时处于挂起状态(暂停计数),当ch=0时,计数才会开始运行。 **这个寄存器的设计还是很巧妙的** ,也就是说,只要我们往秒寄存器写入实际的秒钟数时,ch位都会被清零。换句话说,一般情况下,我们都会先初始化年月日时分等其它寄存器,而秒钟寄存器留待最后设置,同时也开启了芯片计数。
(2 )【地址0x82 】分钟寄存器(minutes ) :与秒钟寄存器一样,bit3~0用来保存分钟的 个数 ,bit6~4用保存分钟的 十位 ,最高位是无效的。
(3 )【地址0x84 】小时寄存器(hour ) :该寄存器的低4位保存小时的个位,而小时的十位则取决于时间是24还是12小时制。bit7=1时为12小时制,那么小时的十位不可能大于1( 1 ~12 ),它只需要一位(bit4)表示即可,只是还多了一个bit5用来表示下午(pm=1)还是上午(am=0);而bit7=0时为24小时制,十位数最大值可能为2( **0** **~23** ),所以用bit5~bit4表示小时的十位。
(4 )【地址0x86 】日期寄存器(data ) :日期表示一个月份有多少天,其范围为1~31,十位最大值为3,所以用bit5~4表示十位,bit3~0表示个位。
(5 )【地址0x88 】月份寄存器(month ) :月份范围是1~12,所以用bit4表示十位,bit3~0表示个位。
(6 )【地址0x8a 】星期寄存器(day ) :星期的范围是1~7,所以用bit2~bit0表示即可。可能有些人在想:为什么星期数用day而不用week之类的呢?我还以为是天数呢!因为英文的星期1~7都是以day结尾,例如,monday,sunday, friday等等。英文询问今天星期几即“what day is today?”
(7 )【地址0x8c 】年份寄存器(year ) :ds1302的年份范围是00~99,所以分别用高4位与低4位分别表示十位与个位。
(8 )【地址0x8e 】写保护寄存器(write protect, wp ) : 该寄存器只有最高位有效,为1表示开启写保护,为0表示解除写保护。在往rtc(或ram)中写入数据前,必须将该位清0。
(9 )【地址0x90 】充电寄存器 :与时间计数无关,咱们最后讨论。
我们使用visualcom软件平台来仿真一下,相应的仿真效果如下图所示:
调出的ds1302器件有一个能够方便我们观察rtc内部状态的屏幕,其实就是一块能够显示4行20个字符的液晶显示模组(lcm2004),从屏幕上看到信息就是从ds1302中读取出来并写入到lcm2004中的。当然,一些特殊的寄存器状态还是得观察“内存”窗口,相应的预置数据如下图所示:
visualcom软件平台中的预置数据格式均按照正常位序定义,共16位有效,高8位设置访问地址,低8位则是写入的数据,如下图所示:
首先我们解除了写保护。因为无论你写什么、往哪里写,写保护都需要解除(将wp位清零),所以需要写入的数据为“ 0b10001110_0000000 (0x8e00 ) ”,如下图所示
写保护解锁后,咱们就可以为所欲为了,在依次写入年份、星期、月份、日期、小时、分钟后,我们才设置了 秒钟 ,也就同时启动了芯片的计数,简单吧!
最后我们谈谈 充电寄存器 ,它是用来做什么的呢?有电脑使用经验的读者都知道,当我们将电脑彻底关机(电)后再开机,时间仍然还在继续跑的,对不对?因为电脑的处理器也有rtc功能,当电脑处于开机时,rtc由外部电源供电,而在断电状态下,rtc则由主板上的电池(最常见的是钮扣电池 cr2032 )供电。换句话说,rtc单元的供电总是不会断开的,所以计数功能也从来没有停止过,类似的供电电路如下图所示:
图中rtc_vdd是rtc单元的供电电源,电路系统上电后vcc是有电的,同时也给rtc单元供电,断电后则由电池供电,两个二极管可以防止vcc与电池之间出现漏电状态。
ds1302有两个电源供电引脚,vcc2为主电源供电(相当于上图的 vcc ),vcc1为辅助电源供电。当vcc2没有电源供电时,挂在vcc1引脚的电池将给rtc供电,如图所示:
如果电池是可充电型的,当vcc2主电源有供电时,我们就可以使用充电寄存器来控制充电参数,我们来看看vcc2与vcc1之间的内部电路,如下图所示:
可以看到,vcc2与vcc1之间有三级开关,tcs3~tcs0控制主电源是否往辅助电源供电,ds1~ds0控制串联的二极管个数,rout1~rout0控制串联的电阻值,数据手册有下表所示的功能表:
如果你使用可充电电池,并且决定使用充电功能,应该通过选择合适的二极管数量与阻值 来限制最大充电电流 。假设供电电源为5v,并且使用1个二极管与2k欧姆电阻串联方式,则最大充电电流为imax=(5v-0.7v)/2k≈2.2ma。

中国未来模拟芯片的出路在何方
高田气囊涉事车企增至19家:特斯拉Model S也将召回
热风枪可以用什么代替_吹风机能代替热风枪吗
人工智能越来越发达 但不能脱离束缚
贸泽电子备货Panasonic PAN1780高性能蓝牙5低功耗模块
讨论一款老掉牙的实时时钟芯片DS1302
无线充电道路:梦想还是要有的 万一实现了呢?
硬件EMC设计规范!
CAN标准中的时钟容差修正建议
热电制冷的原理
云存储管理之Azure Managed Disks分析
华为“天生会画”数字创作大赛完美收官,相聚中国动漫博物馆共话数字化创作价值
如何在RT-Thread OS环境下使用ncnn进行AI推理
5G改变社会将是一个长期渐进式的过程
结合IMOS IP多媒体应用的监控管理平台软件的发展趋势
基于FPGA技术实现SD模式设备接口的设计方案
油浸式变压器高压套管漏油的治理方法
制造业转型期 职业教育为关键
简单电路测量电池消耗
浅析无源雷达的定义及其发展状态