单片机第一季:零基础11——实时时钟DS1302

目录

1,DS1302 时钟芯片介绍 

2,BCD码介绍 

3,涉及到的寄存器 

3.1,控制寄存器

3.2,日历/时钟寄存器 

3.3,DS1302 的读写时序 

4,相关代码 


这一章我们来学习DS1302 时钟芯片,该芯片是3 线SPI 接口,所以需要使用51单片机的3 个IO 口模拟SPI 时序与DS1302 时钟芯片通信,将时钟日历数据读取出来。开发板上集成了1 个DS1302 时钟模块,可使用它设计一个多功能电子时钟。本章要实现的功能是:系统运行时,数码管上显示电子时钟时分秒,格式为“XX-XX-XX”。

1,DS1302 时钟芯片介绍 

DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:①RES复位②I/O 数据线③SCLK 串行时钟。时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信。DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW。 

DS1302 由DS1202 改进而来增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vcc1 为可编程涓流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域下面。 

主要的性能指标:
★ 实时时钟具有能计算2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力;
★ 31 个8 位暂存数据存储RAM;
★ 串行I/O 口方式使得管脚数量最少;
★ 宽范围工作电压2.0~5.5V;
★ 工作在2.0V 时,电流小于300nA;
★ 读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式;
★ 8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配;
★ 简单3 线接口;
★ 与TTL 兼容Vcc=5V;
★ 可选工业级温度范围-40~+85; 

1,VCC2:主电源引脚
2,X1、X2:DS1302 外部晶振引脚,通常需外接32.768K 晶振
3,GND:电源地
4,CE:使能引脚,也是复位引脚(新版本功能变)
5,I/O:串行数据引脚,数据输出或者输入都从这个引脚
6,SCLK:串行时钟引脚
7,VCC1:备用电源 

51单片机和DS1302芯片之间的通讯是SPI,SPI的主要特点:3线or4线、同步、主从、串行;

3线or4线: CE、I/O、SCLK,3线I/O是一根线,4线I/O是两根线;

同步:与UART的异步通讯相比,需要SCLK同步信息的发送和接收;

主从:谁来发出SCLK同步信号; 

串行:在数据线上按位传输数据; 

DS1302是变种SPI,通过SCLK和I/O相互配合,发送和接收信息。SCLK在上升沿前,主机通过I/O口发送数据,DS1302在上升沿是接收;SCLK在下降沿后,DS1302通过I/O口发送数据,主机接收。

 SPI:SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。

DS1302参考: 

DS1302介绍

2,BCD码介绍 

为什么要介绍BCD码?因为从DS1302芯片读出来的数据是BCD 码形式,当使用串口助手查看数据时看到的是十进制形式,但其本质上是十六进制数据。

BCD码是一种数字编码,这种计数编码有个特点:很像10进制和16进制的结合。看起来很像10进制(29下来是30而不是2A),BCD码实际是用十六进制来表示的(BCD码的21其实在计算机中就是0x21)。BCD码中只有0-9,而没有ABCDEF等字目。 

综合来讲:BCD码其实就是看起来很像十进制数的十六进制数。意思就是:BCD码本质上是十六进制数,但是因为他没有ABCDEF,所以看起来很像十进制数。 

DS1302使用BCD码来处理时间信息,对单片机来说是16进制方便单片机处理,对人来说可以认为是10进制,同时方便单片机和人来识别信息。

例如:

如果把一个数21分成两个数,对于十进制的21,需要通过21/10得到2,通过21%10得到1; 

对于十六进制的21,分成两个数,通过0x21>>4的得到2 ,通过0x21&0x0F得到1;

对于计算机来说,移位和与操作的复杂度优于除和取余。 

3,涉及到的寄存器 

操作DS1302 的大致过程,就是将各种数据写入DS1302 的寄存器,以设置它当前的时间的格式。然后使DS1302 开始运作,DS1302 时钟会按照设置情况运转,再用单片机将其寄存器内的数据读出。 

3.1,控制寄存器

控制寄存器用于存放DS1302 的控制命令字,DS1302 的RST 引脚回到高电平后写入的第一个字节就为控制命令。它用于对DS1302 读写过程进行控制,格式如下: 

