NO12 蓝桥杯单片机之DS1302的使用

1 DS1302是什么

DS1302由两块存储器组成,一个是日历时钟寄存器还有一个是31位的静态RAM存储器。

而在蓝桥杯中常考的就是日历时钟寄存器,故这里只介绍日历时钟寄存器。简单来说,其就是一个“电子表”,他会自动的实时记录时间,而不需要像我们之前运用定时器做的时钟一样,要自己来设计时钟怎么运行,DS1302是已经自动设计好了,我们只需要写入从哪个时刻开始计时,以及读取相应的时间即可。

2 DS1302的结构

2.1 硬件原理图(就是单片机上DS1302芯片的引脚连接情况)

这里比较重要的就是SCK,RST,I/O(SDA)这三个引脚,其在头文件中需要定义,要学会看原理图这三个口连接哪三个引脚。

2.2 内部寄存器结构图

2.2.1 控制字的格式

控制字简单理解就是控制写入或读取哪个地址啊,是读取还是写入啊,用的是RAM还是CK啊这些操作,各个位的要求如图。

(再往下看,其实这个控制字就是下个图中左侧读寄存器和写寄存器的那些地址为什么是这样写。)

比如:当选择日历时钟给模式。

读寄存器的第一个地址为81H, BIT7=1,BIT6=0,BIT5~BIT1=0,读操作故BIT0=1,

即1000 0001,写成16进制为81H

写寄存器的第一个地址为80H,BIT7=1,BIT6=0,BIT5~BIT1=0,写操作故BIT0=0,

即1000 0000,写成16进制为80H。

读寄存器的第二个地址为83H, BIT7=1,BIT6=0,BIT5~BIT2=0,BIT1=1,读操作故BIT0=1,

即1000 0001,写成16进制为83H

......

2.2.2 日历时钟寄存器

