DS1302时钟芯片全解析——概况,性能,MCU连接,样例代码

DS1302概述:

数据:

DS1302是一个可充电实时时钟芯片,包含时钟(24小时格式或12小时格式)、日历(年,月,日,星期)、31字节RAM(断电数据丢失)。

供电:

DS1302采用两组供电,一组主电,由外部供电,一组备电,一般由纽扣电池供电。当主电存在时,由主电供电,当主电不存在时由备电供电。

功能:

DS1302,通过外部晶振自动对时间进行计数,对月末日期进行调整,以及闰年矫正。MCU可对其时间日期进行设置及读取,显示正确的当前时间。同时可借用31字节的RAM临时保存重要数据(因为外部断电后,纽扣电池供电保证数据不丢失)。

连接:

与MCU连接只需要三个普通GPIO口即可,DS1302芯片的通讯方式接近于SPI,其中将SPI的MISO和MOSI合并为I/O引脚。但是并不需要使用SPI复用引脚进行连接,只需要普通GPIO引脚即可。

DS1302型号说明:

在这里插入图片描述
这里是常用国产有替代型号:DS1302,插件;DS1302Z+T,贴片;DS1302N温度范围从(0 ~ +70℃)提高到 (-40~ +85℃),插件;DS1302ZN+T温度范围从(0 ~ +70℃)提高到 (-40~ +85℃),贴片。

DS1302引脚说明:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

MCU连接:

正常使用时完全可以安照下图进行连接,非常简单,任意的3个GPIO口连接CE、I/O、SCLK(这里的SCLK只是提供一个上升沿做时钟信号,设低再设高之后数据即被DS1302读取,并非SPI或IIC的CLK)。晶振直接近距离连接DS1302即可,不需要接对地的匹配电容。VCC2接外部供电,VCC1接纽扣电池。
在这里插入图片描述
下图,晶振近距离连接DS1302,斜线部分的不要走信号线,会对晶振信号产生影响。
在这里插入图片描述

DS1302寄存器定义:

在这里插入图片描述

首先是寄存器地址:

寄存地址最后一位表示读写,前边按正常数值。如秒钟地址,读地址为0b1000 0001 = 0x81;写地址为0b1000 0000 = 0x80,所以读地址比写地址大1。

寄存器定义:

一个字节的8位二进制数分为十位和个位,并不是直接对应的十六进制数,这点要注意。例如23秒,读出的是0x23,而不是0x17。采用右移和与运算可对数据进行分离。
控制寄存器进行写保护操作,只对最高位写保护为进行操作即可。

RAM操作:

和时间寄存器一样,最后一位表示读写,前边按正常数值。如RAM 0地址,读地址为0b1100 0001 = 0xC1;写地址为0b1100 0000 = 0xC0。数据内容不限,任意单字节数值。

DS1302寄存器读写:

在这里插入图片描述
首先是读写时序图:
RST 即CE,为数据传输控制,数据传输时设高电平,不用时设低电平;
SCLK即DS1302 读写数值控制信号,上升沿触发, 即SCLK的GPIO由低电平设置到高电平时,DS1302读取或写出一个数据。
I/O即DS1302读取或写出的数据。在MCU写入数据时,连接的GPIO设置为一般输出模式,通过高低电平切换,写入数据;在MCU写入数据时,连接的GPIO设置为一般读取电平模式,通过获取DS1302 I/O输出的高低电平,读取数据。
I/O数据的寄存器地址由低位到高位的顺序进行写入;数据也是由低位到高位写入,或读出。 其中R/W 即为读写控制位0为读,1为写,A0-A4为地址数据,R/C为时间寄存器还是RAM寄存器控制位,D0-D7为写入数据,读取时该位置为读出数据。
在进行写时间数据操作时,MCU先向DS1302输出写寄存器地址,再紧跟着输出时间数据;在进行读时间数据操作时,MCU先向DS1302输出读寄存器地址,再紧跟着读取DS1302输出的时间数据;该数据输入输出流程时序由SCLK上升沿控制。