上图是DS1302 的寄存器样式,我们看到:
1、第7 位永远都是1;
2、第6 位,1 表示RAM,寻址内部存储器地址;0 表示CK,寻址内部寄存器;

3、第5 到第1 位,为RAM 或者寄存器的地址;
4、最低位,高电平表示RD,即下一步操作将要“读”;低电平表示W,即下一步操作将要“写”。

比如要读秒寄存器则命令为1000 0001,反之写为1000 0000,要注意其含义。 

3.2,日历/时钟寄存器 

DS1302 共有12 个寄存器,其中有7 个与日历、时钟相关,存放的数据为BCD码形式 。

秒寄存器:低四位为秒的个位,高的次三位为秒的十位。最高位CH 为DS1302 的运行标志,当CH=0 时,DS1302 内部时钟运行,反之CH=1 时停止; 

小时寄存器:时寄存器。最高位为12/24 小时的格式选择位,该位为1 时表示12 小时格式。当设置为12 小时显示格式时,第5 位的高电平表示下午(PM);而当设置为24 小时格式时,第5 位位具体的时间数据。 

写保护寄存器:当该寄存器最高位WP 为1 时,DS1302 只读不写,所以要在往DS1302 写数据之前确保WP 为0。 

慢充电寄存器(涓细电流充电)寄存器:我们知道,当DS1302 掉电时,可以马上调用外部电源保护时间数据。该寄存器就是配置备用电源的充电选项的。其中高四位(4 个TCS)只有在1010 的情况下才能使用充电选项;低四位的情况与DS1302 内部电路有关。

思考:日历/时钟寄存器中还存储了除了时间数据之外的其它数据,这些数据在读写时是如何操作的? 

3.3,DS1302 的读写时序 

在控制指令字输入后的下一个SCLK 时钟的上升沿时,数据被写入DS1302,数据输入从低位(位0)开始。同样,在紧跟8 位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302 的数据,读出数据时从低位0 位到高位7。其时序图如下所示: 

上图就是DS1302 的三个时序:复位时序,单字节写时序,单字节读时序;CE(RST):复位时序,即在RST 引脚产生一个正脉冲,在整个读写器件,RST 要保持高电平,一次字节读写完毕之后,要注意把RST 返回低电平准备下次读写周期;

单字节读时序:注意读之前还是要先对寄存器写命令,从最低位开始写;可以看到,写数据是在SCLK 的上升沿实现,而读数据在SCLK 的下降沿实现。所以,在单字节读时序中,写命令的第八个上升沿结束后紧接着的第八个下降沿就将要读寄存器的第一位数据读到数据线上了!这个就是DS1302 操作中最特别的地方。当然读出来的数据也是最低位开始。 

单字节写时序:两个字节的数据配合16 个上升沿将数据写入即可。 

程序注意事项:
★要记得在操作DS1302 之前关闭写保护;
★注意用延时来降低单片机的速度以配合器件时序;

★DS1302 读出来的数据是BCD 码形式,要转换成我们习惯的10 进制,转换
方法在源程序里;
★读取字节之前,将IO 设置为输入口,读取完之后,要将其改回输出口;
★在写程序的时候,建议实现开辟数组(内存空间)来集中放置DS1302 的
一系列数据,方便以后扩展键盘输入。 

4,相关代码 

ds1302底层时序代码,分为ds1320.c和ds1302.h两个文件:

 ds1302.h

#ifndef  __DS1302_H__
#define  __DS1302_H__//从ds1302的内部寄存器addr写入一个值value
void ds1302_write_reg(unsigned char addr, unsigned char value);
//从ds1302的内部寄存器addr读出一个值,作为返回值
unsigned char ds1302_read_reg(unsigned char addr);#endif

ds1320.c