(以下图来源小蜜蜂老师,注意:有个错误,CH为1的时候时钟是停止为0的时候是开始运行,这里小蜜蜂老师写反了。

日历时钟寄存器中一共包含8个8位寄存器,前7个分别为秒——分——时——日——月——周——年,(黄色高亮部位即为可以用于表示时间数据的位)

最后一个为控制寄存器,有效位只有BIT7,其他强制为0。(具体操作如图)

第一个秒寄存器:(CH为1的时候时钟是停止为0的时候是开始运行,这里小蜜蜂老师写反了。

第三个时寄存器BIT7位表示可以选择是12小时模式还是24小时模式,当选择24小时时,BIT5位用于选择AM还是PM模式。

注意:时间数据是用BCD码表示,(以八位数为例,前四个为十位,后四个为个位,且每四个数只能表示0~9),因此,图中黄色高亮部分有的写10秒,10分,指的是秒的十位和分的十位,(由于秒和时十位最多为5,故只需要用三个位就可以表示,最高位恒为0,只是秒的最高位被利用成了CH位而已。)

3 DS1302代码编写即使用

(1):地址写成数组

首先,日历时钟寄存器经过控制字格式来写,地址是固定的,因此在代码编写中将读写寄存器地址写成一个固定的数组会方便后续操作。

(与秒——分——时——日——月——周——年即上一个图中的顺序一 一对应,由于最后一个寄存器只有首位有效,我们就放到后面单独写,就不写进数组里了

///写寄存器地址
unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};//读寄存器地址
unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

(2):时间参数写成数组

 DS1302的基本操作实际上非常简单,只有两个操作:其一是设定时间参数,其二是读取实时时间。不管是那个操作,MCU都要通过SPI接口进行数据交互,而SPI接口有其规定的时序,这个必须参考数据手册(这个在官方给的底层代码中.c文件有写,有空可以去看看,所以在这里只需要调用里面函数即可。)

要设定时间参数就要写进时间,因此把要写进去的时间参数也写成一个数组会比较方便

比如:注意写入顺序,秒——分——时——日——月——周——年

这里写成16进制时没有进行下一节(第四节)中讲的数据的转换,而是直接写成了16进制(已转换为为二进制的形式),这是因为若每四个单元都只是0~9,那么BCD和16进制(已转换为二进制的形式)是一样的,故直接写即可。

(3)调用函数来进行读取实时时间

调用以下两个函数(底层代码.c文件)可能有时候名称会有改变具体看你用的底层代码,传入数组的地址以及数据即可进行读取。


unsigned char Read_Ds1302_Byte ( unsigned char address ) 

void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) 

(注意:千万别漏了还有几个寄存器要单独写的,在执行函数中记得写!!)

4 DS1302读写数据时的转换 !!!!!!

这是个难点!

因为DS1302储存是按BCD来储存的,然后我们需要知道一个概念,就是单片机内的数据都是以0,1这两种形式储存(不论是二进制还是BCD等本质还是01),但是在计算时,单片机就直接默认以这些数据(不论是二进制数还是BCD等等)通通运用二进制的转换规则来转换成十进制,在编写代码进行运算时,就直接把这些数据看成是十进制数来进行运算公式的编写。

但是读取显示出来的数据是以16进制的数来表示的(这个就不要管,你在编写公式时就想着这是个十进制数来写公式转化就行了!!!!)

4.1 然后就要解释一下各种进制的转换关系:

(图源:BCD码以及各进制之间的相互转换-CSDN博客)

特别要说一下十六进制和BCD码的区别。

16进制其实就只有0~F这些单个数字,平时我们运算时的每四位作为一个单元,然后每个单元对应0~F这16个数,写成01形式后就是16进制转换为二进制后的结果(即16进制本身为单个数字,而写成每四个是已经转换为2进制的结果),为了不易弄混,其转化为十进制数记成先转成二进制数在以二进制数的方法转十进制(即2^0 * _+ 2^1 * _ +....)

而BCD码本身就是以每四个数字为一个单元,只是每个单元对应的只有0~9这十个数字,而每个单元作为十进制的一位,比如11,BCD码为0001 0001(前四个数转化为十进制是1,为十进制的十位数,后四个数转化为十进制是1,为十进制的个位数,)因此BCD码还要继续转换为二进制。(比如下图中10的表达,二进制是1010,而BCD是0001 0000)

(来源bcd码和16进制的区别_bcd和16进制的区别-CSDN博客)

但是,当四个为1个单元只表示0~9时,此时BCD和16进制(已转换为二进制的形式)是一样的,此时写入数据就可以直接用16进制表达,而不需要在进行转换。


所以可以看到,对于同一个十进制数,用BCD表达,十六进制表达二进制表达都是不一样的。

4.2 DS1302中的转换

在DS1302中数据是以BCD储存的,但是我们讲到在单片机运算时,单片机是默认运用二进制的转换规则来把这些0101形式转换为十进制来进行运算(无论是写入单片机还是读取的单片机的数据),那么在写入和读写数据时(通常只用16进制来表示写入和读写的数据),就要进行BCD码的转换。

(参考:DS1302内码和10进制二进制十六进制之间转换.doc (book118.com),图片来源也是这个文档。)

写入DS1302:

要写入一个十进制为45的数,如果直接把45写进单片机的DS1302,(前面说到,单片机默认是以转换二进制的规则来把二进制转十进制,或者十进制转二进制),那么单片机就会运用2进制规则转换45后储存起来,即等于0010 1101(2^5 * 1 + 2^3 *1 +2^2 * 1 + 2^0 * 1),但是DS1302又是以BCD码的形式储存的,0010 1101对应的BCD码是完全不存在的(因为1101对应>9了,而且单看前四位为2,说明十进制数的十位为2,也是不对的),因此,我们要进行数据的转换使得写进去的数最终表示为BCD码的形式转换回来十进制是我们想要的十进制数。简单说,我们想要45,但我们不能直接写45,我们要写69,这样单片机按2进制规则储存起来的就是0100 0101,按BCD方式转化为十进制就是我们想要的45。

以下例子的公式就是把所谓45转换为69的过程。

读取DS1302:

同样,当BCD存储为0100  0101,如果我们直接读取这个数据,出来的数对应十进制应该是69,因此,我们要把BCD码转换成45对应的二进制,再进行读取,最终显示的是以16进制来显示(转化为十进制是45)。

以下例子的公式就是把69转换为45的过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/578812.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【服务端】node.js详细的配置

👨‍💻个人主页:开发者-曼亿点 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 曼亿点 原创 👨‍💻 收录于专栏&#xff1a…

Centos JDK1.8 下载安装

https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html 一 RPM包安装 rpm -ivh jdk-8u391-linux-x64.rpm /etc/profile export JAVA_HOME/usr/java/jdk1.8.0-x64 export PATH$JAVA_HOME/bin:$PATHsource /etc/profile二 tar.gz 包手动…

k8s下搭建redis集群

记录一下近期实现的在k8s上搭建redis集群的过程 1、新建存储类 主要是为了和其它服务的存储类区分一下 redis-beta-storage 2、编写configMap redis启动时从configMap中读取配置 bind:默认的127.0.0.1可能会导致其它ip地址无法远程访问,因此修改为0.0…

【基于springboot分析Quartz(v2.3.2)的启动流程】

基于springboot分析Quartz(v2.3.2)的启动流程 最近公司的定时任务使用了Quartz框架,在开发中经常出现定任务不执行了的问题,但是我又找不到原因所在,可把我愁坏了。于是我决定看看Quartz框架是怎么调度任务的。&#x…

课时79:流程控制_循环控制_控制解析

1.4.1 控制解析 学习目标 这一节,我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 简介 所谓的流程控制,主要针对的是,当我们处于流程步骤执行的过程中,因为某些特殊的原因,不得不停止既定的操作进行步…

去除图像背景的工具(轻量级,批量式)

GitHub地址:danielgatis/rembg:Rembg 是一种去除图像背景的工具 (github.com) 博主在最近做一个比赛项目,然后数据用的是网上爬取的,所以数据有点脏,想清洗一下图像数据,恰好这次看到了个GitHub里面有开源去除背景的库,所以拿来用了,用了之后发现效果还是很不错的,…

更改chatglm认知

ChatGLM-Efficient-Tuning 下载源代码 下载ChatGLM-Efficient-Tuning 解压 创建虚拟环境 conda create --prefixD:\CondaEnvs\chatglm6btrain python3.10 cd D:\ChatGLM-Efficient-Tuning-main conda activate D:\CondaEnvs\chatglm6btrain安装所需要的包 pip install -r…

Arduino IDE导出esp8266工程编译后的bin文件

一、导出bin文件的方法一 1.通过IDE直接导出,选择 项目 --> 导出已编译的二进制文件,会在工程下生成 build 文件夹,里面有导出的bin文件。 一、导出bin文件的方法二 通过临时文件,找到生成的bin文件。 临时文件的位置&#…

VsCode正确解决vue3+Eslint+prettier+Vetur的配置冲突

手把手教你VsCode正确解决vue3EslintprettierVetur的配置冲突 VsCode正确解决vue3EslintprettierVetur的配置冲突Eslint文档查看和修改规则:step1:首先快速浏览下规则简要setp2: ctrlF 搜索你要配置规则的英文名,例如attributesetp3: 修改配置…

小程序UI设计规范,界面设计尺寸详解

作为互联网技术的重要组成部分,小程序在日常生活中发挥着越来越重要的作用。因此,了解和严格遵守小程序的 UI 设计标准非常重要,它不仅可以帮助我们在保证良好用户体验的同时优化小程序,还可以使我们的产品在竞争激烈的市场中占据…

Kubernetes-running app on kube

Docker 安装Docker 首先,您需要在Linux机器上安装Docker。如果您不使用Linux,则需要启动一个Linux虚拟机(VM)并在该虚拟机中运行Docker。如果你使用的是Mac或Windows系统,并按照指令安装Docker, Docker将为你建立一个虚拟机,并在…

速通汇编(二)汇编mov、addsub指令

一,mov指令 mov指令的全称是move,从字面上去理解,作用是移动(比较确切的说是复制)数据,mov指令可以有以下几种形式 无论哪种形式,都是把右边的值移动到左边 mov 寄存器,数据&#…