DS1302代码样例(基于HC32L130):

ds1302.h文件

#ifndef __DS1302_H__
#define __DS1302_H__#include "ddl.h"
#include "gpio.h"
#include "hc32l13x.h"//DS1302 GPIO定义
#define DS1302_RSTPORT				GpioPortB
#define	DS1302_RSTPIN					GpioPin12
#define	DS1302_DATAPORT				GpioPortB
#define	DS1302_DATAPIN				GpioPin11
#define	DS1302_CLKPORT				GpioPortB
#define	DS1302_CLKPIN					GpioPin10
//DS1302地址定义
#define ds1302_sec_add			  0x80		//秒数据地址
#define ds1302_min_add			  0x82		//分数据地址
#define ds1302_hr_add			    0x84		//时数据地址
#define ds1302_date_add			  0x86		//日数据地址
#define ds1302_month_add		  0x88		//月数据地址
#define ds1302_day_add			  0x8a		//星期数据地址
#define ds1302_year_add			  0x8c		//年数据地址
#define ds1302_control_add		0x8e		//控制数据地址
#define ds1302_charger_add		0x90 					 
#define ds1302_clkburst_add		0xbe
//初始时间定义
extern	uint8_t time_buf[8]; //设置时间
extern	uint8_t readtime[14];//当前时间void ds1302_init(void);
void ds1302ioinit(void);void ds1302_write_byte(uint8_t data);
uint8_t ds1302_read_byte(void);void ds1302_write_reg_byte(uint8_t addr,uint8_t	data);
uint8_t ds1302_read_reg_byte(uint8_t addr);void ds1302_read_time(void);
void ds1302_write_time(void);uint8_t	ds1302_read_hour(void);
uint8_t	ds1302_read_minute(void);
uint8_t	ds1302_read_second(void);#endif /* __DS1302_H__ */

ds1302.c文件

