STM32 的 RTC(实时时钟)详解

news2024/11/15 6:49:37

目录

一、引言

二、RTC 概述

三、RTC 的工作原理

1.时钟源

2.计数器

3.闹钟功能

4.备份寄存器

四、RTC 寄存器

1.RTC_TR(Time Register,时间寄存器)

2.RTC_DR(Date Register,日期寄存器) 

3.RTC_SSR(Subsecond Register,亚秒寄存器) 

4.RTC_PRER(Prescaler Register,预分频器寄存器) 

5.RTC_CR(Control Register,控制寄存器) 

6.RTC_ISR(Interrupt Status Register,中断状态寄存器) 

7.RTC_BKPxR(Backup Register,备份寄存器)

五、实际应用

1.时间记录

2.定时任务

3.低功耗模式下的时间保持

六、代码实现 

七、总结 


一、引言

        在嵌入式系统中,准确的时间信息往往是至关重要的。STM32 系列微控制器内置的实时时钟(RTC)模块为系统提供了可靠的时间基准。本文将深入探讨 STM32 的 RTC 的功能、工作原理以及在实际应用中的使用方法

二、RTC 概述

RTC 是一种能够独立运行的时钟模块,即使在微控制器进入低功耗模式时也能保持时间的准确性。STM32 的 RTC 具有以下主要特点:

  1. 高精度计时:能够提供准确的时间信息,包括年、月、日、时、分、秒等。
  2. 低功耗运行:在电池供电的系统中,RTC 可以以极低的功耗运行,延长电池寿命。
  3. 闹钟功能:可以设置闹钟,在特定时间触发中断。
  4. 备份寄存器:用于存储关键数据,即使在系统电源关闭时也能保持数据不丢失。

三、RTC 的工作原理

1.时钟源

  • STM32 的 RTC 可以使用外部低速时钟源(LSE)或内部低速时钟源(LSI)。LSE 通常是一个 32.768kHz 的石英晶体振荡器,具有较高的精度。LSI 是一个内部的低功耗 RC 振荡器,精度相对较低,但在没有外部晶体的情况下可以作为备用时钟源。
  • 时钟源经过分频后为 RTC 提供计时脉冲。

2.计数器

  • RTC 包含一个可编程的预分频器和一个 32 位的计数器。预分频器用于将时钟源的频率分频到合适的频率,以满足不同的计时需求。计数器则根据预分频器输出的脉冲进行计数,从而实现时间的累加。
  • 通过读取计数器的值,可以获取当前的时间信息。

3.闹钟功能

  • RTC 可以设置多个闹钟,每个闹钟可以独立配置。闹钟可以基于特定的时间(如小时、分钟、秒)或日期(年、月、日)触发中断。
  • 当闹钟时间到达时,RTC 会产生一个中断信号,通知微控制器进行相应的处理。

4.备份寄存器

  • STM32 的 RTC 具有多个备份寄存器,可以用于存储关键数据。这些寄存器在系统电源关闭时由备用电源(如电池)供电,以确保数据不丢失。
  • 备份寄存器可以用于存储系统配置参数、校准数据等重要信息。

四、RTC 寄存器

1.RTC_TR(Time Register,时间寄存器)

  • 功能:用于存储当前的时间信息,包括小时、分钟、秒等。
  • 位定义
    • pm:占 1 位,用于表示上午 / 下午(AM/PM)符号,0 表示 AM/24 小时制,1 表示 PM。
    • ht(1:0):占 2 位,是小时的十位部分。
    • hu(3:0):占 4 位,是小时的个位部分。
    • mnt(2:0):占 3 位,为分钟的十位部分。
    • mnu(3:0):占 4 位,是分钟的个位部分。
    • st(2:0):占 3 位,代表秒的十位部分。
    • su(3:0):占 4 位,是秒的个位部分。
  • 操作注意事项:数据是以 BCD 码格式存储的,读取之后需要进行转换才能得到常规的十进制时间数据。在初始化模式下,对该寄存器进行写操作可以设置时间。

2.RTC_DR(Date Register,日期寄存器) 

  • 功能:保存当前的日期信息,包含年、月、日、星期等。
  • 位定义
    • yt(1:0):占 2 位,是年份的十位部分。
    • yu(3:0):占 4 位,为年份的个位部分。
    • wdu(2:0):占 3 位,表示星期几的个位,000 表示禁止,001 表示星期一,以此类推,111 表示星期日。
    • mt:占 1 位,是月份的十位部分。
    • mu:占 4 位,为月份的个位部分。
    • dt(1:0):占 2 位,代表日期的十位部分。
    • du(3:0):占 4 位,是日期的个位部分。
  • 操作要点:同样以 BCD 码格式存储数据,写操作可设置日期。

