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.rhkb.cn/news/322729.html

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

相关文章

技术分享 | 京东商品API接口|京东零售数据可视化平台产品实践与思考

导读 本次分享题目为京东零售数据可视化平台产品实践与思考。 主要包括以下四个部分&#xff1a; 1.京东API接口介绍 2. 平台产品能力介绍 3. 业务赋能案例分享 01 京东API接口介绍 02 平台产品能力介绍 1. 产品矩阵 数据可视化产品是一种利用数据分析和可视化技术&…

Ti雷达常用工具

Ti雷达常用工具 名称网站功能雷达开箱界面mmWave Demo Visualizer (ti.com)显示距离谱、RD谱图雷达参数估计mmWaveSensingEstimator根据性能设计估计参数雷达项目资料Embedded Software (ti.com)Ti雷达示例及说明书官方论坛Sensors forum - Sensors - TI E2E support forumsTi…

php傻瓜式搭建tcp及websocket服务

网络编程 随着互联网的快速发展&#xff0c;网络应用程序的需求也越来越高。为了使网页更加丰富有趣&#xff0c;许多网站都开始使用套接字(socket)实现网络的实时通信。而 tcp/ip 协议则常常用于实现此类应用程序。 TCP/IP协议是一种工业标准协议&#xff0c;是互联网使用最…

Cheetah3D for Mac - 轻松打造专业级3D作品

对于追求专业级3D作品的设计师来说&#xff0c;Cheetah3D for Mac无疑是一款不可多得的工具。 这款软件拥有强大的建模、渲染和动画功能&#xff0c;能够满足您在3D设计方面的各种需求。通过简单的操作&#xff0c;您可以轻松构建出复杂的3D模型&#xff0c;并为其添加逼真的材…

QT中的容器

Qt中的容器 关于Qt中的容器类&#xff0c;下面我们来进行一个总结&#xff1a; Qt的容器类比标准模板库&#xff08;STL&#xff09;中的容器类更轻巧、安全和易于使用。这些容器类是隐式共享和可重入的&#xff0c;而且他们进行了速度和存储的优化&#xff0c;因此可以减少可…

# 从浅入深 学习 SpringCloud 微服务架构(七)Hystrix(4)

从浅入深 学习 SpringCloud 微服务架构&#xff08;七&#xff09;Hystrix&#xff08;4&#xff09; 一、hystrix&#xff1a;使用 turbine 聚合所有的 hytrix 的监控数据测试。创建父工程 spring_cloud_hystrix_demo&#xff0c;导入相关依赖坐标。并在父工程 spring_cloud_…

牛客NC97 字符串出现次数的TopK问题【中等 哈希+优先级队列 Java/Go】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/fd711bdfa0e840b381d7e1b82183b3ee 核心 哈希&#xff0c;优先级队列Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返…

AI智能对话系统源码 内置所有支付接口 功能强大 带完整的安装代码包以及安装部署教程

在数字化日益普及的今天&#xff0c;AI智能对话系统已经成为企业与客户沟通的重要桥梁。为了满足市场的需求&#xff0c;罗峰给大家分享一款全新的AI智能对话系统源码&#xff0c;它集成了所有必要的支付接口&#xff0c;功能强大且易于部署。 以下是部分代码示例&#xff1a;…

vue3创建响应式数据ref和reactive的区别

reactive和ref在Vue.js中都是用于创建响应式数据的&#xff0c;但它们之间存在一些区别 定义数据类型不同。ref主要用于定义基本数据类型&#xff0c;如字符串、数字、布尔值等&#xff1b;reactive主要用于定义对象&#xff08;或数组&#xff09;类型的数据&#xff0c;但re…

备考2024年小学生古诗文大会:吃透10道历年真题和知识点(持续)

对上海小学生的小升初和各种评优争章来说&#xff0c;语文、数学、英语的含金量较高的证书还是很有价值和帮助的。对于语文类的竞赛&#xff0c;小学生古诗文大会和汉字小达人通常是必不可少的&#xff0c;因为这两个针对性强&#xff0c;而且具有很强的上海本地特色。 根据往…

