基于STM32的DS1302实时时钟模块应用

news2024/9/28 20:05:18

DS1302是一款低功耗的实时时钟芯片,被广泛应用于各种电子产品中。它具有准确计时、多种时间格式表示、定时报警等功能,适用于记录时间、日期和闹钟。在本文中,我们将介绍如何在基于STM32的开发环境中使用DS1302实时时钟模块,并给出一个完整的示例代码。

硬件连接:
首先,我们需要准备以下硬件:
- STM32单片机开发板
- DS1302实时时钟模块

连接方法如下:
- 将DS1302的SCK引脚连接到STM32的SCK引脚
- 将DS1302的SDA引脚连接到STM32的SDA引脚
- 将DS1302的RST引脚连接到STM32的RST引脚
- 将DS1302的VCC引脚连接到STM32的VCC引脚(一般为3.3V)
- 将DS1302的GND引脚连接到STM32的GND引脚

软件实现:
以下是一个基于STM32的DS1302实时时钟模块应用的示例代码:

```c
#include "stm32f10x.h"
#include "ds1302.h"

int main(void)
{
    // 初始化DS1302模块
    DS1302_Init();

    while (1)
    {
        // 读取实时时钟的时间
        uint8_t hour, minute, second;
        DS1302_GetTime(&hour, &minute, &second);

        // 读取实时时钟的日期
        uint8_t year, month, day;
        DS1302_GetDate(&year, &month, &day);

        // 在串口输出时间和日期
        printf("Current time: %02d:%02d:%02d\r\n", hour, minute, second);
        printf("Current date: %02d-%02d-%02d\r\n", year, month, day);

        // 延时一段时间
        delay_ms(1000);
    }
}
```

以上是一个简单的应用示例,该示例通过DS1302模块获取当前的时间和日期,并通过串口输出。在实际应用中,可以根据需要添加其他功能,如定时报警、时间设置等。

需要注意的是,在使用该示例代码之前,你需要提前编写一个适配器库`ds1302.h`和`ds1302.c`,用于实现DS1302模块的初始化、读写时间和日期等操作。你可以根据DS1302的数据手册编写适配器库,或者找到第三方提供的库。

接下来,我们将详细介绍如何编写`ds1302.h`和`ds1302.c`,以及其中的各个函数的实现。在这份代码中,我们假设使用的是STM32的标准外设库进行开发。

ds1302.h:

```c
#ifndef DS1302_H
#define DS1302_H

#include <stdint.h>

void DS1302_Init(void);
void DS1302_GetTime(uint8_t *hour, uint8_t *minute, uint8_t *second);
void DS1302_GetDate(uint8_t *year, uint8_t *month, uint8_t *day);
void DS1302_SetTime(uint8_t hour, uint8_t minute, uint8_t second);
void DS1302_SetDate(uint8_t year, uint8_t month, uint8_t day);

#endif
```

ds1302.c:

