DS1302硬件信息

DS1302引脚图

DS1302典型电路

DS1302寄存器介绍

DS1302的一条指令一个字节共8位。

其中第7位(最高位)固定为1。这一位如果是0的话,那写进去也是无效的。

第6位是选择RAM还是CLOCK的。第6位是0就是选择CLOCK功能,第6位是1就是选择RAM。

第5到第1位,决定了寄存器的5位地址。

第0位是读写位。第0位是0就是写,第0位是1就是读。

DS1302时钟的寄存器,有8个与时钟相关的。

注意:DS1302内部是BCD码!!!

寄存器0:最高位CH是一个时钟停止标志位。如果时钟电路有备用电源,上电后,我们要先检测一下这一位,如果这一位是0,那说明时钟芯片在系统掉电后,由于备用电源的供给,时钟是持续正常运行的;如果这一位是1,那么说明时钟芯片在系统掉电之后,时钟部分不工作了。我们可以通过这一位判断时钟在单片机系统掉电后是否在正常运行。剩下的7位,高3位是秒的十位,低4位是秒的个位。

寄存器1:最高位未使用,剩下的7位中高3位是分钟的十位,低4位是分钟的个位。

寄存器2:bit7是1的话代表是12小时制,0代表是24小时制。bit6固定是0。bit5在12小时制下0代表是上午,1代表是下午,在24小时制下和bit4一起代表了小时的十位。低4位代表的是小时的个位。

寄存器3:高2位固定是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。

DS1302通信时序

DS1302的通信是SPI的变异种类,它用了SPI的通信时序,但是通信的时候没有完全按照SPI的规则来。

上升沿DS1302写入数据,下降沿DS1302读出数据! 上沿采样,下沿输出。

单字节读时序

单字节写时序

读操作有两处需要特别注意的地方。第一,DS1302的时序图上的箭头都是针对DS1302来说的,因此读操作的时候,先写第一个字节指令,上升沿的时 候DS1302来锁存数据,下降沿我们用单片机发送数据。到了第二个字数据,由于我们这个时序过程相当于CPOL=0/CPHA=0,前沿发送数据,后沿读取数据,第二个字节是DS1302下降沿输出数据,我们的单片机上升沿来读取,因此箭头从DS1302角度来说,出现在了下降沿。

第二个需要注意的地方就是,我们的单片机没有标准的SPI接口,和I2C一样需要用IO口来模拟通信过程。在读DS1302的时候,理论上SPI是上升沿读取,但是程序是用IO口模拟的,所以数据的读取和时钟沿的变化不可能同时了,必然就有一个先后顺序。通过实验发现,如果先读取IO线上的数据,再拉高SCLK产生上升沿,那么读到的数据一定是正确的,而颠倒顺序后数据就有可能出错。这个问题产生的原因还是在于DS1302的通信协议与标准SPI协议存在的差异造成的,如果是标准SPI的数据线,数据会一-直保持到下一个周期的下降沿才会变化,所以读取数据和上升沿的先后顺序也就无所谓了。但DS1302的IO线会在时钟上升沿后被DS1302释放,也就是撤销强推挽输出变为弱下拉状态,而此时在单片机引脚内部上拉的作用下,IO线上的实际电平会慢慢上升,从而导致在上升沿产生后再读取IO数据的话就可能会出错。因此这里的程序我们按照先读取IO数据,再拉高SCLK产生上升沿的顺序。

DS1302的BURST模式

定时器时间到了 200ms 后,我们连续把 DS1302 的时间参数的 7 个字节读了出来。但是不管怎么读,都会有一个时间差,在极端的情况下就会出现这样一种情况:假如我们当前的时间是 00:00:59,我们先读秒,读到的秒是 59,然后再去读分钟,而就在读完秒到还未开始读分钟的这段时间内,刚好时间进位了,变成了 00:01:00 这个时间,我们读到的分钟就是 01,显示在液晶上就会出现一个 00:01:59,这个时间很明显是错误的。出现这个问题的概率极小,但却是实实在在可能存在的。