#include "ds1302.h"#include <reg51.h>sbit DSIO	= P3^4;
sbit RST	= P3^5;
sbit SCLK	= P3^6;void delay(void)
{unsigned char i;for (i=0; i<3; i++);
}//从ds1302的内部寄存器addr写入一个值value
void ds1302_write_reg(unsigned char addr, unsigned char value)
{unsigned char i,dat;//第一部分:时序初始化RST = 0;delay();SCLK = 0;delay();RST = 1;delay();//第二部分:写入地址for(i=0; i<8; i++){dat = addr & 0x01; //取地址的低位DSIO = dat;addr >>=1;SCLK = 1;		  //创造一个上升沿,让ds1302将信号线上的值读走delay();SCLK = 0;}//第三步:写入数据for(i=0; i<8;i++){dat = value & 0x01; //取数据的低位DSIO = dat;value >>=1;SCLK = 1;		  //创造一个上升沿,让ds1302将信号线上的值读走delay();SCLK = 0;		}//第四部分:时序结束RST = 0;delay();SCLK = 0;delay();}// 从ds1302的内部寄存器addr读出一个值,作为返回值
unsigned char ds1302_read_reg(unsigned char addr)
{unsigned char i = 0;unsigned char dat = 0; 		// 用来存储读取到的一字节数据的unsigned char tmp = 0;// 第1部分: 时序起始SCLK = 0;delay();RST = 0;delay();RST = 1;  		// SCLK为低时,RST由低变高,意味着一个大的周期的开始delay();// 第2部分: 写入要读取的寄存器地址,addrfor (i=0; i<8; i++){dat = addr & 0x01;	 	// SPI是从低位开始传输的DSIO = dat;	 			// 把要发送的bit数据丢到IO引脚上去准备好SCLK = 1;		 		// 制造上升沿,让DS1302把IO上的值读走delay();				// 读走之后,一个小周期就完了SCLK = 0;				// 把SCLK拉低,是为了给下一个小周期做准备delay();addr >>= 1;	   			// 把addr右移一位}// 第3部分: 读出一字节DS1302返回给我们的值dat = 0;for (i=0; i<8; i++){// 在前面向ds1302写入addr的最后一个bit后,ds1302就会将读取到的寄存器值// 的第一个bit放入到IO引脚上,所以我们应该先读取IO再制造下降沿然后继续// 读取下一个bittmp = DSIO;dat |= (tmp << i);		// 读出来的数值是低位在前的SCLK = 1;  				// 由于上面SCLK是低,所以要先拉到高delay();SCLK = 0;				// 拉低SCLK制造一个下降沿delay();}// 第4部分: 时序结束SCLK = 0;				  	// SCLK拉低为了后面的周期时初始状态是对的delay();RST = 0;					// RST拉低意味着一个大周期的结束delay();// 第5部分:解决读取时间是ff的问题DSIO = 0;return dat;
}

通过串口接收时钟数据,分为uart.c和uart.h两个文件:

 uart.h

#ifndef __UART_H__
#define __UART_H__//串口初始化
void uart_init();
//串口发送数据
void uart_send_byte(unsigned char c);#endif

uart.c

#include "uart.h"
#include <reg51.h>void uart_init()
{TMOD|=0X20; //设置计数器工作方式2SCON=0X50; //设置为工作方式1PCON=0X80; //波特率加倍TH1=0xFA; //计数器初始值设置TL1=0xFA;ES=1; //打开接收中断EA=1; //打开总中断TR1=1; //打开计数器
}void uart_send_byte(unsigned char c)
{// 第1步,发送一个字节SBUF = c;// 第2步,先确认串口发送部分没有在忙while (!TI);// 第3步,软件复位TI标志位TI = 0;
}

main函数:

包括ds1302的上层时序,读出时钟数据和写入时钟数据,以及调用uart函数。

#include <reg51.h>
#include <intrins.h>#include "ds1302.h"
#include "uart.h"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};
unsigned char time[7]={0};void delay1s(void)   //误差 0us
{unsigned char a,b,c;for(c=167;c>0;c--)for(b=171;b>0;b--)for(a=16;a>0;a--);_nop_();  //if Keil,require use intrins.h
}void ds1302_read_time(void)
{unsigned char i = 0;for (i=0; i<7; i++){time[i] = ds1302_read_reg(READ_RTC_ADDR[i]);}
}void ds1302_write_time(void)
{unsigned char i = 0;// 准备好要写入的时间time[0] = 0x24;				// 对应 24stime[1] = 0x39;				// 对应 39mtime[2] = 0x11;				// 对应 11htime[3] = 0x06;				// 对应 6日time[4] = 0x12;				// 对应 12月time[5] = 0x02;				// 对应 星期2time[6] = 0x16;				// 对应 2016年ds1302_write_reg(0x8E, 0x00);	// 去掉写保护for (i=0; i<7; i++){ds1302_write_reg(WRITE_RTC_ADDR[i], time[i]);}ds1302_write_reg(0x8E, 0x80);	// 打开写保护
}void main()
{uart_init();ds1302_write_time();while(1){int i = 0;ds1302_read_time();for(i=0;i<7;i++) {uart_send_byte(time[i]);}delay1s();}}

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

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

相关文章

测牛学堂:软件测试之andorid app性能测试面试知识点总结(二)

APP性能测试指标之FPS 如果经常玩游戏的同学应该听过FPS。 FPS本来是图像领域中的概念&#xff0c;是指画面每秒传输的帧数。每秒钟帧数越多&#xff0c;所显示的动作就会越流畅。 但是因为功耗的限制&#xff0c;一般60fps就是跑满的效果了。 我们测试的话&#xff0c;一般…

如何在Windows上恢复已删除的文件?

大多数人在无意中删除了一些重要文件后无法恢复。这些文件被暂时删除&#xff0c;直到我们清空回收站才会消失。你可以通过右键单击回收站中的文件并选择还原选项来轻松恢复这些文件。但是&#xff0c;如果你清理回收站删除了文件怎么办&#xff1f;或者不小心使用Shift Delet…

Pytorch nn.Linear的基本用法与原理详解

1. 参考 Pytorch nn.Linear的基本用法与原理详解_iioSnail的博客-CSDN博客 [机器学习]深度学习初学者大疑问之nn.Linear(a,b)到底代表什么?_五阿哥爱跳舞的博客-CSDN博客

Rola-IP系统崩溃怎么办?亚马逊、沃尔玛、速卖通等测评该如何应对?(详解篇)

近期做测评的卖家遇到了一个大问题&#xff0c;罗拉IP&#xff08;rola-ip&#xff09;的突然关闭&#xff0c;给用户带来了诸多不便&#xff0c;这种跑路行为让用户损失惨重。身为IP提供商&#xff0c;跑路不仅伤害了用户的信任&#xff0c;也影响了用户的项目和工作。 许多用…

观察者模式(java)

目录 结构 案例 代码实现 抽象观察者 抽象主题类 具体观察者 具体主题类 测试类 优缺点 优点 缺点 结构 在观察者模式中有如下角色&#xff1a; Subject&#xff1a;抽象主题&#xff08;抽象被观察者&#xff09;&#xff0c;抽象主题角色把所有观察者对象保存在一个…

Mysql数据库用户操作

# Mysql数据库用户操作 ## 1.1创建用户 shell create user ‘nz’ identified by ‘123456’ # hzm&#xff1a;用户账号&#xff0c;123456&#xff1a;密码 create user ‘nz’’%’ identified by ‘123456’ #所有ip都可用账号 create user ‘nz’’localhost’ identifi…

zabbix通过JMX监控tomcat运行情况

第三阶段基础 时 间&#xff1a;2023年7月20日 参加人&#xff1a;全班人员 内 容&#xff1a; zabbix通过JMX监控tomcat 目录 zabbix通过JMX监控tomcat 一、配置java网关 二、修改zabbix服务端配置文件 三、安装tomcat 四、Zabbix-web端配置 zabbix通过JMX监控tomc…

苹果11手机设置手机跟踪功能

苹果11手机设置手机跟踪功能&#xff0c;就算是手机丢了&#xff0c;也能通过查询手机定位在哪里。 第一步&#xff1a;点击Apple ID进入详情 第二步&#xff1a;点击“查找” 第三步&#xff1a; 第四步&#xff1a; 到了这步&#xff0c;就算是设置成功。 下面需要到官方查询…

初步认识Linux系统编程

Linux是一种自由和开放源代码的操作系统&#xff0c;它以良好的稳定性、强大的安全性和广泛的应用领域而著称。Linux系统编程是指在Linux操作系统下开发应用程序的过程&#xff0c;其中包括与硬件交互、系统调用以及与其他程序进行通信等。 文章目录 学习Linux系统编程前的准备…

04. Idea集成Docker

目录 1、前言 2、开启docker远程 2.1、配置远程访问模式 2.2、重启docker服务 2.3、验证 3、Idea配置Docker 3.1、配置证书登录 4、创建Dockerfile 4.1、编写Dockerfile 4.2、配置启动项 4.3、访问接口 1、前言 上一节中&#xff0c;我们介绍了Dockerfile的方式构建…

Mac电脑必备:3款优质系统软件推荐

对于Mac电脑使用者来说&#xff0c;良好的系统软件是确保计算机高效运行和提升使用者体验的关键。无论是日常办公、娱乐还是创意设计&#xff0c;一系列优质的系统软件都能为使用者带来更顺畅、更便捷的操作体验。在本文中&#xff0c;我们将推荐3款在Mac电脑上必备的优质系统软…

数据结构之优先级队列(堆)

文章目录 1.优先级队列概念 &#x1f4ae;2.优先级队列的模拟实现&#x1f4ae;3.常用接口PrinrityQueue介绍&#x1f4ae;4.堆的应用&#x1f4ae; 1.优先级队列概念 &#x1f4ae; 优先级队列 &#xff1a;是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优…

qt采用C++/CLI 方式调用C#dll的封装方法

在qt中调用Cdll一般都可以直接使用&#xff0c;但是在调用C#版dll时&#xff0c;就有些麻烦了。本文采用C/cli封装C#的dll的方式。实现了qt调用C#dll的方法。 .h文件 #pragma once #include <string> //stl库 #include <vector> // stl中vector库//dll生成文件定…

CAD中让时间日期自动填写的方法

图纸的图签中&#xff0c;通常会有一栏是出图日期。有的单位&#xff0c;也会叫做版本号。即哪天出的图。一般情况下&#xff0c;出图日期就是打图当天。 在这样的前期下&#xff0c;图纸由于存在频繁修改&#xff0c;所以出图日期也会存在变化。还有一种情况&#xff0c;就是出…

linux 用户鉴权文件学习

一、 /etc/sudoers /etc/sudoers用于管理 Linux 系统上特权操作的访问控制列表&#xff08;ACL&#xff09;。该文件指定了哪些用户、组或主机可以执行特权命令&#xff0c;以及他们可以执行哪些命令。 # sudoers file. # # This file MUST be edited with the visudo comman…

Docker Compose 实现单机容器集群编排管理

目录 Docker ComposeDocker Compose 三大概念1. Docker Compose 环境安装2. YAML 文件格式及编写注意事项3. Docker Compose配置restart 设置重启策略&#xff0c;no&#xff0c;always&#xff0c;no-failure&#xff0c;unless-stopped 4. Docker Compose 常用命令选项5. Doc…

基础算法-数组模拟栈

栈&#xff1a;先进后出 队列&#xff1a;先进先出 栈 例题&#xff1a; 实现一个栈&#xff0c;栈初始为空&#xff0c;支持四种操作&#xff1a; push x – 向栈顶插入一个数 x&#xff1b;pop – 从栈顶弹出一个数&#xff1b;empty – 判断栈是否为空&#xff1b;query …

mysql实现in且模糊匹配、实现 in( like xxx ) 效果

问题 删除某表涉及到指定任务id的数据&#xff0c;没有直接关联字段&#xff0c;只有在某表的body字段中存储有含任务id的json串&#xff0c;所以需要批量模糊匹配 用到的函数 REGEXP 可以实现模糊匹配多个值 select * from xxx where body like %"taskId":1% or…

CPU渲染or GPU渲染,你选对了吗?看完这六点就懂了!

在进行动画或效果图渲染时&#xff0c;选择适合的渲染方式对于项目的速度和质量至关重要。CPU渲染和GPU渲染作为两种主要的渲染方式&#xff0c;哪一种更适合你现在的情况&#xff1f;接下来我将从以下六个方面带大家深入了解&#xff0c;看完就知道怎么选了。 1.渲染原理 CPU…