STM32控制DS1302时钟模块获取实时时间

欢迎入群共同学习交流
时间记录:2024/4/30

一、知识点

原理图
(1)读写数据时序(伪SPI协议)
读写时序
1.1 读写时序默认电平均为SCLK线低电平,CE线低电平
1.2 写数据,CE线拉高为高电平,开始传输数据,然后准备数据在SCLK线的上升沿DS1302读取数据,发送8位控制命令后,发送8位数据(低位先发)
1.3 读数据,CE线拉高为高电平,开始传输数据,然后在SCLK低电平时准备数据,上升沿发送数据,发送8位控制命令后,下一个下降沿开始读取数据(低位先发,低位先读)
(2)读写命令及数据格式
命令及数据格式
2.1 READ和WRITE的命令即为发送和读取数据前需要先发送的对应8位控制命令
2.2 秒数据的BIT7位CH决定时钟的开启/关闭
2.3 小时数据的BIT7位决定是12小时显示还是24小时显示
2.4 WP位决定开启写保护还是取消写保护,写入0取消写保护,写入1打开写保护
(3)数据转换
3.1 DS1302读取的数据为BCD编码格式,需要转为10进制,写入时10进制数据需要转为BCD格式
3.2 BCD->10进制,BCD/1610+BCD%16
3.3 10进制->BCD,10进制/10
16+10进制%10

二、示例代码

(1)头文件

#ifndef __DS1302_H__
#define __DS1302_H__
#include "stm32f10x.h"typedef struct __DS1302TIME
{int year;int mon;int day;int hour;int min;int sec;int week;
}ds_time;void vDS1302_Init(void);
void vDS1302_SetTime(ds_time *sys_time);
void vDS1302_GetTime(ds_time *sys_time);#endif

(2)源文件

#include "ds1302.h"/*** 模块引脚宏定义*/
#define DS1302_SCLK_PORT GPIOA
#define DS1302_SCLK_PIN GPIO_Pin_10
#define DS1302_DAT_PORT GPIOA
#define DS1302_DAT_PIN GPIO_Pin_11
#define DS1302_RST_PORT GPIOA
#define DS1302_RST_PIN GPIO_Pin_12/*** 获取设置时间命令宏定义*/
#define READ_SEC 0x81
#define WRITE_SEC 0x80
#define READ_MIN 0x83
#define WRITE_MIN 0x82
#define READ_HOUR 0x85
#define WRITE_HOUR 0x84
#define READ_DAY 0x87
#define WRITE_DAY 0x86
#define READ_MON 0x89
#define WRITE_MON 0x88
#define READ_WEEK 0x8B
#define WRITE_WEEK 0x8A
#define READ_YEAR 0x8D
#define WRITE_YEAR 0x8C
#define ENABLE_WRITE 0x00
#define DISABLE_WRITE 0x80/*** 枚举定义*/
enum __LINEMODE
{INPUT_MODE = 0,OUTPUT_MODE
};/*** 函数声明*/
static void vDatLineMode(u8 mode);
static void vWriteRam(u8 addr, u8 data);
static u8 vReadRam(u8 addr);/*** 初始化函数定义*/
void vDS1302_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = DS1302_SCLK_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS1302_SCLK_PORT, &GPIO_InitStruct);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);GPIO_InitStruct.GPIO_Pin = DS1302_RST_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS1302_RST_PORT, &GPIO_InitStruct);GPIO_ResetBits(DS1302_RST_PORT, DS1302_RST_PIN);
}/*** 数据引脚切换输入输出模式*/
static void vDatLineMode(u8 mode)
{GPIO_InitTypeDef GPIO_InitStruct;if (mode == INPUT_MODE){GPIO_InitStruct.GPIO_Pin = DS1302_DAT_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS1302_DAT_PORT, &GPIO_InitStruct);}else if (mode == OUTPUT_MODE){GPIO_InitStruct.GPIO_Pin = DS1302_DAT_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS1302_DAT_PORT, &GPIO_InitStruct);}
}/*** 写入数据*/
static void vWriteRam(u8 addr, u8 data)
{vDatLineMode(OUTPUT_MODE);GPIO_SetBits(DS1302_RST_PORT, DS1302_RST_PIN); // 开始传输数据for (u8 i = 0; i < 8; i++) // 传输控制字节{GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN); // 低电平准备数据if (addr & 0x01)                                   // 低位先发GPIO_SetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);elseGPIO_ResetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN); // 上升沿发送数据addr >>= 1;}for (u8 i = 0; i < 8; i++) // 传输数据字节{GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);if (data & 0x01)GPIO_SetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);elseGPIO_ResetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);data >>= 1;}// 传输完毕,恢复取消传输数据状态GPIO_ResetBits(DS1302_RST_PORT, DS1302_RST_PIN);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);
}/*** 读取数据*/
static u8 vReadRam(u8 addr)
{vDatLineMode(OUTPUT_MODE);GPIO_SetBits(DS1302_RST_PORT, DS1302_RST_PIN);u8 retData = 0x00;for (u8 i = 0; i < 8; i++) // 传输控制字节{GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN); // 低电平准备数据if (addr & 0x01)                                   // 低位先发GPIO_SetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);elseGPIO_ResetBits(DS1302_DAT_PORT, DS1302_DAT_PIN);GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);addr >>= 1;}vDatLineMode(INPUT_MODE);for (u8 i = 0; i < 8; i++){retData >>= 1;GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);if (GPIO_ReadInputDataBit(DS1302_DAT_PORT, DS1302_DAT_PIN))retData |= 0x80;GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);}GPIO_ResetBits(DS1302_RST_PORT, DS1302_RST_PIN);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);return (retData & 0x7F); // 最高位是一些标志位可清零不获取
}void vDS1302_SetTime(ds_time *sys_time)
{vWriteRam(0x8E, ENABLE_WRITE); // 关闭写保护sys_time->year = sys_time->year - 2000;vWriteRam(WRITE_YEAR, ((sys_time->year / 10 * 16) + (sys_time->year % 10)));vWriteRam(WRITE_MON, ((sys_time->mon / 10 * 16) + (sys_time->mon % 10)));vWriteRam(WRITE_DAY, ((sys_time->day / 10 * 16) + (sys_time->day % 10)));vWriteRam(WRITE_HOUR, ((sys_time->hour / 10 * 16) + (sys_time->hour % 10)));vWriteRam(WRITE_MIN, ((sys_time->min / 10 * 16) + (sys_time->min % 10)));vWriteRam(WRITE_SEC, ((sys_time->sec / 10 * 16) + (sys_time->sec % 10)));vWriteRam(WRITE_WEEK, ((sys_time->week / 10 * 16) + (sys_time->week % 10)));vWriteRam(0x8E, DISABLE_WRITE); // 开启写保护
}void vDS1302_GetTime(ds_time *sys_time)
{u8 tempDat = 0x00;tempDat = vReadRam(READ_YEAR);sys_time->year = (tempDat / 16 * 10) + (tempDat % 16) + 2000;tempDat = vReadRam(READ_MON);sys_time->mon = (tempDat / 16 * 10) + (tempDat % 16);tempDat = vReadRam(READ_DAY);sys_time->day = (tempDat / 16 * 10) + (tempDat % 16);tempDat = vReadRam(READ_HOUR);sys_time->hour = (tempDat / 16 * 10) + (tempDat % 16);tempDat = vReadRam(READ_MIN);sys_time->min = (tempDat / 16 * 10) + (tempDat % 16);tempDat = vReadRam(READ_SEC);sys_time->sec = (tempDat / 16 * 10) + (tempDat % 16);tempDat = vReadRam(READ_WEEK);sys_time->week = (tempDat / 16 * 10) + (tempDat % 16);
}

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

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

