51单片机之DS1302实时时钟

慈云数据 11个月前 (04-19) 技术支持 49 0

1.DS1302时钟芯片介绍

  • DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
  • RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片

            这个时钟芯片的应用十分广泛,而且使用它作为时钟计时也是很常见的操作。

            我们51单片机上采用的也是这个芯片,有人认为,我们的定时器也可以做一个时钟计时,但其实,我们的定时器毕竟不是专业的,在长时间的积累下还是会产生一定的误差,而且我们对定时器的采样和各种操作都是会占用一定的的cpu时间的,因为CPU要去处理这个定时器的信息。并且,很重要的一点就是:我们的单片机断电就会让定时器暂停,再次重启单片机的时候,计时才会继续,所以这需要我们一直供电,并且单片机的高频率调用定时器还是挺耗电的,一点都不节能。

            让专业的人做专业的事——我们使用DS1302芯片就是为了解决这个问题的:高精度计时,无惧误差;自带内置电池,不怕断电,断电计时还在继续计时,开启继续显示。

            这里是这个芯片的引脚图:

            这里要注意的是芯片有两个VCC供电,其中VCC2是主电源,就是我们单片机的直接供电,VCC1就是芯片内部的备用电池,让芯片在断电的情况下还可以继续运作。

    这个就是芯片的内部结构图:

            

            在芯片手册里面还有这样的一张图:

            这个就是时序图,什么是时序图?你可以理解为单片机内部一个周期内发生的事情用一个电波来表示,这里有三个芯片上的引脚:CE(芯片使能),SCLK(时钟沿),I/O(输入输出)。CE比较简单,置为1就开始工作,置为0就停止工作。SCLK就是时钟周期,图上的箭头表示上升沿有效和下降沿有效。IO就是经典的寄存器,R/W到A0到1这个方向就是从低位到高位的数据

            R/W表示Read和Write(读和写)。R是高电平有效,W是低电平有效,这个位置决定了调用哪个模式。后面的D0到D7就是芯片内部对应的区域了,代入你想要写入哪个地址,这个就是最后的写入的数据。

            芯片手册里还有这个图片:

            这个图最左边就是读和写对应的地址,中间是对应地址的对应位表示的数据,最后就是数据的范围,第一行是秒,第二行是分钟,第三行是小时(对应有12和24小时制),第四行是日,第五行是月份,第六行是星期,第七行就是年,第八行主要看到WP(即Write Protect),写入保护(WP为1的时候生效,此时所有写入的操作无效),最后一行是电池充电,这个不需要我们配置,保持默认就好。

            然后这个表格中的读写地址是根据这个图的出来的:

            这里就不多解释了,看上面的详细的表格更好一点。它对应的运作模式就是上面的时序图。

    2.代码实现时钟

            这里主要用到LCD1602显示屏和这个时钟芯片相互配合实现,有人可能会疑惑为什么不用数码管,其实数码管也是可以的,这里主要是为了显示更多的数字和信息,数码管可以显示的位太少了,所以不使用数码管。

            我们配置寄存器前还要看一下原理图:

            可以看到,SCLK,IO,CE三个引脚都有定义,我们要在代码里使用sbit把它们重新定义一下,以便我们以后调用程序的时候一眼看出写的是什么。

    sbit DS1302_SCLK =	P3^6;
    sbit DS1306_IO   =	P3^4;
    sbit DS1306_CE 	 =	P3^5;

            这里我们要配置初始的时间数值,我们按照时序图先写一个写入函数:

            这里我们看到每次开始前SCLK和CE都是低电平,所以我们在写写入函数前,还要再写一个初始化函数,先把SCLK和CE先初始化为低电平

    void DS1602_Init()
    {
    	DS1306_CE = 0;
    	DS1302_SCLK = 0;
    }

            看时序图我们可以知道:一个上升沿表示一个数据的写入,和之前我们LED点阵屏的寄存器一样,使用SCLK控制读写数据,先把准备好的数据0/1放在IO口,当时钟上升沿生效之后,这个数据就被读入。并且,有一点要注意的是:数据是从低位(R/W)到高位(1),这个顺序,也就是上面图中从左到右对应输入数据的从低到高,这样我们就可以写出一个IO从低到高输入我们传入指令的代码了(按照时钟周期,先读入前面那8个控制位,后读入后面那八个数据位):

    unsigned char i = 0;
    for(i = 0;i
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon