51单片机入门:DS1302时钟

51单片机内部含有晶振,可以实现定时/计数功能。但是其缺点有:精度往往不高、不能掉电使用等。 我们可以通过DS1302时钟芯片来解决以上的缺点。


DS1302时钟芯片

功能:DS1302是一种低功耗实时时钟芯片,内部有自动的计时功能,其范围包括:年、月、日、时、分、秒、星期。(且每个月的天数和闰年的天数可以内部自动调整)。

结构以及引脚定义

常见的DS1302时钟芯片有DIP(直插式)和SO(表贴式)两种封装 。

引脚定义
引脚名称功能
X1、X2DS1302外部晶振引脚,通常接32.768K晶振
VCC1备用电源,在主电源使用时可被充电
VCC2主电源供应管脚(与单片机共用一个电源)
GND电源地
CE使能端,也是复位引脚,在进行读写时CE要保持高电平
I/O串行数据输入或输出
SCLK串行时钟

通常通过单片机直接与CE、I/O、SCLK这3个引脚相连,控制其高低电平,进而控制DS1302时钟芯片。

DS1302电路图

其中,C2和C3为旁路电容,目的是消除晶振起振时产生的电感干扰。对于此电路,没有接入备用电池,可自行将外部备用电源接入VCC1。


 DS1302内部寄存器

控制寄存器

功能:通过给控制寄存器数据,来决定:进入年月日等具体哪一个寄存器、进行读/写操作。

 上图为控制寄存器样式。

最高位一直为1;

第6位:1表示RAM,寻址内部存储器;0为CK,寻址内部寄存器。

第5位~第1位:为年月日等日历寄存器的地址。

最低位:1表示下一步操作为“读”;0表示下一步操作为“写”。

日历/时钟寄存器

上图为年月日等相关寄存器的地址(绿框内)、功能等。以下对其进行详细说明:

相关寄存器的位说明
寄存器名称取值范围D7D6D5D4D3D2D1D0
秒寄存器00~59CH秒的十位秒的个位
分寄存器00~590分的十位分的个位
小时寄存器

1~12或

00~23

12小时制/

24小时制

0AM/PMHour小时的个位
日寄存器01~3100日的十位日的个位
月寄存器01~120001或0月的个位
星期寄存器01~070000星期几
年寄存器01~9920XX年的十位年的个位
写保护寄存器WP0000000

需特别注意以下部分:

秒寄存器:CH为DS1302的运行标志,当CH=0时,DS1302内部才能工作;当CH=1时,DS1302停止工作。

写保护寄存器:当WP为1时,DS1302只读不写。所以进行写操作时要确保WP为0。


 DS1302初始时间设置

举个例子,如果想将2024.05.04—周7—23:59:49这个时间写入DS1302内部,具体操作如下:

1、对0x8E地址操作,关闭写保护;

2、对秒寄存器0x80操作,写入0x49;

3、对分寄存器0x82操作,写入0x59;

4、对时寄存器0x84操作,写入0x23;

......以此类推,最后对0x8E地址操作,打开写保护。

BCD码

BCD码:用4位二进制数来表示1位十进制数。

例如:0001 0011表示13、1000 0101表示85、0001 1010不合法。

日历/时钟寄存器内部都是以BCD码来存放数据。因此要设置DS1302的时间,要写入BCD码格式。同时读取数据时,读到的也是BCD码,使用时需转换为对应十进制。

0000050101
1000160110
2001070111
3001181000
4010091001

 转换公式:

读写时序

前面提到:单片机与DS1302相连的线有3根,分别为:CE、SCLK和I/O引脚;如何通过这3根线进行数据写入和读出呢?

CE:初始化使其为低电平,在整个读写过程中,要保持高电平;一次读写操作完毕后,再回到低电平。

//  功能:DS1302初始化
void DS1302_Init(){DS1302_CE=0;    //使能端置0DS1302_SCLK=0;  //时钟脉冲置0
}

单字节写入:(先关闭写保护)当CE为高电平时,通过单片机控制SCLK产生脉冲,每一个上升沿,I/O线的数据就进入控制寄存器;当控制寄存器配置完成后,紧接着的I/O线数据会在上升沿时进入对应地址的寄存器。

/***@breaf DS1302单字节写入函数*@param command:写入命令字,包含要写入寄存器的地址;*@param Data:将要写入的数据内容;*@retval 无*/
void  DS1302_WriteBety(unsigned char command,Data)
{unsigned char i;DS1302_CE=1;//使能位置高电平;//设置控制寄存器for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入{DS1302_IO=command&(0x01<<i);DS1302_SCLK=1;  //给一个上升沿DS1302_SCLK=0;}//设置相关年月日寄存器for(i=0;i<8;i++)//数据写入{DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}DS1302_CE=0;	
}