相关文章

在线教育系统怎么样的呢,音乐培训班学习音乐基本要求有哪些?

现在高考已经不仅仅是学科类就可以&#xff0c;还可以艺术类进行报考&#xff0c;音乐就是艺术类的一种&#xff0c;很多人学音乐都是为了报考更好的院校&#xff0c;音乐机构也越来越多&#xff0c;那培训班学习音乐基本要求有哪些&#xff1f; 一、基础乐理 音乐理论也称乐理…

服装行业如何巧借神秘顾客调查,洞悉门店运营真相

在竞争激烈的服装行业中&#xff0c;洞悉门店运营的真实情况、优化服务体验、提升品牌形象&#xff0c;已成为每个品牌不可或缺的核心任务。而神秘顾客调查&#xff0c;正是一种能够深入门店、精准揭示运营真相的高效手段。在这方面&#xff0c;群狼调研&#xff08;长沙员工满…

Flutter笔记:美工设计.导出视频到RIVE

Flutter笔记 美工设计.导出视频到RIVE - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28…

华为eNSP中型企业局域网网络规划设计(上)

敲半天一个闪退全™给我干没了呜呜呜&#xff0c;eNSP&#xff0c;wcnm&#xff01;wcnm&#xff01;wcnm&#xff01; →b站传送门&#xff0c;感谢大佬← →华为eNSP中型企业局域网网络规划设计&#xff08;下&#xff09;← →拓扑图传送门&#xff0c;可以自己配置着玩←…

Vue从入门到实战Day01

一、Vue快速上手 1. vue概念 概念&#xff1a;Vue是一个用于 构建用户界面的 渐进式 框架 构建用户界面&#xff1a;基于数据动态渲染页面渐进式&#xff1a;循序渐进的学习框架&#xff1a;一套完整的项目解决方案&#xff0c;提升开发效率 优点&#xff1a;大大提升开发效…

springboot集成-Redis

Spring Boot项目中集成Redis&#xff0c;可以使用Spring Data Redis来简化操作。首先需要在pom.xml文件中添加Redis和Spring Data Redis的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

python 统计列表相同数据出现的次数