```c
#include "ds1302.h"
#include "stm32f10x.h"

// DS1302模块引脚定义
#define DS1302_RST_PIN GPIO_Pin_0
#define DS1302_SCK_PIN GPIO_Pin_1
#define DS1302_IO_PIN GPIO_Pin_2
#define DS1302_PORT GPIOB

// DS1302模块相关函数
void DS1302_WriteByte(uint8_t dat)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIO_ResetBits(DS1302_PORT, DS1302_SCK_PIN);
        if (dat & 0x01)
            GPIO_SetBits(DS1302_PORT, DS1302_IO_PIN);
        else
            GPIO_ResetBits(DS1302_PORT, DS1302_IO_PIN);
        GPIO_SetBits(DS1302_PORT, DS1302_SCK_PIN);
        dat >>= 1;
    }
}

uint8_t DS1302_ReadByte(void)
{
    uint8_t i, dat = 0;
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(DS1302_PORT, &GPIO_InitStructure);

    for (i = 0; i < 8; i++)
    {
        dat >>= 1;
        GPIO_ResetBits(DS1302_PORT, DS1302_SCK_PIN);
        if (GPIO_ReadInputDataBit(DS1302_PORT, DS1302_IO_PIN))
            dat |= 0x80;
        GPIO_SetBits(DS1302_PORT, DS1302_SCK_PIN);
    }

    return dat;
}

void DS1302_Write(uint8_t reg, uint8_t dat)
{
    GPIO_ResetBits(DS1302_PORT, DS1302_RST_PIN);
    DS1302_WriteByte(reg);
    DS1302_WriteByte(dat);
    GPIO_SetBits(DS1302_PORT, DS1302_RST_PIN);
}

uint8_t DS1302_Read(uint8_t reg)
{
    uint8_t dat;
    GPIO_ResetBits(DS1302_PORT, DS1302_RST_PIN);
    DS1302_WriteByte(reg | 0x81);
    dat = DS1302_ReadByte();
    GPIO_SetBits(DS1302_PORT, DS1302_RST_PIN);

    return dat;
}

void DS1302_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = DS1302_RST_PIN | DS1302_SCK_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(DS1302_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(DS1302_PORT, &GPIO_InitStructure);

    DS1302_Write(0x8e, 0x00);  // 写入禁止写保护命令
}

void DS1302_GetTime(uint8_t *hour, uint8_t *minute, uint8_t *second)
{
    uint8_t data[3];
    for (int i = 0; i < 3; i++)
    {
        data[i] = DS1302_Read(0x81 + i * 2);  // 从RAM中读取时间数据
        if (i == 0)
            *second = ((data[0] & 0x0F) + (data[0] >> 4) * 10);
        else if (i == 1)
            *minute = ((data[1] & 0x0F) + (data[1] >> 4) * 10);
        else
            *hour = ((data[2] & 0x0F) + (data[2] >> 4) * 10);
    }
}

void DS1302_GetDate(uint8_t *year, uint8_t *month, uint8_t *day)
{
    uint8_t data[3];
    for (int i = 0; i < 3; i++)
    {
        data[i] = DS1302_Read(0x81 + i * 2 + 6);  // 从RAM中读取日期数据
        if (i == 0)
            *day = ((data[0] & 0x0F) + (data[0] >> 4) * 10);
        else if (i == 1)
            *month = ((data[1] & 0x0F) + (data[1] >> 4) * 10);
        else
            *year = ((data[2] & 0x0F) + (data[2] >> 4) * 10);
    }
}

void DS1302_SetTime(uint8_t hour, uint8_t minute, uint8_t second)
{
    // 禁止写保护
    DS1302_Write(0x8e, 0x00);
    
    // 写入时间数据到RAM
    DS1302_Write(0x80, (second / 10) << 4 | (second % 10));
    DS1302_Write(0x82, (minute / 10) << 4 | (minute % 10));
    DS1302_Write(0x84, (hour / 10) << 4 | (hour % 10));

    // 打开写保护
    DS1302_Write(0x8e, 0x80);
}

void DS1302_SetDate(uint8_t year, uint8_t month, uint8_t day)
{
    // 禁止写保护
    DS1302_Write(0x8e, 0x00);

    // 写入日期数据到RAM
    DS1302_Write(0x86, (day / 10) << 4 | (day % 10));
    DS1302_Write(0x88, (month / 10) << 4 | (month % 10));
    DS1302_Write(0x8c, (year / 10) << 4 | (year % 10));

    // 打开写保护
    DS1302_Write(0x8e, 0x80);
}
```

以上是一个基于STM32的DS1302实时时钟模块的完整示例代码。在这个示例中,我们实现了DS1302模块的初始化,读取时间和日期,设置时间和日期等操作,并给出了相应的函数实现。需要注意的是,具体的引脚定义、外设时钟使能等操作可能会根据你的实际硬件环境而有所不同,你需要根据自己的实际情况进行相应的调整。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

代码获取、问题探讨及文章转载可私信。

 ☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

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

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

相关文章

【重点!!!】【单调栈】84.柱状图中最大矩形

题目 法1&#xff1a;单调栈[原版] O(N)O(N) 必须掌握算法&#xff01;&#xff01;&#xff01; class Solution {public int largestRectangleArea(int[] heights) {int n heights.length, res 0;int[] leftMin new int[n], rightMin new int[n];Stack<Integer>…

开源项目解读 —— Self-Operating Computer Framework # 长期主义 # 价值

价值&#xff1a;生成主函数业务逻辑函数思维导图&#xff0c;帮助理解&#xff0c;PR到开源项目&#xff0c;希望帮助大家理解IPA工作原理&#xff0c;国内没有好的开源项目&#xff0c;我就来翻译分析解读&#xff0c;给大家抛砖引玉。思维导图用文心一言配合其思维导图插件实…

jar 运行清单文件MANIFEST.MF生成定义Main-Class Premain-Class IDEA maven-assembly-plugin

可运行jar文件中的启动清单文件 META-INF/MANIFEST.MF 内容自定义生成 清单文件中的 Main-Class: Premain-Class: Can-Retransform-Classes: 在maven-assembly-plugin插件中的生成配置如下, 注意命名 <archive> <manifest> <mainClass>c…

华为设备VRP系统管理

为了满足企业业务对网络的需求&#xff0c;网络设备中的系统文件需要不断进行升级。另外&#xff0c;网络设备中的配置文件也需要时常进行备份&#xff0c;以防设备故障或其他灾害给业务带来损害。在升级和备份系统文件或配置文件时&#xff0c;经常会使用FTP和TFTP来传输文件。…

浅谈Springboot默认logger函数的使用

目录 前言1. logger日志2. 补充 前言 原先写过一篇logger日志函数的总结&#xff0c;不同的引用来源&#xff1a;java常见log日志的使用方法详细解析 但是为了不引入依赖包&#xff0c;更好的直接使用&#xff0c;总结了如下博文 1. logger日志 Spring Boot使用Spring框架中…

基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道

作者&#xff1a;尹航 在前文基于阿里云服务网格流量泳道的全链路流量管理&#xff08;一&#xff09;&#xff1a;严格模式流量泳道中&#xff0c;我们介绍了使用服务网格 ASM 的严格模式流量泳道进行全链路灰度管理的使用场景。该模式对于应用程序无任何要求&#xff0c;只需…

