进行产品开发的时候,逻辑的严谨性非常重要,如果一个产品或者程序逻辑上不严谨,就有可能出现功能上的错误。比如我们 15.3.4 节里的这个程序,我们再回顾一下,当单片机定时器时间到了 200ms 后,我们连续把 DS1302 的时间参数的 7 个字节读了出来。但是不管怎么读,都会有一个时间差,在极端的情况下就会出现这样一种情况:假如我们当前的时间是 00:00:59,我们先读秒,读到的秒是 59,然后再去读分钟,而就在读完秒到还未开始读分钟的这段时间内,刚好时间进位了,变成了 00:01:00 这个时间,我们读到的分钟就是 01,显示在液晶上就会出现一个 00:01:59,这个时间很明显是错误的。出现这个问题的概率极小,但却是实实在在可能存在的。
为了解决这个问题,芯片厂家肯定要给我们提供一种解决方案,这就是 DS1302 的突发模式。突发模式也分为 RAM 突发模式和时钟突发模式,RAM 部分我们不讲,我们只看和时钟相关的 clock burst mode。
当我们写指令到 DS1302 的时候,只要我们将要写的 5 位地址全部写 1,即读操作用 0xBF,写操作用 0xBE,这样的指令送给 DS1302 之后,它就会自动识别出来是 burst 模式,马上把所有的 8 个字节同时锁存到另外的 8 个字节的寄存器缓冲区内,这样时钟继续走,而我们读数据是从另外一个缓冲区内读取的。同样的道理,如果我们用 burst 模式写数据,那么我们也是先写到这个缓冲区内,最终 DS1302 会把这个缓冲区内的数据一次性送到它的时钟寄存器内。
要注意的是,不管是读还是写,只要使用时钟的 burst 模式,则必须一次性读写 8 个寄存器,要把时钟的寄存器完全读出来或者完全写进去。
下边就提供一个 burst 模式的例程给大家学习一下,程序的功能还是与上一节一样的。
/***************************Lcd1602.c 文件程序源代码*****************************/
(此处省略,可参考之前章节的代码)
为了解决这个问题,芯片厂家肯定要给我们提供一种解决方案,这就是 DS1302 的突发模式。突发模式也分为 RAM 突发模式和时钟突发模式,RAM 部分我们不讲,我们只看和时钟相关的 clock burst mode。
当我们写指令到 DS1302 的时候,只要我们将要写的 5 位地址全部写 1,即读操作用 0xBF,写操作用 0xBE,这样的指令送给 DS1302 之后,它就会自动识别出来是 burst 模式,马上把所有的 8 个字节同时锁存到另外的 8 个字节的寄存器缓冲区内,这样时钟继续走,而我们读数据是从另外一个缓冲区内读取的。同样的道理,如果我们用 burst 模式写数据,那么我们也是先写到这个缓冲区内,最终 DS1302 会把这个缓冲区内的数据一次性送到它的时钟寄存器内。
要注意的是,不管是读还是写,只要使用时钟的 burst 模式,则必须一次性读写 8 个寄存器,要把时钟的寄存器完全读出来或者完全写进去。
下边就提供一个 burst 模式的例程给大家学习一下,程序的功能还是与上一节一样的。
/***************************Lcd1602.c 文件程序源代码*****************************/
(此处省略,可参考之前章节的代码)
- /*****************************main.c 文件程序源代码******************************/
- #include <reg52.h>
- sbit DS1302_CE = P1^7;
- sbit DS1302_CK = P3^5;
- sbit DS1302_IO = P3^4;
- bit flag200ms = 0; //200ms 定时标志
- unsigned char T0RH = 0; //T0 重载值的高字节
- unsigned char T0RL = 0; //T0 重载值的低字节
- void ConfigTimer0(unsigned int ms);
- void InitDS1302();
- void DS1302BurstRead(unsigned char *dat);
- extern void InitLcd1602();
- extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
- void main(){
- unsigned char psec=0xAA; //秒备份,初值 AA 确保首次读取时间后会刷新显示
- unsigned char time[8]; //当前时间数组
- unsigned char str[12]; //字符串转换缓冲区
- EA = 1; //开总中断
- ConfigTimer0(1); //T0 定时 1ms
- InitDS1302(); //初始化实时时钟
- InitLcd1602(); //初始化液晶
- while (1){
- if (flag200ms){ //每 200ms 读取依次时间
- flag200ms = 0;