所以这个时候就有了BURST模式,BURST模式就是一次把7 个字节全部读或写到缓冲区,然后再来进行后续操作!

当写指令到DS1302的时候,只要将要写的5位地址全部写1,即读操作用0xBF,写操作用0xBE,这样的指令送给DS1302之后,它就会自动识别出来是burst模式,马上把所有的8个字节同时锁存到另外的8个字节的寄存器缓冲区中,这样时钟继续走,而我们读数据是从另外一个缓冲区内读取的。同样的道理,如果我们是用burst模式写数据,那么我们也是先写到这个缓冲区内,最终DS1302会把这个缓冲区内的数据一次性送到它的时钟寄存器内。

注意:不管是读还是写,只要使用时钟的burst模式,则必须一次性读写8个寄存器,要把时钟的寄存器完全读出来或者完全写进去。

#include "sys.h"sbit DS1302_IO = P2^3;
sbit DS1302_CK = P1^7;
sbit DS1302_CE = P1^3;struct sTime{unsigned int year;      //年unsigned char mon;       //月unsigned char day;       //日unsigned char hour;      //时unsigned char min;       //分unsigned char sec;       //秒unsigned char week;      //周
};/*******************************************************************************
* 函数名   :DS1302ByteWrite
* 输入值   :unsigned char dat
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:发送一个字节到DS1302通信总线上
* 备注        :
*******************************************************************************/
void DS1302ByteWrite(unsigned char dat)
{unsigned char mask;DS1302_IO = 1;                 //拉低IO总线for(mask = 0x01; mask != 0; mask <<= 1)    //低位在前,逐位移出{if((dat&mask) != 0)     //首先输出该位数据DS1302_IO = 1;elseDS1302_IO = 0;DS1302_CK = 1;             //拉高时钟线DS1302_CK = 0;              //拉低时钟线,完成一个位的操作}DS1302_IO = 1;                 //写完之后确保释放IO总线
}  /*******************************************************************************
* 函数名   :DS1302ByteRead
* 输入值   :none
* 返回值   :unsigned char dat
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:由DS1302通信总线上读取一个字节
* 备注        :返回读到的字节数据
*******************************************************************************/
unsigned char DS1302ByteRead(void)
{unsigned char mask, dat = 0;for(mask = 0x01; mask != 0; mask <<= 1)  //低位在前,逐位读取{if(DS1302_IO)            //首先读取此时的IO引脚,并设置dat中的对应位dat |= mask;DS1302_CK = 1;        //拉高时钟DS1302_CK = 0;       //再拉低时钟,完成一个位的操作}return dat;                 //返回读到的字节数据
} /*******************************************************************************
* 函数名   :DS1302SingleWrite
* 输入值   :unsigned char reg, unsigned char dat
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:用单次写操作向某一寄存器写入一个字节
* 备注        :reg为寄存器地址,dat为待写入字节
*******************************************************************************/
void DS1302SingleWrite(unsigned char reg, unsigned char dat)
{DS1302_CE = 1;                    //使能片选信号DS1302ByteWrite((reg << 1) | 0x80);   //发送写寄存器指令DS1302ByteWrite(dat);     //写入字节数据DS1302_CE = 0;                 //除能片选信号
}/*******************************************************************************
* 函数名   :DS1302SingleRead
* 输入值   :unsigned char reg
* 返回值   :unsigned char dat
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:用单次读操作从某一寄存器读取一个字节
* 备注        :reg为寄存器地址,返回值dat为读到的字节
*******************************************************************************/
unsigned char DS1302SingleRead(unsigned char reg)
{unsigned char dat;DS1302_CE = 1;                  //使能片选信号DS1302ByteWrite((reg << 1) | 0x81);   //发送读寄存器指令dat = DS1302ByteRead();  //读取字节数据DS1302_CE = 0;                 //除能片选信号DS1302_IO = 0;                 //单字节读必须加的!return dat;
}/*******************************************************************************
* 函数名   :DS1302BurstWrite
* 输入值   :unsigned char *dat
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:用突发模式连续写入8个寄存器数据
* 备注        :reg为寄存器地址,返回值dat为读到的字节
*******************************************************************************/
void DS1302BurstWrite(unsigned char *dat)
{unsigned char i;DS1302_CE = 1;DS1302ByteWrite(0xBE);              //发送突发写寄存器指令for(i = 0; i < 7; i ++)               //连续写入8字节数据DS1302ByteWrite(*dat++);        DS1302_CE = 0;
}/*******************************************************************************
* 函数名   :DS1302BurstRead
* 输入值   :unsigned char *dat
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:用突发模式连续读取8个寄存器的数据
* 备注        :dat为读到的字节
*******************************************************************************/
void DS1302BurstRead (unsigned char *dat)
{unsigned char i;DS1302_CE = 1;DS1302ByteWrite(0xBF);              //发送突发读寄存器指令for(i = 0; i < 7; i++)                //连续读取8个字节dat[i] = DS1302ByteRead();      DS1302_CE = 0;  DS1302_IO = 0;                             //突发读必须加
}   /*******************************************************************************
* 函数名   :GetRealTime
* 输入值   :struct sTime *time
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:读取DS1302时间
* 备注        :
*******************************************************************************/
void GetRealTime(struct sTime *time)
{unsigned char buf[8];DS1302BurstRead(buf);time -> year = buf[6] + 0x2000;time -> mon  = buf[4];time -> day  = buf[3];time -> hour = buf[2];time -> min  = buf[1];time -> sec  = buf[0];time -> week = buf[5];
}/*******************************************************************************
* 函数名   :SetRealTime
* 输入值   :struct sTime *time
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:设置DS1302时间
* 备注        :
*******************************************************************************/
void SetRealTime(struct sTime *time)
{unsigned char buf[8];buf[7] = 0;buf[6] = time -> year;buf[4] = time -> mon;buf[3] = time -> day;buf[2] = time -> hour;buf[1] = time -> min;buf[0] = time -> sec;buf[5] = time -> week;DS1302BurstWrite(buf);
}/*******************************************************************************
* 函数名   :InitDS1302
* 输入值   :none
* 返回值   :none
* 作者        :小默haa
* 时间        :2019年3月1日
* 功能描述:DS1302初始化
* 备注        :
*******************************************************************************/
void InitDS1302()
{struct sTime InitTime[] = {  //2019年3月1日 星期五 21:50:000x19, 0x03, 0x01, 0x21, 0x50, 0x00, 0x05};DS1302_CE = 0;                                //初始化DS1302通信引脚DS1302_CK = 0;DS1302SingleWrite(7, 0x00);   //撤销写保护以允许写入数据SetRealTime(&InitTime);               //设置DS1302为默认时间
}

蓝桥杯之单片机设计与开发(20)——DS1302相关推荐

  1. 2020蓝桥杯之单片机设计与开发(1)——CT107D开发板了解与准备

    在快放假期间开始准备蓝桥杯,也感谢我的好朋友带我一起去了解这个比赛. 首先从单片机开始,比赛的时候使用的开发板是官方指定的CT107D单片机竞赛板V20. 先看上面的官方指定开发版原理图,包含了开发板 ...

  2. 蓝桥杯之单片机设计与开发

    目录 1.关于开发板 2.关于各个模块 3.历年省赛真题 4.省赛代码资源下载 5.历年国赛真题 6.国赛代码资源下载 7.第十届省赛前最后的总结与程序封装 8.第十届省赛再现 2021年1月26更新 ...

  3. 蓝桥杯之单片机设计与开发——第八届省赛_基于单片机的电子钟程序设计与调试

    目前在准备蓝桥杯,自己写了往届的赛题,调试以后觉得没什么问题.希望大家能给出一些建议,指出其中的错误和不足,也真挚地希望能给大家提供一些方法和思路.共勉! 赛题 main.c #include < ...

  4. 蓝桥杯之单片机设计与开发(18)——模数转换A/D与数模转换D/A

    A/D的主要指标 1.ADC的位数 一个n位的ADC表示这个ADC共有2的n次方个刻度.8位的ADC输出的是从0~255一共256个数字值,也就是个数据刻度.. 2.基准源 基准源也叫基准电压,是AD ...

  5. 蓝桥杯之单片机设计与开发(34)——第十届省赛前最后总结与程序封装

    目录 上电全部初始化 LED 数码管显示 蜂鸣器buzzer 继电器relay 独立按键BTN 矩阵键盘KBD E2PROM和AD DS18B20 DS1302 超声波 明天就是省赛了,今天最后一天. ...

  6. 蓝桥杯之单片机设计与开发(9)——独立按键实现计时器

    功能:     1.按下S6,清零并停止计时     2.按下S5,暂停计时     3.按下S4,开始计时 计时时,LED为流水灯状态,计时显示格式为 分-秒-毫秒 main.c /******** ...

  7. 第十三届蓝桥杯《EDA设计与开发》赛后总结

    目录 一,赛前准备 1.立创培训第一题 2.立创培训第二题 3.立创培训第三题 4.自选训练第一题 5.自选训练第二题 二,省赛 1.第12届蓝桥杯湖北省赛试题 2.第13届蓝桥杯山东省赛试题 3.第 ...

  8. 【蓝桥杯嵌入式】【STM32】12_2020_第十一届_蓝桥杯_嵌入式设计与开发项目_省赛

    工程下载地址   这是比赛时写的工程,个人感觉写的不怎么样(仅供参考)但是功能算是实现的七七八八: https://gitee.com/Joseph_Cooper/blue-bridge-embedd ...

  9. 第十三届蓝桥杯《EDA设计与开发》客观题

    题目一主要考察元器件的基本知识. 电容器在电路中的作用.ABCD 第二题 只要ABC中其中一个输出高电平其余Y就可以获得高电平.A 第三题 电容容量的计算和转换,前两位是真实数,第三位是10的n次方. ...

最新文章

  1. centos7安装mongodb3.4
  2. 三维激光重建原理与实现HALCON
  3. android各目录大小,Android 基础篇 — 放不同drawable文件夹中图片的大小
  4. Python学习笔记__8章错误、调试和测试__8.1章错误处理
  5. VTK:可视化之Follower
  6. 【嵌入式】Libmodbus源码分析(五)-TCP相关函数分析
  7. C# 图片画矩形,添加文字
  8. 安装程序将在重启您的计算机后黑屏,安装windows10一直黑屏怎么解决_win10安装到一半黑屏修复方法...
  9. php打包mysql_PHP封装MySQL的单例
  10. Android学习_ContentProvider和Uri
  11. 使用dos下的命令行,也可以完成wifi连接。
  12. js打开本地文件_JS逆向|高频问题:为何Reres插件总是替换本地文件失败?
  13. AEC回声消除基础知识
  14. 闲谈安全测试之IAST
  15. 迷信一把:三才数理吉凶
  16. 变形菌门扩张——肠道微生态失调和炎症肠病的潜在特征
  17. Python手册(Machine Learning)--statsmodels(列联表和多重插补)
  18. Psychopy学习笔记上|online流程,unexpected token
  19. 5阶魔方阵c语言程序设计,五阶魔方阵源代码c语言时课程设计.docx
  20. 为多孔介质的当量直径_CFX多孔介质模型介绍

热门文章

  1. 三菱FX3U——ST编程定时器和计数器
  2. 网站抛出521解决思路
  3. 慧数汽车纵览:特朗普以关税为名要求德系车企增加在美投资,这招可还行?
  4. openjfx(javaFX)完整学习指南(教程)
  5. EasyRecovery for Mac(数据恢复软件)中文免费版
  6. 商品cta策略_CTA策略解析
  7. code warrior 及BDM
  8. WOWWEE ROVIO小车改造思路
  9. 视频教程-YOLOv4目标检测实战:人脸口罩佩戴检测-计算机视觉
  10. python实现 小程序用户管理实现