单片机学习笔记---DS1302时钟

上一节我们讲了DS1302的工作原理,这一节我们开始代码演示。

新创建一个工程写上框架

单片机学习笔记---DS1302时钟_第1张图片

我们需要LCD1602进行显示,所以我们要将LCD1602调试工具那一节的LCD1602的模块化代码给添加进来

单片机学习笔记---DS1302时钟_第2张图片

然后我们开始创建一个DS1302.c和DS1302.h

单片机学习笔记---DS1302时钟_第3张图片

根据原理图,为了方便操作,我们要在DS1302.c文件重新定义我们的三个端口

单片机学习笔记---DS1302时钟_第4张图片

单片机学习笔记---DS1302时钟_第5张图片

定义好之后我们操作重命名的名字,就相当于操作单片机的这三个引脚。

然后我们就可以根据上节讲的工作原理模拟这个时序

单片机学习笔记---DS1302时钟_第6张图片

首先我们要写一个函数,叫做单字节写DS1302,模拟这个时序

单片机学习笔记---DS1302时钟_第7张图片

单片机学习笔记---DS1302时钟_第8张图片

第二个函数是单字节读DS1302,模拟这个时序

单片机学习笔记---DS1302时钟_第9张图片

单片机学习笔记---DS1302时钟_第10张图片

然后初始化DS1302

单片机学习笔记---DS1302时钟_第11张图片

开始写字节,第一步将CE置1

单片机学习笔记---DS1302时钟_第12张图片

下一步把命令字的第0位放在IO线上

单片机学习笔记---DS1302时钟_第13张图片

然后DS1302_SCLK置1再置0

单片机学习笔记---DS1302时钟_第14张图片

单片机学习笔记---DS1302时钟_第15张图片

这里置1后立马置0的话需要考虑我们芯片能够承受的时钟最快频率,因为置1后立马置0的过程中,可能时钟线操作的太快,而时钟芯片反应不过来。

所以要看看芯片手册上支持的最快速率是多少。

比如手册上给出了这个时序上每一段的操作时间表格

单片机学习笔记---DS1302时钟_第16张图片

还画了图表示哪里到哪里对应的是表格中的哪一个时间

单片机学习笔记---DS1302时钟_第17张图片

比如说tDC对应的是当VCC是2V的时候,操作时间最小不能小过200ns,如果VCC是5V的时候,时间最小是50ns。

但是由于我们51单片机的速率是比较慢的(一个机器周期是1微秒),所以置1到置0之间可以不用加延时。如果有的单片机的速度很快的话,置1到置0之间要加一段延时,等IO后完成数据交互之后再置0。

经过以上三步后我们的时序已经走完到这一步了

单片机学习笔记---DS1302时钟_第18张图片

接下来我们接着写入命令字的第1位,第2位,第3位......数据(保持CE=1)

我们可以用for循环来实现

单片机学习笔记---DS1302时钟_第19张图片

更正:图中应该是i<8

这个循环完成后整个时序就进行到这个地方

单片机学习笔记---DS1302时钟_第20张图片

最后那一半时序其实和前面一半的时序操作几乎一模一样,只是它的数据不同

可以直接复制过来改一下

单片机学习笔记---DS1302时钟_第21张图片

更正:图中应该是i<8

这个循环完成后我们时序已经完成到这里了

单片机学习笔记---DS1302时钟_第22张图片

最后就是把CE给清零

单片机学习笔记---DS1302时钟_第23张图片

更正:图中应该是i<8

这样单字节写的这整个时序就已经完成了。

数据写进去后,我们还要让单片机读出来,最后再显示出来才能看到我们写进去的数据。

接下来我们就操作单字节读的时序

单片机学习笔记---DS1302时钟_第24张图片

操作命令字部分的时序几乎一样,可以直接复制过来

单片机学习笔记---DS1302时钟_第25张图片

更正:图中应该是i<8

这样整个时序就进行到这里了

单片机学习笔记---DS1302时钟_第26张图片

但是这里有个问题当时钟来一个下降沿的时候,时钟芯片就会向单片机输出数据了,这就意味着如果我们直接这样写的话,那进行到最后一轮for循环的时候就同时有一位数据出来了,我们应该想要时序进行到这一步才对

单片机学习笔记---DS1302时钟_第27张图片

所以得调整一下顺序,先给0,再给1

单片机学习笔记---DS1302时钟_第28张图片

更正:图中应该是i<8

这样当第一个for循环结束后,时序就不是到这里来了

单片机学习笔记---DS1302时钟_第29张图片

而是到这里来了

单片机学习笔记---DS1302时钟_第30张图片

最后一个for循环结束后就到这里来了

单片机学习笔记---DS1302时钟_第31张图片

这样我们这个for循环就全部是与命令字有关的,

当这一部分时序进行完之后,这里单片机就要释放掉对IO口的控制,然后把IO口的控制权转交给DS1302。DS1302输出数据,然后单片机在这里直接读取IO口的状态。

因此接下来先给下降沿

单片机学习笔记---DS1302时钟_第32张图片

更正:图中应该是i<8

那么数据就已经到了IO口的线上了,所以我们直接读

所以我们再给一个上升沿

单片机学习笔记---DS1302时钟_第33张图片

更正:图中应该是i<8