#include "ds1302.h"
#include "hc32l13x.h"//定义GPIO操作
#define DS1302_SCK_PIN_LOW 		Gpio_ClrIO(DS1302_CLKPORT,DS1302_CLKPIN)
#define DS1302_SCK_PIN_HIGH 	Gpio_SetIO(DS1302_CLKPORT,DS1302_CLKPIN)#define DS1302_RST_PIN_LOW 		Gpio_ClrIO(DS1302_RSTPORT,DS1302_RSTPIN)
#define DS1302_RST_PIN_HIGH 	Gpio_SetIO(DS1302_RSTPORT,DS1302_RSTPIN)#define DS1302_SDA_PIN_LOW		Gpio_ClrIO(DS1302_DATAPORT,DS1302_DATAPIN)
#define DS1302_SDA_PIN_HIGH		Gpio_SetIO(DS1302_DATAPORT,DS1302_DATAPIN)
#define DS1302_SDA_PIN_READ		Gpio_GetInputIO(DS1302_DATAPORT,DS1302_DATAPIN)//GPIO定义 SCLK和RST(CE)
void	ds1302ioinit(void) 
{stc_gpio_cfg_t         GpioInitStruct;	DDL_ZERO_STRUCT(GpioInitStruct);  ///< 打开GPIO外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);///< 端口驱动能力配置->低驱动能力GpioInitStruct.enDrv = GpioDrvL;///< 端口方向配置->输出GpioInitStruct.enDir = GpioDirOut;///< 端口上下拉配置->下拉GpioInitStruct.enPu = GpioPuDisable;GpioInitStruct.enPd = GpioPdEnable;///< 端口输出关闭Gpio_ClrIO(DS1302_CLKPORT, DS1302_CLKPIN);Gpio_ClrIO(DS1302_RSTPORT, DS1302_RSTPIN);///< 端口初始化Gpio_Init(DS1302_CLKPORT,DS1302_CLKPIN,&GpioInitStruct);Gpio_Init(DS1302_RSTPORT,DS1302_RSTPIN,&GpioInitStruct);
}//GPIO定义 I/O输出
void	ds1302_dataOut_init(void)
{stc_gpio_cfg_t         GpioInitStruct;	DDL_ZERO_STRUCT(GpioInitStruct);  ///< 打开GPIO外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);///< 端口驱动能力配置->低驱动能力GpioInitStruct.enDrv = GpioDrvL;///< 端口方向配置->输出GpioInitStruct.enDir = GpioDirOut;///< 端口上下拉配置->下拉GpioInitStruct.enPu = GpioPuDisable;GpioInitStruct.enPd = GpioPdEnable;///< 端口输出关闭Gpio_ClrIO(DS1302_DATAPORT, DS1302_DATAPIN);///< 端口初始化Gpio_Init(DS1302_DATAPORT,DS1302_DATAPIN,&GpioInitStruct);
}
//GPIO定义 I/O输入
void	ds1302_dataIn_init(void)
{stc_gpio_cfg_t         GpioInitStruct;	DDL_ZERO_STRUCT(GpioInitStruct);  ///< 打开GPIO外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);///< 端口驱动能力配置->低驱动能力GpioInitStruct.enDrv = GpioDrvL;///< 端口方向配置->输入GpioInitStruct.enDir = GpioDirIn;///< 端口上下拉配置->无GpioInitStruct.enPu = GpioPuDisable;GpioInitStruct.enPd = GpioPdDisable;///< 端口开漏输出配置->开漏输出关闭GpioInitStruct.enOD = GpioOdDisable;///< 端口输入/输出值寄存器总线控制模式配置->AHBGpioInitStruct.enCtrlMode = GpioAHB;Gpio_Init(DS1302_DATAPORT,DS1302_DATAPIN,&GpioInitStruct);               ///< 端口初始化
}//DS1302初始化函数
void ds1302_init(void) 
{ds1302ioinit();ds1302_dataOut_init();
}//向DS1302写入一字节数据
void ds1302_write_byte(uint8_t data) 
{uint8_t i;ds1302_dataOut_init();for (i = 0; i < 8; i ++) {DS1302_SCK_PIN_LOW;if (data & 0x01) DS1302_SDA_PIN_HIGH;elseDS1302_SDA_PIN_LOW;DS1302_SCK_PIN_HIGH;data = data >> 1;}
}//从DS1302读出一字节数据
uint8_t ds1302_read_byte(void)
{uint8_t i, data = 0;ds1302_dataIn_init();for (i = 0; i < 8; i ++){DS1302_SCK_PIN_LOW;data >>= 1;if(DS1302_SDA_PIN_READ)data |= 0x80;DS1302_SCK_PIN_HIGH;}return data;
}//向DS1302写入对应寄存器数据
void ds1302_write_reg_byte(uint8_t addr,uint8_t	data)
{DS1302_RST_PIN_LOW;DS1302_SCK_PIN_LOW;DS1302_RST_PIN_HIGH;ds1302_write_byte(addr);ds1302_write_byte(data);DS1302_SCK_PIN_HIGH;DS1302_RST_PIN_LOW;
}//从DS1302读出对应寄存器数据
uint8_t ds1302_read_reg_byte(uint8_t addr)
{uint8_t data;DS1302_RST_PIN_LOW;DS1302_SCK_PIN_LOW;DS1302_RST_PIN_HIGH;ds1302_write_byte(addr);data=ds1302_read_byte();DS1302_SCK_PIN_HIGH;DS1302_RST_PIN_LOW;return data;
}//向DS1302写入时间数据
void ds1302_write_time(void) 
{ds1302_write_reg_byte(ds1302_control_add,0x00);			//关闭写保护 ds1302_write_reg_byte(ds1302_charger_add,0x00);	    		//禁止充电 ds1302_write_reg_byte(ds1302_year_add,time_buf[1]);		//年 ds1302_write_reg_byte(ds1302_month_add,time_buf[2]);	//月 ds1302_write_reg_byte(ds1302_date_add,time_buf[3]);		//日 ds1302_write_reg_byte(ds1302_hr_add,time_buf[4]);		//时 ds1302_write_reg_byte(ds1302_min_add,time_buf[5]);		//分ds1302_write_reg_byte(ds1302_sec_add,time_buf[6]);		//秒ds1302_write_reg_byte(ds1302_day_add,time_buf[7]);		//周 ds1302_write_reg_byte(ds1302_control_add,0x80);			//打开写保护     
}//从DS1302读出时间数据
void ds1302_read_time(void)  
{time_buf[1]=ds1302_read_reg_byte(ds1302_year_add+1);		//年 time_buf[2]=ds1302_read_reg_byte(ds1302_month_add+1);		//月 time_buf[3]=ds1302_read_reg_byte(ds1302_date_add+1);		//日 time_buf[4]=ds1302_read_reg_byte(ds1302_hr_add+1);		  //时 time_buf[5]=ds1302_read_reg_byte(ds1302_min_add+1);		  //分 time_buf[6]=(ds1302_read_reg_byte(ds1302_sec_add+1))&0x7f;//秒,屏蔽秒的第7位,避免超出59time_buf[7]=ds1302_read_reg_byte(ds1302_day_add+1);		  //周 	readtime[0]=(time_buf[0]>>4);   //分离出年千位readtime[1]=(time_buf[0]&0x0F); //分离出年百位 readtime[2]=(time_buf[1]>>4);   //分离出年十位readtime[3]=(time_buf[1]&0x0F); //分离出年个位 readtime[4]=(time_buf[2]>>4);   //分离出月十位readtime[5]=(time_buf[2]&0x0F); //分离出月个位 readtime[6]=(time_buf[3]>>4);   //分离出日十位readtime[7]=(time_buf[3]&0x0F); //分离出日个位 readtime[8]=(time_buf[4]>>4);   //分离出小时十位readtime[9]=(time_buf[4]&0x0F); //分离出小时个位 readtime[10]=(time_buf[5]>>4);   //分离出分钟十位readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位 
}//从DS1302读出小时数据
uint8_t	ds1302_read_hour(void)
{uint8_t	time_hour;time_buf[4]=ds1302_read_reg_byte(ds1302_hr_add+1);		  //时readtime[8]=(time_buf[4]>>4);   //分离出小时十位readtime[9]=(time_buf[4]&0x0F); //分离出小时个位 time_hour = readtime[8]*10+readtime[9];return	time_hour;
}//从DS1302读出分钟数据
uint8_t	ds1302_read_minute(void)
{uint8_t	time_minute;time_buf[5]=ds1302_read_reg_byte(ds1302_min_add+1);		  //分readtime[10]=(time_buf[5]>>4);   //分离出分钟十位readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位 time_minute = readtime[10]*10+readtime[11];return	time_minute;
}//从DS1302读出秒钟数据
uint8_t	ds1302_read_second(void)
{uint8_t	time_second;time_buf[6]=(ds1302_read_reg_byte(ds1302_sec_add+1))&0x7f;//秒,屏蔽秒的第7位,避免超出59readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位 time_second = readtime[12]*10+readtime[13];return	time_second;
}