3.RTC_SSR(Subsecond Register,亚秒寄存器) 

  • 功能:用于记录亚秒值,能够提供更高精度的时间信息,通常用于精确到毫秒或更短时间单位的时间记录。
  • 计算亚秒值:亚秒值的计算需要结合同步预分频器的值。公式为亚秒值 = (prediv_s – ss(15:0)) / (prediv_s + 1),其中 ss(15:0) 是同步预分频器计数器的值,prediv_s 是同步预分频器的值。

4.RTC_PRER(Prescaler Register,预分频器寄存器) 

  • 组成:由 7 位的异步预分频器 apre 和 15 位的同步预分频器 spre 组成。
  • 功能:对输入的时钟源进行分频,以得到合适的时钟频率用于 RTC 的时间和日期更新。异步预分频器时钟 ck_apre 用于为二进制 RTC_SSR 亚秒递减计数器提供时钟,同步预分频器时钟 ck_spre 用于更新日历。
  • 时钟频率计算:异步预分频器时钟 fck_apre = frtc_clk / (prediv_a + 1),同步预分频器时钟 fck_spre = frtc_clk / (prediv_s + 1)。为了最大程度降低功耗,一般将异步预分频器配置为较高的值。

5.RTC_CR(Control Register,控制寄存器) 

  • 功能:用于控制 RTC 的各种功能,如开启或关闭 RTC、设置闹钟使能、选择时钟源等。
  • 具体位的作用:不同的位具有不同的功能,例如可能有位用于使能闹钟输出、配置闹钟输出的极性、设置时间戳功能等。

6.RTC_ISR(Interrupt Status Register,中断状态寄存器) 

  • 功能:反映 RTC 的各种中断状态,例如闹钟中断标志位、时间戳中断标志位等。当相应的事件发生时,对应的标志位会被置位,通过读取该寄存器可以判断中断是否发生以及发生的是哪种中断。

7.RTC_BKPxR(Backup Register,备份寄存器)

  • 功能:STM32 的 RTC 有备份寄存器,包括 20 个 32 位寄存器,用于存储用户应用数据。这些寄存器在备份域中实现,可在 VDD 电源关闭时通过 VBAT 保持上电状态。备份寄存器不会在系统复位或电源复位时复位,也不会在器件从待机模式唤醒时复位。它可用于在掉电等情况下保存一些关键数据。

五、实际应用

1.时间记录

  • 在数据采集系统中,RTC 可以用于记录数据的采集时间,以便后续分析和处理。
  • 在日志记录系统中,RTC 可以为每条日志记录添加时间戳,方便查看和分析系统的运行情况。

2.定时任务

  • 可以使用 RTC 的闹钟功能来实现定时任务,如在特定时间执行特定的操作。例如,在智能家居系统中,可以设置在特定时间打开或关闭电器设备。
  • 在工业自动化系统中,RTC 可以用于定时控制生产过程中的各个环节。

3.低功耗模式下的时间保持

在低功耗应用中,当微控制器进入低功耗模式时,RTC 可以继续运行,保持时间的准确性。当系统从低功耗模式唤醒时,可以通过 RTC 获取当前的时间信息,无需重新初始化时间。

六、代码实现 

以下是一个使用 STM32F429 的 RTC(实时时钟)的代码示例:

#include "stm32f4xx.h"
#include "stm32f4xx_hal.h"

void RTC_Init(void)
{
    // 使能电源时钟和备份区域时钟
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_RCC_BKPSRAM_CLK_ENABLE();

    // 允许访问备份寄存器
    HAL_PWR_EnableBkUpAccess();

    // 检查是否已经配置过 RTC
    if ((RCC->BDCR & RCC_BDCR_RTCEN)!= 0)
    {
        // RTC 已经配置过,无需再次初始化
        return;
    }

    // 选择 LSE 作为 RTC 时钟源
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
    {
        Error_Handler();
    }

    // 使能 RTC 时钟
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    {
        Error_Handler();
    }

    // 初始化 RTC
    RTC_HandleTypeDef hrtc;
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 0x7F;
    hrtc.Init.SynchPrediv = 0xFF;
    hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
    hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    if (HAL_RTC_Init(&hrtc)!= HAL_OK)
    {
        Error_Handler();
    }
}

void RTC_SetTime(uint8_t hour, uint8_t minute, uint8_t second)
{
    RTC_TimeTypeDef sTime = {0};
    sTime.Hours = hour;
    sTime.Minutes = minute;
    sTime.Seconds = second;
    sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN)!= HAL_OK)
    {
        Error_Handler();
    }
}