单字节读出:当CE为高电平时,通过单片机控制SCLK产生脉冲,每一个上升沿,I/O线的数据就进入控制寄存器;当控制寄存器配置完成后,紧接着对应地址的寄存器数据会在下降沿时进入I/O线。

/***@breaf  DS1302单字节读出函数*@param command:写入控制指令的指令,包含要读出寄存器的地址;*@retval Data:读出的数据;*/
unsigned char   DS1302_ReadBety(unsigned char command)
{unsigned i,Data=0X00;command|=0X01;//写入指令与读出指令只在最后一位相差1,故在此利用或运算消除;DS1302_CE=1;//使能位置高电平;for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入{DS1302_IO=command&(0x01<<i);DS1302_SCLK=0;	DS1302_SCLK=1;}DS1302_IO=0;for(i=0;i<8;i++)//数据读出{DS1302_SCLK=1;DS1302_SCLK=0;			if(DS1302_IO)  {Data |=(0X01<<i);}}DS1302_CE=0;return Data;
}

注意数据输入从低位开始。


代码设计

main.c

#include <REGX52.H>
#include "lcd1602.h"//包含LCD1602头文件
#include "DS1302.h"//包含DS1302头文件
void main ()//定义主函数
{LCD_Init();	//LCD1602初始化DS1302_Init();//DS1302初始化LCD_ShowString(1,1,"  -  -  ");//设置年月日格式LCD_ShowString(2,1,"  :  :  ");//设置时分秒格式DS1302_SetTime();//设置时间,通过数组进行设置while(1){DS1302_ReadTime();//读取内部时间LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒LCD_ShowNum(2,13,DS1302_Time[6], 1);//显示星期}
}

DS1302.c

#include <REGX52.H>//引脚定义;
sbit  DS1302_SCLK=P3^6;
sbit  DS1302_IO=P3^4;
sbit  DS1302_CE=P3^5;//对应寄存器位置定义
#define  DS1302_SECOND		0X80
#define  DS1302_MINUTE  	0X82
#define  DS1302_HOUR		0X84
#define  DS1302_DATE        0X86
#define  DS1302_MONTH		0X88
#define  DS1302_DAY         0X8A
#define  DS1302_YEAR        0X8C
#define  DS1302_WP          0X8E //定义数组,用于存放设定的时间,年月日时分秒星期
unsigned char DS1302_Time[]={23,10, 28,19,00,59,6};//顺序:年月日时分秒星期
/***@breaf DS1302初始化*@param无*@retval无*/
void  DS1302_Init()
{DS1302_CE=0;//将使能位置0,低电平;DS1302_SCLK=0;//将时钟位置0,低电平;
}/***@breaf DS1302单字节写入函数*@param command:写入控制指令的指令,包含要写入寄存器的地址;*@param Data:将要写入的数据内容;*@retval 无*/
void  DS1302_WriteBety(unsigned char command,Data)
{unsigned char i;DS1302_CE=1;//使能位置高电平;for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入{DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;DS1302_SCLK=1;DS1302_SCLK=0;}for(i=0;i<8;i++)//数据写入{DS1302_IO=Data&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;DS1302_SCLK=1;DS1302_SCLK=0;}DS1302_CE=0;	
}/***@breaf  DS1302单字节读出函数*@param command:写入控制指令的指令,包含要读出寄存器的地址;*@retval Data:读出的数据;*/
unsigned char   DS1302_ReadBety(unsigned char command)
{unsigned i,Data=0X00;command|=0X01;//写入指令与读出指令只在最后一位相差1,故在此利用或运算消除;DS1302_CE=1;//使能位置高电平;for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入{DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;DS1302_SCLK=0;	DS1302_SCLK=1;}DS1302_IO=0;for(i=0;i<8;i++)//数据读出{DS1302_SCLK=1;DS1302_SCLK=0;			if(DS1302_IO)  {Data |=(0X01<<i);}}DS1302_CE=0;return Data;
}/***@breaf 向DS1302内设定时间*@param无*@retval无*/
void DS1302_SetTime()
{DS1302_WriteBety(DS1302_WP,0x00);//操作 DS1302 之前,关闭写保护,不然指令无法进入控制寄存器;DS1302_WriteBety(DS1302_YEAR, DS1302_Time[0]/10*16+DS1302_Time[0]%10);//写入年,并将10进制转化BCD码;DS1302_WriteBety(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10);//写入月,并将10进制转化BCD码;DS1302_WriteBety(DS1302_DATE, DS1302_Time[2]/10*16+DS1302_Time[2]%10);//写入日,并将10进制转化BCD码;DS1302_WriteBety(DS1302_HOUR, DS1302_Time[3]/10*16+DS1302_Time[3]%10);//写入时,并将10进制转化BCD码;DS1302_WriteBety(DS1302_MINUTE, DS1302_Time[4]/10*16+DS1302_Time[4]%10);//写入分,并将10进制转化BCD码;DS1302_WriteBety(DS1302_SECOND, DS1302_Time[5]/10*16+DS1302_Time[5]%10);//写入秒,并将10进制转化BCD码;DS1302_WriteBety(DS1302_DAY, DS1302_Time[6]/10*16+DS1302_Time[6]%10);//写入星期,并将10进制转化BCD码;DS1302_WriteBety( DS1302_WP,0x80);//写入结束,开启写保护;
}/**
*@breaf 读取DS1302内时间
*@param无
*@retval无
*/
void DS1302_ReadTime()	
{unsigned char Temp;//定义变量,用于暂时存储BCD码Temp=DS1302_ReadBety(DS1302_YEAR);//读取年BCD码;DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_MONTH);//读取月BCD码;DS1302_Time[1]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_DATE);//读取日BCD码;DS1302_Time[2]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_HOUR);//读取小时BCD码;DS1302_Time[3]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_MINUTE);//读取分钟BCD码;DS1302_Time[4]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_SECOND);//读取秒BCD码;DS1302_Time[5]=Temp/16*10+Temp%16;//BCD码转十进制;Temp=DS1302_ReadBety(DS1302_DAY);//读取星期BCD码;DS1302_Time[6]=Temp/16*10+Temp%16;//BCD码转十进制;
}