main.c文件

#include "gpio.h"
#include "ddl.h"
#include "ds1302.h"//读写时间列表定义
uint8_t time_buf[8]; //设置时间
uint8_t readtime[14];//当前时间//读取时间
uint8_t ds1302_hour = 0;
uint8_t ds1302_minute = 0;
uint8_t ds1302_second = 0;void init()
{time_buf[0] = 0x00;		//年 time_buf[1] = 0x24;		//年 time_buf[2] = 0x07;		//月 time_buf[3] = 0x19;		//日 time_buf[4]	= 0x17;		//时 time_buf[5] = 0x16;		//分time_buf[6]	= 0x20;		//秒time_buf[7] = 0x05;		//周 
}int main(void)
{init();//DS1302初始化ds1302_init();//DS1302写入时间数据ds1302_write_time();while(1){ds1302_hour = ds1302_read_hour();					//读取小时数据ds1302_minute = ds1302_read_minute();			//读取分钟数据ds1302_second	= ds1302_read_second();			//读取秒钟数据//DS1302读取时间数据ds1302_read_time();}
}

调试效果:
在这里插入图片描述

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

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

相关文章

Fantastic-admin:Vue 中后台管理系统

Fantastic-admin&#xff1a;Vue 中后台管理系统 在当今的前端开发世界里&#xff0c;fantastic-admin 作为一款功能强大的 Vue 中后台管理系统框架&#xff0c;简直是开发者的福音。本文将介绍 fantastic-admin 的基本信息、特点&#xff0c;以及如何快速上手和使用。 项目简介…

