ARM32开发--RTC内置实时时钟

2024-06-12 23:12

本文主要是介绍ARM32开发--RTC内置实时时钟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

知不足而奋进 望远山而前行


目录

系列文章目录

文章目录

前言

学习目标

学习内容

RTC时钟介绍

RTC结构框图

RTC原理图

RTC时钟电源

RTC的配置流程

RTC时钟

开发流程

RTC初始化

时钟配置

时钟获取

BCD格式转化

完整代码

RTC时钟备份寄存器

总结


前言

在嵌入式系统开发中,实时时钟(RTC)是至关重要的组件,它提供了准确的日期和时间信息,为各种应用场景提供了时间基准。本文将深入探讨RTC的设计原理和初始化过程,帮助您理解RTC在GD32F407上的实现方式以及如何进行初始化、配置和读取时间等操作。


学习目标

  1. 理解原理图RTC设计部分
  2. 掌握初始化RTC
  3. 掌握设置时间
  4. 掌握读取时间

学习内容

RTC时钟介绍

RTC是实时时钟(Real-Time Clock)的缩写。它是一种硬件模块或芯片,用于提供准确的日期和时间信息。

GD32F407上有RTC的外设,它提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。

RTC本质上就是一个1秒计数器,通过秒来换算出时间。因此需要我们提供一个1HZ频率的时钟。

RTC结构框图

RTC原理图

RTC时钟电源

RTC时钟分为两个电源域。RTC的核心部分位于备份域中。系统复位或从待机模式唤醒时,RTC的设置和时间都保持不变。另一部分包括APB接口及一组控制寄存器位于VDD电源域中。

RTC的配置流程

RTC时钟

开发流程
  1. 加载依赖。gd32f4xx_rtc.c,gd32f4xx_pmu.c
  2. 初始化RTC。
  3. 时钟配置。
  4. 获取时钟。
RTC初始化
// 电池管理加载
rcu_periph_clock_enable(RCU_PMU);
pmu_backup_write_enable();// 重置备份域(不重置可能导致无法设置晶振,出现不走字情况)
/* reset backup domain */
rcu_bkp_reset_enable();
rcu_bkp_reset_disable();// 2. 设置时钟的晶振 LXTAL (低速外部时钟, 需焊接)
// rcu_osci_on(RCU_LXTAL);
// rcu_osci_stab_wait(RCU_LXTAL);
// rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);// 2. 设置时钟的晶振 IRC32K
// rcu_osci_on(RCU_IRC32K);
// // 等待晶振稳定
// rcu_osci_stab_wait(RCU_IRC32K);
// /* 给rtc配置晶振 configure the RTC clock source selection */
// rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);// 2. 设置时钟的晶振 HXTAL -> 8Mrcu_osci_on(RCU_HXTAL);// 等待晶振稳定rcu_osci_stab_wait(RCU_HXTAL);/* 给rtc配置晶振 configure the RTC clock source selection */rcu_rtc_clock_config(RCU_RTCSRC_HXTAL_DIV_RTCDIV);// 分频系数(HXTAL时,需要配置) // DIV25 -> 320Krcu_rtc_div_config(RCU_RTC_HXTAL_DIV25); // RTC功能加载
rcu_periph_clock_enable(RCU_RTC);
rtc_register_sync_wait();
  • RTC电源供应为外部独立电路,需要加载电源管理,打开rtc电源供应。
  • 重置备份域,不重置可能导致无法设置晶振,出现时钟不走字情况。
  • RTC的时钟晶振为外部,需要加载外部晶振。
  • 加载完成过程,需要等待同步。