DS1302.h

#ifndef __DS1302_H__
#define __DS1302_H__extern unsigned char DS1302_Time[];//声明设置时间的数组
void  DS1302_Init();//声明初始化函数
void  DS1302_WriteBety(unsigned char command,Data);//声明时间写入函数
unsigned char   DS1302_ReadBety(unsigned char command);//声明时间读出函数
void DS1302_SetTime();//声明设置内部时间函数
void DS1302_ReadTime();//声明读取内部时间函数#endif

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

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

相关文章

SpringBoot启动流程源码解析

目录 一、SpringApplication构造方法解析 1. web应用类型 2. BootstrapRegistryInitializer 3. ApplicationContextInitializer 4. ApplicationListener 5. 推断Main方法所在类 二、SpringApplication.run(String... args)方法解析 1.创建DefaultBootstrapContext 2.获…

订单超时自动取消的实践方案

1、定时任务方案 方案流程&#xff1a; 每隔 30 秒查询数据库&#xff0c;取出最近的 N 条未支付的订单。 遍历查询出来的订单列表&#xff0c;判断当前时间减去订单的创建时间是否超过了支付超时时间&#xff0c;如果超时则对该订单执行取消操作。 定时任务方案工程实现相…

【Vue】vue中将 html 或者 md 导出为 word 文档

原博主 xh-htmlword文档 感谢这位大佬的封装优化和分享&#xff0c;亲测有用&#xff01;可以去看大佬&#x1f447;的说明&#xff01; 前端HTML转word文档&#xff0c;绝对有效&#xff01;&#xff01;&#xff01; 安装 npm install xh-htmlword导入 import handleEx…

远动通讯屏的作用

远动通讯屏的作用 远动通讯屏有时有称为调度数据网柜&#xff0c;远动通讯屏具体干啥作用&#xff1f;远动通讯屏是以计算机为基础的生产过程与调度自动化系统&#xff0c;可以对现场的运行设备进行监视和控制、以实现数据采集、设备测量、参数调节以及各类信号报警等各项功能。…

用webui.sh安装报错No module named ‘importlib.metadata‘

安装sdweb报错&#xff0c;出现No module named importlib.metadata&#xff1a; glibc version is 2.35 Cannot locate TCMalloc. Do you have tcmalloc or google-perftool installed on your system? (improves CPU memory usage) Traceback (most recent call last):File…

堆的基本操作(c语言实现)

1.堆的基本操作 1.1定义堆 typedef int HPDataType;//堆中存储数据的类型typedef struct Heap {HPDataType* a;//用于存储数据的数组int size;//记录堆中已有元素个数int capacity;//记录堆的容量 }HP;1.2初始化堆 然后我们需要一个初始化函数&#xff0c;对刚创建的堆进行初…

【C语言】路漫漫其修远兮,深入[指针]正当下

一. 指针初步 1.概念定义 地址&#xff1a;我们在内存中开辟空间时&#xff0c;为了方便后续访问&#xff0c;每个数据有确切的地址。 指针&#xff1a;指向数据的地址&#xff0c;并将其地址储存在指针变量中。 2.基本运算符 • 取地址操作符&#xff08;&&#xff09; …