面试场景题系列--(4)设计一个支持敏感数据存储和传输安全的加解密平台--xunznux

文章目录 设计一个支持敏感数据存储和传输安全的加解密平台1. 设计背景2. 需求分析日常开发中的加解密程序常见问题解决方案具体来说系统主要用例过程和功能系统需求 3. 概要设计3.1 部署模型3.2 加解密调用流程 4. 详细设计4.1 密钥领域模型4.2 核心服务类设计4.3 加解密数据接…

WSL for Windows

1、安装 超详细Windows10/Windows11 子系统&#xff08;WSL2&#xff09;安装Ubuntu20.04&#xff08;带桌面环境&#xff09;_wsl安装ubuntu20.04-CSDN博客https://blog.csdn.net/weixin_44301630/article/details/122390018 注意&#xff0c;安装之后首次启动 Ubuntu 时&…

【Web开发手礼】探索Web开发的魅力(十二)-Vue(2)用户动态页面

前言 主要介绍了用vue框架创建用户动态页面的具体过程&#xff0c;可以帮助学习vue框架的基本知识&#xff01;&#xff01;&#xff01;&#xff01; 用户动态页面 用户信息 用户头像 通过 Bootstrap 所提供的 .img-fluid 类让图片支持响应式布局。其原理是将 max-width: 10…

三子棋小程序

一.自定义头文件(game.h) 放入源文件需要用到的标准库头文件和函数的声明 ROW 和COL为棋盘的行和列&#xff0c;三子棋嘛&#xff0c;肯定为3啦 #pragma once #include<stdio.h> #include<String.h> #include<stdlib.h> #include<time.h> #define ROW…

《Java初阶数据结构》----10.<Map和Set---TreeSet和TreeMapHashSet和HashMap >

前言&#xff1a; 大家好&#xff0c;我目前在学习java。我准备利用这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论&#xff01;&#xff01;&#xff01; 喜欢我文…

C/C++大雪纷飞代码

目录 写在前面 C语言简介 EasyX简介 大雪纷飞 运行结果 写在后面 写在前面 本期博主给大家带来了C/C实现的大雪纷飞代码&#xff0c;一起来看看吧&#xff01; 系列推荐 序号目录直达链接1爱心代码https://want595.blog.csdn.net/article/details/1363606842李峋同款跳…

【LeetCode】141.环形链表、142. 环形链表 II(算法 + 图解)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;数据结构 &#x1f4da;本系列文章为个人学…

AI学习记录 - 本地知识库实现的相关知识

在公司内部实现了个知识库&#xff0c;但这里只介绍在实现知识库的过程中用到的知识。 1、分词器 先分词&#xff0c;中文可以使用jieba分词 2、构造数据集 将词汇向量化是自然语言处理中的重要任务&#xff0c;它可以将文本数据转化为计算机能够理解和处理的向量形式。以…

在react中如何计算本地存储体积

