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,一经查实,立即删除!

相关文章

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;大大提升开发效…

【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…

责任链模式和观察者模式

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

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

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

Tansformer原理解读

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

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

大家好&#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…

图卷积神经网络GCN

计算图 通过消息传递的框架构建一个局部邻域的计算图 每个节点分别构建自己的计算图 理论上任意深度&#xff0c;根据六度空间理论&#xff0c;层数一般不会超过六层 基本过程 数学形式 矩阵表示 代码表示 图计算改进 能够听见自己内心的声音 最终形式 如何训…

windows端口复用

1. 概述 使用 HTTP.sys 中的 Net.tcp Port Sharing 服务&#xff0c;配合 WinRM 实现端口复用。 优点&#xff1a; HTTP.sys 为 windows 原生机制&#xff0c; WinRM 为 windows 自带功能&#xff0c;动作较小&#xff0c;不易触发主 动防御。 需要管理员权限。 2. 原理 (…

鞋店小程序商城的作用是什么

鞋与服装一样其购买/复购属性都非常足&#xff0c;每个人生活所需无疑促进了品牌多样化、工厂/店铺商家/个人都有很多&#xff0c;其目的都是为了品牌宣传和将更多货卖给下游/客户。 对消费者来说&#xff0c;买鞋渠道线上线下选择比较多&#xff0c;普遍会以品牌为主&#xf…

✬ ✬ ✬ 宁波推进ISO14000认证:共创美好生态家园✬ ✬ ✬

&#x1f308;&#x1f308;宁波推进ISO14000认证&#xff0c;&#x1f349;共创美好生态家园&#x1f929; &#x1f603;哇&#xff01;宁波这个大都市&#x1f353;真的在努力推进&#x1f688;ISO14000认证啊&#xff01;&#x1f6b5;‍♀️作为一个环保爱好者&#xff0…

文本批量操作实例:如何实现文本批量拆分?实用方法与技巧分享

在文本处理和数据分析的过程中&#xff0c;我们经常会遇到需要批量拆分大量文本数据的情况。文本批量拆分能够大大提高工作效率&#xff0c;减少重复劳动。下面&#xff0c;我们将通过一个实例来介绍如何实现文本批量拆分&#xff0c;并分享一些实用方法与技巧。 一、实例背景 …

U盘管控软件,禁止员工用U盘拷贝机密数据,防止信息通过U盘泄露

随着信息技术的不断发展&#xff0c;U盘等便携式存储设备已成为我们日常工作中不可或缺的工具。然而&#xff0c;随着U盘的普及&#xff0c;企业面临的信息泄露风险也在不断增加。为了确保企业的信息安全&#xff0c;许多企业开始采用U盘管控软件&#xff0c;禁止员工使用U盘拷…

【YOLOv8改进[Backbone]】使用SCINet改进YOLOv8在黑暗环境的目标检测效果

目录 一 SCINet 1 本文方法 ① 权重共享的照明学习 ② 自校准模块 ③ 无监督训练损失 二 使用SCINet助力YOLOv8在黑暗环境的目标检测效果 1 整体修改 2 配置文件 3 训练 其他 一 SCINet 官方论文地址&#xff1a;https://arxiv.org/pdf/2204.10137 官方代码地址&…

STM32平衡车-MPU6050的DMP库移植

本文目录 一、硬件接线二、需要移植的三个文件夹1. DMP文件夹目录2. IIC文件夹目录3. MPU6050文件夹目录 三、文件内容IO12C.cIO12C.hMPU6050.cMPU6050.hmain.c 四、附录1.更改IIC引脚 一、硬件接线 SCL-- PA11 SDA-- PA12 VCC-- 3.3v GND-- GND 二、需要移植的三个文件夹 1.…

winscp断点续传

背景 超大文件上传&#xff0c; scp可能因为网络或其他原因中断&#xff0c;并且已上传完的文件无法同步。如何断点续传呢&#xff1f;使用winscp软件 winscp安装 百度搜索&#xff0c;自行安装 开启断点续传功能 https://jingyan.baidu.com/article/fdffd1f8395529b2e98ca…