void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day)
{
    RTC_DateTypeDef sDate = {0};
    sDate.Year = year;
    sDate.Month = month;
    sDate.Date = day;
    sDate.WeekDay = RTC_WEEKDAY_MONDAY;
    if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN)!= HAL_OK)
    {
        Error_Handler();
    }
}

void RTC_GetTime(uint8_t *hour, uint8_t *minute, uint8_t *second)
{
    RTC_TimeTypeDef sTime;
    if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN)!= HAL_OK)
    {
        Error_Handler();
    }
    *hour = sTime.Hours;
    *minute = sTime.Minutes;
    *second = sTime.Seconds;
}

void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day)
{
    RTC_DateTypeDef sDate;
    if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN)!= HAL_OK)
    {
        Error_Handler();
    }
    *year = sDate.Year;
    *month = sDate.Month;
    *day = sDate.Date;
}

void Error_Handler(void)
{
    // 处理错误
    while (1)
    {
    }
}

在主函数中,可以这样调用:

int main(void)
{
    HAL_Init();

    RTC_Init();

    // 设置时间为 12:30:00
    RTC_SetTime(12, 30, 0);

    // 设置日期为 2023 年 9 月 14 日
    RTC_SetDate(23, 9, 14);

    uint8_t hour, minute, second;
    uint8_t year, month, day;

    // 获取时间和日期并打印
    RTC_GetTime(&hour, &minute, &second);
    RTC_GetDate(&year, &month, &day);

    while (1)
    {
    }
}

七、总结 

        STM32 的 RTC 模块为嵌入式系统提供了可靠的时间基准。通过了解 RTC 的工作原理、配置方法和应用场景,开发者可以充分利用 RTC 的功能,为系统添加时间记录、定时任务等功能,提高系统的实用性和可靠性。在使用 RTC 时,需要注意时钟源的选择、时间的初始化和校准以及备份寄存器的使用等问题,以确保 RTC 的正常运行和数据的安全性。

希望本文对大家在使用 STM32 的 RTC 模块时有所帮助。

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

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

相关文章

R语言统计分析——功效分析(比例、卡方检验)

参考资料:R语言实战【第2版】 1、比例检验 当比较两个比例时,可使用pwr.2p.test()函数进行功效分析。格式为: pwr.2p.test(h, n, sig.level, power, alternative) 其中,h是效应值,n是各相同的样本量。效应值h的定义如…

性能测试-jmeter提取器(十三)

一、jmeter的常用关联 正则表达式提取器xpath提取器json提取器 二、正则表达式提取器 注&#xff1a;&#xff08;正则表达式的变量与引用的变量的区别&#xff1a;引用变量多加了"_1"后缀&#xff09; 需求&#xff1a;将www.itcast.cn网页时&#xff0c;<ti…

【JAVA开源】基于Vue和SpringBoot的校园管理系统

本文项目编号 T 026 &#xff0c;文末自助获取源码 \color{red}{T026&#xff0c;文末自助获取源码} T026&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 管…

每日一练:游游的u

1.题目 2.代码 #include <iostream> using namespace std;int main() {int q 0;cin >> q;int a,b,c;while(q--){cin >> a >> b >> c;int you min(a,min(b,c)) * 2;int ooo max(b-(you/2)-1,0);cout << (you ooo) << endl;}retu…

【计算机毕设-大数据方向】基于Hadoop的社交媒体数据分析可视化系统的设计与实现

&#x1f497;博主介绍&#xff1a;✌全平台粉丝5W,高级大厂开发程序员&#x1f603;&#xff0c;博客之星、掘金/知乎/华为云/阿里云等平台优质作者。 【源码获取】关注并且私信我 【联系方式】&#x1f447;&#x1f447;&#x1f447;最下边&#x1f447;&#x1f447;&…

[ComfyUI]Flux:写真新篇章!字节PuLID率先开启一致性风格迁移,无损画手和优质画面保持

前言 Flux&#xff1a;PuLID率先开启F1写真新篇章 所有的AI设计工具&#xff0c;模型和插件&#xff0c;都已经整理好了&#xff0c;&#x1f447;获取~ Flux PuLID简介 在Flux出来后短时间内&#xff0c;社区生态反响和发展足够的迅猛快速。至今为止&#xff0c;社区LORA模…

力扣每日一题:236.二叉树的最近公共祖先

题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它…

<<编码>> 第 11 章 逻辑门电路(Gates)--猫咪选择电路 示例电路