一、使用for循环 生成数据[randint(0,20) for _ in range(30)]得到 data [18, 11, 16, 18, 2, 15, 6, 6, 4, 8, 16, 19, 8, 17, 6, 14, 7, 1, 3, 2, 8, 17, 4, 6, 18, 11, 15, 16, 3, 3] 要生成的数据格式肯定是一个字典类型&#xff0c;比如{1:5,2:3,5:5}这样的数据&#x…

【Debug日记】albumentations包安装失败解决方案

直接pip安装pip install albumentations 报错&#xff1a; ERROR: Command errored out with exit status 1:command: D:\anaconda3\envs\pytorch\python.exe D:\anaconda3\envs\pytorch\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py build_wheel C:\Users…

如何利用CAM350检查Gerber文件

利用CAM350检查Gerber文件 1、 打开CAM350软件。双击桌面上的CAM350图标以启动软件。 2、选择文件输入选项。在文件菜单中选择“输入”然后选择“自动输入”&#xff0c;因为Gerber文件通常是由EDA软件自动导出的&#xff0c;这样可以快速识别。 3、选择Gerber文件夹。在弹出的…

责任链模式和观察者模式

1、责任链模式 1.1 概述 在现实生活中&#xff0c;常常会出现这样的事例&#xff1a;一个请求有多个对象可以处理&#xff0c;但每个对象的处理条件或权限不同。例如&#xff0c;公司员工请假&#xff0c;可批假的领导有部门负责人、副总经理、总经理等&#xff0c;但每个领导…

C语言——每日一题(轮转数组)

一.前言 前不久学习了时间复杂度的概念&#xff0c;便在力扣上刷了一道需要参考时间复杂度的题——轮转数组 https://leetcode.cn/problems/rotate-array/submissions这道题不能使用暴力算法&#xff0c;因为这道题对时间复杂度的要求不能为O&#xff08;N^2&#xff09;。因…

java博客目录

博客目录 基础知识 集合列表 List ArrayList&#xff1a; LinkedList&#xff1a; Set Map TreeMap 设计模式 单例模式&#xff1a; 工厂方法

如何根据索引删除数组中的元素,并保证删除的正确性

使用 splice() 方法来删除这些索引处的数据 var array [1, 2, 3, 4, 5]; var indexesToDelete [1, 3]; // 需要删除的索引// 将需要删除的索引按照从大到小的顺序排序&#xff0c;以避免删除元素后索引发生变化 indexesToDelete.sort((a, b) > b - a);// 遍历需要删除的索…

Tansformer原理解读

什么是注意力机制 生物学中的注意力机制是指人类或动物能够选择性地将感知和认知资源集中到某些信息或任务上的能力。这种能力允许我们在众多信息的背景中过滤出重要的信息&#xff0c;并将这些信息传递给相应的神经元进行处理。 本质&#xff1a;能从中抓住重点&#xff0c;…

上海市计算机学会竞赛平台2023年7月月赛丙组先行后列

题目描述 从 11 开始的 &#x1d45b;&#x1d45a;nm 个整数按照先行后列的规律排列如下&#xff1a; 第一列第二列第 &#x1d45a;m 列第一行1122……&#x1d45a;m第二行&#x1d45a;1m1&#x1d45a;2m2……2&#x1d45a;2m第三行2&#x1d45a;12m12&#x1d45a;22…

一个好用的短链接都需要具备哪些功能?

大家好&#xff0c;今天我们将会来聊聊一款优秀的短链接&#xff0c;都需要具备的功能&#xff0c;看看是不是你想要的呢&#xff1f; 1. 能够支持自定义域名 现在越来越多的用户都不会选择公用域名了&#xff0c;因为那样风险太大&#xff0c;而会选择用一个他们自己的专用域…

自动控制原理MATLAB:系统分析

控制系统时域分析 &#xff08;1&#xff09;稳定性分析 稳定是控制系统的重要性能&#xff0c;也是系统设计过程中的首要问题。线性系统稳定的充分必要条件是&#xff1a;闭环系统特征方程的所有根均具有负实部。在MATLAB中可以调用roots命令求取特征根&#xff0c;进而判别…

C#实战—代码实现收发文件智能化

在信息化的今天&#xff0c;收发电子文档几乎是每个朋友都要经历的事情。比如班级学委和班长需要收发作业&#xff0c;企业管理者需要收发工作文件。但是&#xff01;&#xff01;&#xff01; 每到要交结果时&#xff0c;往往会发现总会有一些人没有即使交上&#xff0c;50个…

8W 1.5KVDC 隔离宽电压输入 DC/DC 电源模块——TP08DA 系列

TP08DA系列电源模块额定输出功率为8W&#xff0c;外形尺寸为31.80*20.30*10.00&#xff0c;应用于2&#xff1a;1&#xff0c;4:1电压输入范围 9-18V,18-36V,36-72V9V-36V和18V-72VDC的输入电压环境&#xff0c;输出电压精度可达1%&#xff0c;具有输出短路保护等功能&#xff…

“IP协议全解析:为何它是互联网通信的基石?”(包含开源免费的API接口)

IP地址简介 IP地址&#xff08;Internet Protocol Address&#xff09;是指互联网协议地址&#xff0c;又译为网际协议地址。 IP地址是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异…