【强化学习入门】基于DDPG的强化学习控制器设计

最近在看控制领域研究热门–强化学习相关的东西&#xff0c;跟着matlab官方强化学习教程一边看一边学&#xff0c;感觉入门门槛略高&#xff0c;需要补很多机器学习相关的知识&#xff0c;高数概率论那些&#xff0c;摸索了个把月感觉现在只大概会用&#xff0c;原理啥的还没搞…

进口家装水管十大品牌哪家好,弗锐德为您推荐进口家装水管领先十大品牌

水管作为家装隐蔽工程之一&#xff0c;选对一款优质的水管是至关重要的&#xff0c;毕竟好的水管能够保证家庭后续几十年的用水安全和健康。今天&#xff0c;小编就和大家说说进口家装水管十大品牌哪家好&#xff1f; 目前国内进口家装水管具有知名度和消费者认可的品牌有&…

自制一个3D打印的移动终端——T3rminal

T3rminal是我过去几个月一直在努力开发的一个CyberDeck&#xff0c;并希望将其开源。 我从不同设备如Decktility、YARH和其他项目中获得了灵感。 你可以在我的Github上协助并关注该项目&#xff1a;https://github.com/crazycaleb2008/T3rminal/tree/main/3D%20Models 材料 …

Edge的使用心得和深度探索-Sider: ChatGPT 侧边栏

作为一款备受欢迎的网络浏览器&#xff0c;Microsoft Edge在用户体验和功能方面都有着诸多优势。在长期的使用中&#xff0c;我总结出了三条使用心得&#xff0c;同时也发现了三个能够极大提高效率的功能。让我们一起深度探索Edge的潜力吧&#xff01; 使用心得&#xff1a; 界…

Spring 常用的注入方式有什么?

Spring 是一个非常流行的 Java 开发框架&#xff0c;它提供了多种依赖注入&#xff08;Dependency Injection&#xff09;的方式&#xff0c;使得开发者可以轻松地管理应用程序中的组件依赖关系。在 Spring 中&#xff0c;常用的注入方式主要包括构造器注入、Setter 方法注入、…

【测试报告】星光日册

⭐ 作者&#xff1a;Jwenen &#x1f331; 作者主页&#xff1a;Jwenen的个人主页 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 测试报告 1. 项目介绍2. 测试用例框架3. 自动化测试源码 1. 项目介绍 “星光日册”项目实现了用…

继续SQL

主知识点六&#xff1a;having 聚合前的筛选用where&#xff0c;聚合后的筛选用having Having和where的区别是&#xff1a;运行顺序和对象不用 Having是在group by聚合后的基础上进行筛选。 ● 【例题27*】&#xff08;运行原理&#xff09;查询总人口数至少为3亿的大洲和…

vxe-table 区域选取、复制粘贴功能,的基本使用

vxe-table区域选取、复制粘贴功能&#xff0c;的基本使用&#xff08;注&#xff1a;该功能仅支持企业版&#xff0c;这里仅供部分演示&#xff09; 1.鼠标区域选择功能&#xff1a; 参数说明&#xff1a; mouse-config.area 是否开启鼠标单元格区域选取 <template>&l…

详解基于 RAG 的 txt2sql 全过程

前文 本文使用通义千问大模型和 ChromaDB 向量数据库来实现一个完整的 text2sql 的项目&#xff0c;并基于实际的业务进行效果的展示。 准备 在进行项目之前需要准备下面主要的内容&#xff1a; python 环境通义千问 qwen-max 模型的 api-keyChromaDB 向量数据库acge_text_…

Linux-笔记 uboot修改设备树

1. FDT介绍 扁平设备树&#xff08;Flattened Device Tree&#xff0c;FDT&#xff09;&#xff0c;也叫平坦设备树&#xff0c;是设备树的一种二进制表示形式&#xff0c;提高了在嵌入式系统中的传输和解析效率&#xff1b; 2. 在U-Boot中使用FDT 2.1. 进入U-Boot 开发板上…

OpenCV 入门(四)—— 车牌号识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

【论文阅读】VMamba: Visual State Space Model

VMamba:视觉状态空间模型 code&#xff1a;https://github.com/MzeroMiko/VMamba Background ​ CNN拥有线性复杂度因而可以处理高分辨率的图像&#xff0c;而ViT在拟合能力方面超过了CNN&#xff0c;但ViT是二次复杂度&#xff0c;在处理高分辨率图像时计算开销较大。ViT通过…

Wappalyzer指纹识别下载安装使用教程,图文教程(超详细)

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…