语法树的画法(根据文法求字符串)

目录 1.语法树的画法 2.语法树的短语 3.直接短语&#xff08;直接到根部&#xff09; 4.素短语 5.句柄 6.算符优先分析句型 1.语法树的画法 文法G[E]:E->EE | E*E | (E) | i ,字符串 ii*i 推导方式有两种最左推导和最右推导&#xff08;推导的技巧就是逐步靠近字符串…

数禾使用 Knative 加速 AI 模型服务部署丨KubeCon China 2023

作者&#xff1a;李鹏&#xff08;阿里云&#xff09;、魏文哲&#xff08;数禾科技&#xff09;&#xff0c; 此文基于 KubeCon China 2023 分享整理 摘要 AI 服务的数据、训练、推理等都需要消耗大量的计算资源以及运维成本&#xff0c;在数禾科技的金融业务场景下&#xf…

LaTex中参考文献引用

一、引用参考文献 这里我们使用的是BibTeX的引用格式&#xff0c;因此文件中应包括两个文件&#xff08;.bib-参考文献 和 .bst-文献格式&#xff09;。 有了这两个文件后&#xff0c;我们在bib文件中创建参考文献&#xff1a;&#xff08;注意&#xff0c;作者的名字是逗号前…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Image图片组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Image图片组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Image组件 Image 用来加载并显示图片的基础组件&#xff0c;它支持从内存、本…

Ps:图框工具

图框工具 Frame Tool是自 Ps 2019 版开始新增的一个工具。 图框 Frame可用于限制图像的显示范围&#xff0c;在设计过程中&#xff0c;还常常可起到占位符的功能。 快捷键&#xff1a;K 使用图框工具&#xff0c;对于快速相册排版、创建某种形式的特效等有一定的帮助。比起使用…

变量的存储类型(storage class)

变量的存储类型(storage class) 对于变量的存储类型&#xff0c;前面遇到过一些疑惑&#xff0c;再简单的在这里说一下。存储类型是指存储变量值的内存类型&#xff0c;它用来决定存储空间的大小。变量的存储类型决定着变量的存储器和作用域。有三个地方可以用于存储变量&#…

java进阶(二)-java小干货

java一些精干知识点分享 2. java小干货2.1循环遍历2.2可变参数2.3 list和数组转化2.3.1 数组转list2.3.2 list转数组 2.4 值传递和地址传递2.4.1值传递2.4.2 地址传递2.4.3易错点总结 2.5 数组数组帮助类Arrays 2.5 基本数据类型和包装类2.5集合2.6文件流2.7java代码块、内部类…

MQ(消息队列)相关知识

1. 什么是mq 消息队列是一种“先进先出”的数据结构 2. 应用场景 其应用场景主要包含以下3个方面 应用解耦 系统的耦合性越高&#xff0c;容错性就越低。以电商应用为例&#xff0c;用户创建订单后&#xff0c;如果耦合调用库存系统、物流系统、支付系统&#xff0c;任何…

python dash 写一个登陆页 4

界面 代码&#xff1a; 这里引入了dash_bootstrap_components 进行界面美化 &#xff0c;要记一些className&#xff0c;也不是原来说的不用写CSS了。 from dash import Dash, html, dcc, callback, Output, Input, State import dash_bootstrap_components as dbcapp Dash(…

Git安装及基本操作

1.安装Git 配置用户 git config --global user.name "用户名" git config --global user.email "邮箱"配置完成后查看配置 git config -l生成SSH秘钥 ssh-keygen -t rsa -C “邮箱” 输入完成后需要按3次Enter键 $ ssh-keygen -t rsa -C "邮箱&quo…

【MySQL学习笔记009】事务

一、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 二、事务操作 1、操作1 查看/设置事务提交方式 select a…

基于Hexo+GitHub Pages 的个人博客搭建

基于HexoGitHub Pages 的个人博客搭建 步骤一&#xff1a;安装 Node.js 和 Git步骤二&#xff1a;创建Github Pages 仓库步骤二&#xff1a;安装 Hexo步骤三&#xff1a;创建 Hexo 项目步骤四&#xff1a;配置 Hexo步骤五&#xff1a;创建新文章步骤六&#xff1a;生成静态文件…

c语言:从函数中返回指针

return关键词可以从被调函数中返回一个值到主调函数。现在我们尝试让它返回一个指针到主调函数中。 #include <stdio.h> int* func() { int n 100; return &n; } int main() { int* p func(); printf("%d\n", *p); return 0; } 我们在函数 func 中定义…

【FPGA 器件比较】Altera -- Xilinx

比较以下市场前二名的产品线及定位 应用场景XilinxAltera高性能VersalAgilex F/I性能Virtex / Kintex / Artix / Zynq UltraScaleAgilex F/I / Stratix 10中档Virtex / Kintex / Zynq ~ 7 / UltraScaleStratix 10 / Arria 10低成本Artix-7 Sparton-7Cyclone 10 如上表&#x…