使用门电路的猫咪选择电路 info::操作说明 鼠标单击开关切换开合状态 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/code-hlchs-examples/assets/circuit/code-hlchs-ch11-16-cat-circuit-with-gate.txt 集成的猫咪选择电路 in…

html+css+js网页设计 旅游 厦门旅游网11个页面

htmlcssjs网页设计 旅游 厦门旅游网11个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&am…

WPF 手撸插件 八 依赖注入

本文内容大量参考了&#xff1a;https://www.cnblogs.com/Chary/p/11351457.html 而且这篇文章总结的非常好。 1、注意想使用Autofac&#xff0c;Autofac是一个轻量级、‌高性能的依赖注入&#xff08;‌DI&#xff09;‌框架&#xff0c;‌主要用于.NET应用程序的组件解耦和…

Halcon 深度学习 分类预处理

文章目录 read_dl_dataset_classification 产生一个深度学习数据集算子split_dl_dataset 将样本分为训练、验证和测试子集create_dl_preprocess_param 使用预处理参数创建字典preprocess_dl_dataset 预处理DLDataset中声明的整个数据集write_dict 写入字典文件find_dl_samples …

[网络]TCP/IP五层协议之应用层,传输层(1)

文章目录 一. 应用层二. 传输层端口号传输层的协议UDPTCPTCP报头TCP协议的核心机制 一. 应用层 应用层是和应用程序直接相关, 和程序猿打交道最多的一层 应用层协议, 里面描述的内容, 就是你写的程序, 通过网络具体按照啥样的形式来传输数据 不同的应用程序, 就可以用不同的应…

PHP 使用Spreadsheet写excel缓存导致内存不断增加

这里写自定义目录标题 问题描述问题解决 问题描述 新增了 Spreadsheet 用于写 excle 文件。 从网上查找一些实例后&#xff0c;封装成 createExcelFormData 函数如下&#xff1a; /*** brief 按照指定的键&#xff0c;将 array2(关联数组) 合并到 array1(关…

【C#】VS插件

翻译 目前推荐较多的 可以单词发言&#xff0c;目前还在开发阶段 TranslateIntoChinese - Visual Studio Marketplace 下载量最高的(推荐) Visual-Studio-Translator - Visual Studio Marketplace 支持翻译的版本较多&#xff0c;在 Visual Studio 代码编辑器中通过 Googl…

YOLOV8实现小目标检测

YOLOV8小目标检测 前言&#xff1a;&#xff1a; yolo版出现很多&#xff0c;基本大同小异 但是这些差异让我们考虑在实验中使用哪个版本会比较好&#xff01; 在对小目标检测的过程中&#xff0c;yolov7相比yolov8性能更加好。 如果我们还是想使用yolov8&#xff0c;也是可以实…

大模型获利「攻略」浮出水面!ToC 蓬勃发展,ToB 蕴含奥秘

前言 自去年引发“百模大战”&#xff0c;到近日开启“行业价格战”&#xff0c;中国大模型行业迈入了新的发展阶段。在近期的智源大会上&#xff0c;众多专家分享了对大模型发展现状的见解。结合 IDC 近期发布的大模型实测报告以及 Scale AI 的“AI 就绪报告”&#xff0c;大…

热榜:24年秋招没有金九银十?地信应届生想就业,如何入场?

秋招的“金九银十”即将结束&#xff0c;你的秋招到哪一步了&#xff1f; 是早已收获满满offer&#xff0c;还是仍然在海投面试中&#xff0c;亦或者根本没开始呢&#xff1f; 2024年的就业环境到底如何&#xff1f;上周&#xff0c;“2024年的就业环境到底如何&#xff1f;”…

LeetCode(04) 最接近的三数之和 【双指针】

题目描述 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 解题思路 首先进行数组排序&#xff0c;时间复杂度 O(nlogn)&#xff1b;在…

花3000元自学AI大模型后,她薪水涨了20%

“我看到了一个充满无限可能的新世界”&#xff0c;在面试完AI产品经理这一岗位后&#xff0c;陈漫在社交平台上如此描述自己的感受。 AGI大模型浪潮席卷全球&#xff0c;技术革新越是凶猛&#xff0c;人们的失业焦虑便越加强烈。为了应对AI带来的冲击&#xff0c;有些人决定“…

c++—多态【万字文章】

目录 C—多态1.多态的概念2.多态的定义及实现2.1多态的构成条件2.2虚函数的重写2.2.1虚函数重写的两个例外&#xff1a;2.2.1.1协变2.2.1.2析构函数的重写 2.3 c11的override和final2.3.1final2.3.2override 2.4 重载、重写、重定义的对比 3.抽象类3.1抽象类的概念3.2接口继承和…