MM模块学习一(供应商创建,物料类型的定义及功能)

物料管理流程&#xff1a; 源头&#xff1a;采购需求->采购申请 MRP&#xff1a;物料需求计划。运行物料需求计划的结果&#xff0c;根据物料的性质来判断是外购&#xff08;采购申请&#xff09;或者是生产&#xff08;计划订单->生产订单&#xff09;。 采购申请&am…

Angular基础-搭建Angular运行环境

这篇文章介绍了在Angular项目中进行开发环境搭建的关键步骤。包括node.js安装和配置、安装Angular CLI工具、安装angular-router、创建Angular项目等步骤。这篇文章为读者提供了清晰的指南&#xff0c;帮助他们快速搭建Angular开发环境&#xff0c;为后续的项目开发奠定基础。 …

改进灰狼算法优化随机森林回归预测

灰狼算法&#xff08;Grey Wolf Optimization&#xff0c;GWO&#xff09;是一种基于自然界灰狼行为的启发式优化算法&#xff0c;在2014年被提出。该算法模仿了灰狼群体中不同等级的灰狼间的优势竞争和合作行为&#xff0c;通过不断搜索最优解来解决复杂的优化问题。 灰狼算法…

如何使用ESOP电子作业指导书系统提高工作效率?

在当今工业生产和制造领域&#xff0c;实现作业标准化是提高生产效率、保证产品质量、提升企业竞争力的重要途径。而 ESOP 无纸化指导书系统作为一种创新的技术手段&#xff0c;正逐渐成为实现作业标准化的关键所在。 ESOP 无纸化指导书系统通过数字化的方式&#xff0c;将传统…

docker学习笔记(四)制作镜像

目录 第1步&#xff1a;编辑Dockerfile 第2步&#xff1a;编辑requirements.txt文件 第3步&#xff1a;编辑app.py文件&#xff0c;我们的程序文件 第4步&#xff1a;生成镜像文件 第5步&#xff1a;使用镜像&#xff0c;启动容器 第6步&#xff1a; 启动redis容器、将容器…

MySQL中JOIN连接的实现算法

目录 嵌套循环算法&#xff08;NLJ&#xff09; 简单嵌套循环&#xff08;SNLJ&#xff09; 索引嵌套循环&#xff08;INLJ&#xff09; 块嵌套循环&#xff08;BNLJ&#xff09; 三种算法比较 哈希连接算法&#xff08;Hash Join&#xff09; 注意事项&#xff1a; 工…

93、动态规划-最长回文子串

思路 首先从暴力递归开始&#xff0c;回文首尾指针相向运动肯定想等。就是回文&#xff0c;代码如下&#xff1a; public String longestPalindrome(String s) {if (s null || s.length() 0) {return "";}return longestPalindromeHelper(s, 0, s.length() - 1);…

django中的cookie与session

获取cookie request.COOKIE.GET 使用cookie response.set-cookie views.py from django.http import HttpResponse from django.shortcuts import render# Create your views here. def cookie_test(request):r HttpResponse("hello world")r.set_cookie(lan, py…

【第38天】SQL进阶-SQL设计优化-范式设计(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是范式设计第一范式&#xff08;1NF&#xff09;第二范式&#xff08;2NF&#xff09;第三范式&#xff08;3NF&#xff09; 三、总结四、参考 零、前言 今天是学习 SQL …

Sealos急速部署生产用k8s集群

最近一段时间部署k8s全部使用sealos了&#xff0c;整体使用感觉良好&#xff0c;基本没有什么坑。推荐给大家。 使用 Sealos&#xff0c;可以安装一个不包含任何组件的裸 Kubernetes 集群。 最大的好处是提供 99 年证书&#xff0c;用到我跑路是足够了。不用像之前kubeadm安装…