时钟配置
rtc_parameter_struct rps;
rps.year = 0x23;
rps.month = 0x04;
rps.date = 0x20;
rps.day_of_week = 0x04;
rps.hour = 0x23;
rps.minute = 0x59;
rps.second = 0x55;
rps.display_format = RTC_24HOUR;
rps.am_pm = RTC_AM;
// 配置异步和同步分频器数值 LXTAL
// rps.factor_asyn = 0x7F;
// rps.factor_syn = 0xFF;// 配置异步和同步分频器数值IRC32K
//  rps.factor_asyn = 0x7F;   // 7位异步预分频器, 0x0 - 0x7F
//  rps.factor_syn  = 0xF9;   // 15位同步预分频器。0x0 - 0x7FFF// IRC32K ck_spre = 1 -> 1秒 -> 1个时钟 (1Hz)
// ck_spre = rtc_clk / ((FACTOR_A + 1)*( FACTOR_S + 1))
// 1 = 32K / ((0x7F + 1)*( FACTOR_S + 1))
// FACTOR_S = 32K / 0x80 - 1 = 32K / 128 - 1 = 249// 配置异步和同步分频器数值HXTAL_DIV25
rps.factor_asyn = 127;   // 7位异步预分频器, 0x0 - 0x7F
rps.factor_syn  = 2499;   // 15位同步预分频器。0x0 - 0x7FFF// HXTAL_DIV25 -> 8M/25 -> 320K
// ck_spre = 1 -> 1秒 -> 1个时钟 (1Hz)
// ck_spre = rtc_clk / ((FACTOR_A + 1)*( FACTOR_S + 1))
// 1 = 320K / ((0x7F + 1)*( FACTOR_S + 1))
// FACTOR_S = 320K / 0x80 - 1 = 32K / 128 - 1 = 2499rtc_init(&rps);

1 = rtc_clk/(asyn + 1)/(syn + 1)

  • asyn取值范围为0到0x7F
  • syn取值范围为0到0x07FF
时钟获取
rtc_parameter_struct rps;
rtc_current_time_get(&rps);uint16_t year = READ_BCD(rps.year) + 2000;
uint8_t month = READ_BCD(rps.month);
uint8_t date = READ_BCD(rps.date);
uint8_t week = READ_BCD(rps.day_of_week);
uint8_t hour = READ_BCD(rps.hour);
uint8_t minute = READ_BCD(rps.minute);
uint8_t second = READ_BCD(rps.second);printf("%d-%d-%d %d %d:%d:%d\r\n", year, month, date, week, hour, minute, second);
BCD格式转化

BCD(Binary-Coded Decimal,二进制编码十进制)是一种用于表示十进制数字的二进制编码形式。在RTC(实时时钟)等应用中,BCD格式常用于存储和显示日期和时间信息。它的主要特点是每个十进制数位都被编码成4位二进制数。

在BCD格式中,一个十进制数的每一位被表示为4位二进制数,其中每个二进制数位都对应一个十进制数位。例如:

  • 十进制数 0 用BCD表示为 0000。
  • 十进制数 1 用BCD表示为 0001。
  • 十进制数 9 用BCD表示为 1001。

这样,一个BCD字节(8位)可以表示两个十进制数字。

// 十位取出左移4位 + 个位 (得到BCD数)
#define WRITE_BCD(val) 	((val / 10) << 4) + (val % 10)
// 将高4位乘以10 + 低四位 (得到10进制数)
#define READ_BCD(val) 	(val >> 4) * 10 + (val & 0x0F)
完整代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart.h"// 十位取出左移4位 + 个位 (得到BCD数)
#define WRITE_BCD(val) 	((val / 10) << 4) + (val % 10)
// 将高4位乘以10 + 低四位 (得到10进制数)
#define READ_BCD(val) 	(val >> 4) * 10 + (val & 0x0F)void Usart0_recv(uint8_t *data, uint32_t len) {printf("%s\r\n", data);
}static void RTC_config() {// 电池管理加载rcu_periph_clock_enable(RCU_PMU);pmu_backup_write_enable();// 重置备份域(不重置可能导致无法设置晶振,出现不走字情况)/* reset backup domain */rcu_bkp_reset_enable();rcu_bkp_reset_disable();// 晶振加载rcu_osci_on(RCU_LXTAL);rcu_osci_stab_wait(RCU_LXTAL);rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);// RTC功能加载rcu_periph_clock_enable(RCU_RTC);rtc_register_sync_wait();rtc_parameter_struct rps;rps.year = WRITE_BCD(23);rps.month = WRITE_BCD(4);rps.date = WRITE_BCD(20);rps.day_of_week = WRITE_BCD(4);rps.hour = WRITE_BCD(23);rps.minute = WRITE_BCD(59);rps.second = WRITE_BCD(55);rps.display_format = RTC_24HOUR;rps.am_pm = RTC_AM;rps.factor_asyn = 0x7F;rps.factor_syn = 0xFF;rtc_init(&rps);
}static void RTC_read() {rtc_parameter_struct rps;rtc_current_time_get(&rps);uint16_t year = READ_BCD(rps.year) + 2000;uint8_t month = READ_BCD(rps.month);uint8_t date = READ_BCD(rps.date);uint8_t week = READ_BCD(rps.day_of_week);uint8_t hour = READ_BCD(rps.hour);uint8_t minute = READ_BCD(rps.minute);uint8_t second = READ_BCD(rps.second);printf("%d-%d-%d %d %d:%d:%d\r\n", year, month, date, week, hour, minute, second);
}int main(void)
{nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);systick_config();Usart0_init();RTC_config();while(1) {RTC_read();delay_1ms(1000);}
}