1.定义useLocalStorageSize钩子函数 // 计算localStorage大小 function useLocalStorageSize() {const [size, setSize] useState(0);useEffect(() > {const calculateSize () > {let totalSize 0;for (let key in localStorage) {//过滤掉继承自原型链的属性if (loc…

抄作业-跟着《React通关秘籍》捣鼓React-playground-上集

文章目录 前言1. 搭建react 开发环境2、react hooks 知识3. 目标&#xff1a;跟着小册实现 react-playground3.1 整体布局初始化项目使用Alloment 来实现左右分屏的拖拉功能 3.2 代码编辑器Monaco Editor 3.3 实现了多文件的切换用 useContext 来共享数据。优化 tab的样式&…

扫雷游戏小程序

目录 一.文件 1.头文件 2.源文件 二.游戏界面和执行(test.c) 三.函数实现(void game部分,源文件game.c) 1.定义雷二维数组和展示二维数组 2.初始化地雷数组 3.初始化显示的数组 4.显示当前的情况 5.随机放置地雷 6.排雷 ps:深度优先遍历数组 四.结束 一.文件 1.头…

《Single-Stage Extensive Semantic Fusion for multi-modal sarcasm detection》

系列论文研读目录 文章目录 系列论文研读目录文章题目含义ABSTRACTKeywords1. Introduction2. Related work3. Method3.1. Multi-modal projection 多模态投影3.2. Extensive Semantic Fusion Multiway Transformer 可拓语义融合多路Transformer3.3. Multi-objective optimizat…

LeetCode 热题 HOT 100 (011/100)【宇宙最简单版】

【图论】No. 0200 岛屿数量 【中等】&#x1f449;力扣对应题目指路 希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【力扣详解】谢谢你的支持&#xf…

DjangoRF-10-过滤-django-filter

1、安装pip install django-filter https://pypi.org/ 搜索django-filter基础用法 2、进行配置 3、进行内容调试。 4、如果碰到没有关联的字段。interfaces和projects没有直接关联字段&#xff0c;但是interface和module有关联&#xff0c;而且module和projects关联&#x…

linux下使用yum安装mysql

本文使用常规方式手动安装mysql 第一步 下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm第二步 安装mysql-community-release-el7-5.noarch.rpm包 rpm -ivh mysql-community-release-el7-5.noarch.rpm第三步 安装mysql-server yum -y…

Esp_server 安卓嵌入壳子,原创! 2024/7/28 20:58

用到的软件: uni-app 思路: 让用户感觉是,一个完整的程序.实际上只是一个类浏览器壳子.轻便小巧. 由于是第一次用uni-app开发类软件,所以前前后后耗费7小时! 隔行如隔山,不是白讲的. 软件界面: 软件功能: 简化输入: 输入ip地址,例:http:// www.baidu.com 完整网址 前面…

Javaer 5分钟入门 Golang

文章目录 前言一个 go 文件长啥样&#xff1f;Go 语言的变量变量类型变量声明 Go 语言的函数&方法Go 语言没有的概念访问修饰符面向对象模型异常处理机制 Go 语言高效简洁的并发编程总结 前言 这两年主流的编程语言 Golang&#xff0c;想必大家或多或少都接触过。云原生领…

使用 Docker Compose 部署 RabbitMQ 的一些经验与踩坑记录

前言 RabbitMQ 是一个功能强大的开源消息队列系统&#xff0c;它实现了高效的消息通信和异步处理。 本文主要介绍其基于 Docker-Compose 的部署安装和一些使用的经验。 特点 成熟&#xff0c;稳定消息持久化灵活的消息路由高性能&#xff0c;高可用性&#xff0c;可扩展性高支…

【PYTHON】多进程运行示例含共享数据

运行结果 Python多进程调用示例 import multiprocessing import time import os import sys# 注册多个函数用于不同进程分别调用 def testcase0():time.sleep(1)return "case0_"get_time()def testcase1(timestamp):return "case1_"timestampdef testcase…