这个时候时序就进行到这里了

单片机学习笔记---DS1302时钟_第34张图片

这个时候DS1302操作IO口把它想要输出的数据的D0给到IO口线上了。

然后先定义一个变量Data,然后进行循环读出数据的每一位

单片机学习笔记---DS1302时钟_第35张图片

这样就和这个时序完全相同了

PS:连续两次置1时序上的电平不会产生变化,并且单字节读的时序比单字节写的时序少了一个脉冲,那么我们这个地方重复置了一个1的话可以补充少了的这个脉冲。

单片机学习笔记---DS1302时钟_第36张图片

最后别忘记CE清零

单片机学习笔记---DS1302时钟_第37张图片

把Data返回(到时候主程序里面调用这个函数的话,返回值就可以打印出来了)

返回值类型也要改

单片机学习笔记---DS1302时钟_第38张图片

这里有一个重点!敲黑板!重点来了!

读取完数据时候一定要给IO口清零!!!

单片机学习笔记---DS1302时钟_第39张图片

如果不写上这一句代码的话效果是这样的,请看视频,读出来的数据是乱码的!

DS1302实时时钟2

这样读和写的两个时序已经模拟完成,我们需要再DS1302.h文件里面进行声明一下这几个函数

单片机学习笔记---DS1302时钟_第40张图片

到这里我们的读写程序基本已经完成了

BCD码

然后还需要补充一个知识:BCD码

DS1302的内部寄存器不是以正常的二进制进行存储的,而是以BCD码进行存储的。

BCD码(Binary Coded Decimal‎),用4位二进制数来表示1位十进制数

高四位表示十进制的十位,低四位表示十进制的个位

例:0001 0011表示13,1000 0101表示85,0001 1010不合法

在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法

(10的BCD码是0001 0000,转换成正常的十进制是16)

BCD码转十进制:DEC=BCD/16(把高四位提取出来)*10+BCD%16(把低四位提取出来); (2位BCD)

十进制转BCD码:BCD=DEC/10(得到十位)*16+DEC%10(得到个位); (2位BCD)

所以我们回头这一下这张表格就能看明白了

单片机学习笔记---DS1302时钟_第41张图片

以秒寄存器为例,这张表格上写明低四位存的是秒,而高位的那三位(0-50就只能用到三位(0)101)存的是10秒,CH置为1的话,秒就会停止,整个时钟就会停止。CH=0的话时钟时钟是运行的。

单片机学习笔记---DS1302时钟_第42张图片

所以想要最后的结果显示成正常的十进制数的话就要将结果转换成十进制再显示。

如果还是想转换成十进制再显示的话可以利用这一个转换公式

BCD码转十进制:DEC=BCD/16(把高四位提取出来)*10+BCD%16(把低四位提取出来); (2位BCD)

设置时间时,要将十进制转换成BCD码写进时钟芯片,可以利用这个公式

十进制转BCD码:BCD=DEC/10(得到十位)*16+DEC%10(得到个位); (2位BCD)

我们要将年月日,时分秒,星期显示在液晶屏上的话还要在DS1302.c文件中定义是个数组,然后再写两个函数,方便我们后续设置时间

单片机学习笔记---DS1302时钟_第43张图片

单片机学习笔记---DS1302时钟_第44张图片

为了方便后面不用每次都查找这个表上的地址码

单片机学习笔记---DS1302时钟_第45张图片

我们可以把这个表格上的写入地址重定义

单片机学习笔记---DS1302时钟_第46张图片

然后我们知道,写入时的命令字最低位肯定是0,读出时的命令字最低位肯定是1

单片机学习笔记---DS1302时钟_第47张图片

所以我们在ReadByte()这里加一行这样的代码

单片机学习笔记---DS1302时钟_第48张图片

因为这个读的命令字一定是1了,将Command或0x01之后,那它的最低位肯定是1,也就是肯定是读,然后我们给地址的时候,可以直接给写的地址,因为写的地址或了0x01之后就是读的地址,这样我们就不需要重复定义那么多地址了。因此我们就不需要把读的地址也弄成这样了

单片机学习笔记---DS1302时钟_第49张图片

要想获得读的地址就直接将写的这个地址|0x01就变成读的地址了!

于是两个函数写完之后是这样

单片机学习笔记---DS1302时钟_第50张图片

单片机学习笔记---DS1302时钟_第51张图片

将这两个函数和数组都声明一下

单片机学习笔记---DS1302时钟_第52张图片

最后DS1302.c的完整代码如下:

单片机学习笔记---DS1302时钟_第53张图片

单片机学习笔记---DS1302时钟_第54张图片

单片机学习笔记---DS1302时钟_第55张图片

单片机学习笔记---DS1302时钟_第56张图片

单片机学习笔记---DS1302时钟_第57张图片

最后我们在主程序中调用函数然后运行

单片机学习笔记---DS1302时钟_第58张图片

单片机学习笔记---DS1302时钟_第59张图片

运行后的效果,请看视频:

DS1302实时时钟1

本节的代码演示就到这里。

之后有时间再演示一个可调时钟的代码!

源码放在评论区,自取!有什么问题,可以评论区留言。

你可能感兴趣的:(51单片机学习笔记,单片机,学习,笔记,51单片机,物联网,mcu,嵌入式硬件)