RTC时钟备份寄存器

RTC时钟有20个32位(共80字节)通用备份寄存器,能够在省电模式下保存数据。通过备份寄存器可以实现只配置一次时间即可。

注意:如果在尝试向RTC_BKP0写入数据之前或之后调用了rcu_bkp_reset_enable(),那么这确实会导致写入的数据在系统复位后丢失,因为RTC备份寄存器会被复位重置。因此,要确保在向RTC备份寄存器写入数据并期望这些数据在复位后仍然有效时,不能调用rcu_bkp_reset_enable()。

if( RTC_BKP0 == 0xf234 ){	//说明不是第一次初始化,可以不用重新设置时间
}else{//如果后备寄存器0 的值 不为 0XF234//设置后备寄存器0的值为 0XF234,标记已经初始化过RTCRTC_BKP0 = 0xf234;//初始化RTC时间RtcTimeConfig(0x23,0x07,0x12,0x03,0x12,0x59,0x50);
}

总结

  1. 理解了RTC的基本原理,包括其在实时时钟设计中的作用和结构。
  2. 掌握了初始化RTC的步骤,包括加载依赖、配置时钟源和初始化RTC等。
  3. 理解了设置时间的方法,包括配置时钟参数和异步同步分频器的数值等。
  4. 掌握了读取时间的操作,包括BCD格式转换和从RTC中获取日期和时间信息。

这篇关于ARM32开发--RTC内置实时时钟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1055607

相关文章

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

Python使用smtplib库开发一个邮件自动发送工具

《Python使用smtplib库开发一个邮件自动发送工具》在现代软件开发中,自动化邮件发送是一个非常实用的功能,无论是系统通知、营销邮件、还是日常工作报告,Python的smtplib库都能帮助我们... 目录代码实现与知识点解析1. 导入必要的库2. 配置邮件服务器参数3. 创建邮件发送类4. 实现邮件

基于Python开发一个有趣的工作时长计算器

《基于Python开发一个有趣的工作时长计算器》随着远程办公和弹性工作制的兴起,个人及团队对于工作时长的准确统计需求日益增长,本文将使用Python和PyQt5打造一个工作时长计算器,感兴趣的小伙伴可... 目录概述功能介绍界面展示php软件使用步骤说明代码详解1.窗口初始化与布局2.工作时长计算核心逻辑3

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示

JavaScript实战:智能密码生成器开发指南

本文通过JavaScript实战开发智能密码生成器,详解如何运用crypto.getRandomValues实现加密级随机密码生成,包含多字符组合、安全强度可视化、易混淆字符排除等企业级功能。学习密码强度检测算法与信息熵计算原理,获取可直接嵌入项目的完整代码,提升Web应用的安全开发能力 目录

使用Python实现实时金价监控并自动提醒功能

《使用Python实现实时金价监控并自动提醒功能》在日常投资中,很多朋友喜欢在一些平台买点黄金,低买高卖赚点小差价,但黄金价格实时波动频繁,总是盯着手机太累了,于是我用Python写了一个实时金价监控... 目录工具能干啥?手把手教你用1、先装好这些"食材"2、代码实现讲解1. 用户输入参数2. 设置无头浏