蓝桥杯之单片机设计与开发(20)——DS1302
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相关推荐
- 2020蓝桥杯之单片机设计与开发(1)——CT107D开发板了解与准备
在快放假期间开始准备蓝桥杯,也感谢我的好朋友带我一起去了解这个比赛. 首先从单片机开始,比赛的时候使用的开发板是官方指定的CT107D单片机竞赛板V20. 先看上面的官方指定开发版原理图,包含了开发板 ...
- 蓝桥杯之单片机设计与开发
目录 1.关于开发板 2.关于各个模块 3.历年省赛真题 4.省赛代码资源下载 5.历年国赛真题 6.国赛代码资源下载 7.第十届省赛前最后的总结与程序封装 8.第十届省赛再现 2021年1月26更新 ...
- 蓝桥杯之单片机设计与开发——第八届省赛_基于单片机的电子钟程序设计与调试
目前在准备蓝桥杯,自己写了往届的赛题,调试以后觉得没什么问题.希望大家能给出一些建议,指出其中的错误和不足,也真挚地希望能给大家提供一些方法和思路.共勉! 赛题 main.c #include < ...
- 蓝桥杯之单片机设计与开发(18)——模数转换A/D与数模转换D/A
A/D的主要指标 1.ADC的位数 一个n位的ADC表示这个ADC共有2的n次方个刻度.8位的ADC输出的是从0~255一共256个数字值,也就是个数据刻度.. 2.基准源 基准源也叫基准电压,是AD ...
- 蓝桥杯之单片机设计与开发(34)——第十届省赛前最后总结与程序封装
目录 上电全部初始化 LED 数码管显示 蜂鸣器buzzer 继电器relay 独立按键BTN 矩阵键盘KBD E2PROM和AD DS18B20 DS1302 超声波 明天就是省赛了,今天最后一天. ...
- 蓝桥杯之单片机设计与开发(9)——独立按键实现计时器
功能: 1.按下S6,清零并停止计时 2.按下S5,暂停计时 3.按下S4,开始计时 计时时,LED为流水灯状态,计时显示格式为 分-秒-毫秒 main.c /******** ...
- 第十三届蓝桥杯《EDA设计与开发》赛后总结
目录 一,赛前准备 1.立创培训第一题 2.立创培训第二题 3.立创培训第三题 4.自选训练第一题 5.自选训练第二题 二,省赛 1.第12届蓝桥杯湖北省赛试题 2.第13届蓝桥杯山东省赛试题 3.第 ...
- 【蓝桥杯嵌入式】【STM32】12_2020_第十一届_蓝桥杯_嵌入式设计与开发项目_省赛
工程下载地址 这是比赛时写的工程,个人感觉写的不怎么样(仅供参考)但是功能算是实现的七七八八: https://gitee.com/Joseph_Cooper/blue-bridge-embedd ...
- 第十三届蓝桥杯《EDA设计与开发》客观题
题目一主要考察元器件的基本知识. 电容器在电路中的作用.ABCD 第二题 只要ABC中其中一个输出高电平其余Y就可以获得高电平.A 第三题 电容容量的计算和转换,前两位是真实数,第三位是10的n次方. ...
最新文章
- centos7安装mongodb3.4
- 三维激光重建原理与实现HALCON
- android各目录大小,Android 基础篇 — 放不同drawable文件夹中图片的大小
- Python学习笔记__8章错误、调试和测试__8.1章错误处理
- VTK:可视化之Follower
- 【嵌入式】Libmodbus源码分析(五)-TCP相关函数分析
- C# 图片画矩形,添加文字
- 安装程序将在重启您的计算机后黑屏,安装windows10一直黑屏怎么解决_win10安装到一半黑屏修复方法...
- php打包mysql_PHP封装MySQL的单例
- Android学习_ContentProvider和Uri
- 使用dos下的命令行,也可以完成wifi连接。
- js打开本地文件_JS逆向|高频问题:为何Reres插件总是替换本地文件失败?
- AEC回声消除基础知识
- 闲谈安全测试之IAST
- 迷信一把:三才数理吉凶
- 变形菌门扩张——肠道微生态失调和炎症肠病的潜在特征
- Python手册(Machine Learning)--statsmodels(列联表和多重插补)
- Psychopy学习笔记上|online流程,unexpected token
- 5阶魔方阵c语言程序设计,五阶魔方阵源代码c语言时课程设计.docx
- 为多孔介质的当量直径_CFX多孔介质模型介绍