当前位置: 首页 > news >正文

【GD32】从零开始学兆易创新32位微处理器——RTC实时时钟+日历例程

1 简介

RTC实时时钟顾名思义作用和墙上挂的时钟差不多,都是用于记录时间和日历,同时也有闹钟的功能。从硬件实现上来说,其实它就是一个特殊的计时器,它内部有一个32位的寄存器用于计时。RTC在低功耗应用中可以说相当重要,因为在使用外部低速晶振的条件下,它在所有的低功耗模式下都可以工作,这使得RTC很适合实现芯片的低功耗唤醒。下面是RTC的框图。

咋一看RTC的内部还挺复杂的。

2 硬件时钟

先看时钟,RTC的时钟可以选择内部32kHz晶振、外部高速晶振分频或外部低速时钟,一般都是使用外部32.768kHz低速晶振来驱动。时钟会先经过数字平滑校准器,用户可以配置进行进行校准;接着进入7位异步预分频器,这个分频器一般设置最大分频,即128分频,因为这个分频器的值越大RTC的功耗会越低;然后时钟进入一个粗校准器,需要注意的是粗校准和前面的数字平滑校准同时只能开启其中一个;之后时钟进入一个15位的同步预分频器,这里一般设置为256分频,这样就刚好能分出1Hz的频率,也就是每秒更新一次RTC。

当然上面介绍的是最常用的RTC时钟配置,根据不同的功能实现还可以有其他的配置。

3 功能

3.1 日历

RTC的日历功能依赖3个寄存器——RTC_DATE(日期寄存器)RTC_TIME(时间寄存器)RTC_SS(亚秒寄存器)。日期寄存器和时间寄存器保存我们熟知的年月日时分秒数据,是以BCD码的方式保存的。亚秒寄存器用于保存毫秒级的时钟数据。

上面的3个寄存器RTC内部会有对应的影子寄存器,在实际应用中我们一般读取它们对应的影子寄存器。每2个RTC周期影子寄存器才会更新一次,虽说影子寄存器的值与实际值会有延迟,但它能保证读出来的值是一致的。如果我们读的是寄存器的实际值,那么有可能在读的过程中RTC对寄存器进行了更新,导致我们读到的值前后不一致

在读取影子寄存器的值时,我们要等待状态寄存器的RSYNF位置1才能读取,此时寄存器的值才是稳定的。另外需注意的是,在深度睡眠和待机模式下,影子寄存器的值是不更新的,因此退出该模式时需要清除RSYNF位

3.2 自动唤醒

在低功耗应用中,RTC的自动唤醒功能可以说是必用到的,RTC内部使用一个16位的向下计数的计数器实现自动唤醒。计数器的驱动时钟可以选择RTC时钟的2/4/8/16分频或内部时钟,一般会选择内部时钟,即ck_spre。如果ck_spre为1Hz的话,唤醒的时间可以设置在1秒到36小时之间。

当计数器到0时,WTF标志位置1,唤醒计数器自动重载RTC_WUT的值。当WTF1后,必须软件清除该标志。如果使能了中断功能,并且芯片处于低功耗模式,唤醒中断会使芯片退出低功耗模式。

3.3 闹钟

RTC内部有2个可配置的闹钟,它与我们日常熟知的闹钟原理是差不多的;通过设置闹钟日期寄存器和闹钟亚秒寄存器来配置唤醒时刻,当到达指定时刻时闹钟会产生中断,该中断也能将芯片从低功耗模式中唤醒。

3.4 时间戳功能

时间戳功能由RTC_TS管脚输入,通过配置TSEN位来使能。当RTC_TS管脚检测到时间戳事件发生时,会将日历的值保存在时间戳寄存器中(RTC_DTS / RTC_TTS / RTC_SSTS),同时时间戳标志(TSF)也将由硬件置1。如果时间戳中断使能被启用(TSIE),时间戳事件会产生一个中断,该中断也能将芯片从低功耗模式中唤醒。

4 例程

4.1 日历

这个例程主要是配置RTC让它正常工作,然后定时读取日历值。

先看main函数。

#include "gd32f4xx.h"
#include "systick.h"
#include "debug.h"
#include "rtc.h"struct tm time_struct = {.tm_year = 2024,.tm_mon = 1,.tm_mday = 1,.tm_hour = 0,.tm_min = 0,.tm_sec = 0,.tm_wday = RTC_MONDAY
};int main(void)
{systick_config();debug_init();rtc_config(&time_struct);printf("rtc demo\r\n");while(1){struct tm ts = {0};rtc_get_time(&ts);printf("%02d-%02d-%02d %02d:%02d:%02d\r\n", ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);delay_1ms(1000);}
}

 main函数调用rtc_config函数初始化RTC,传入struct tm结构体,这个结构体是time.h里面定义的,是系统库自带的,它的定义如下。

struct tm {int tm_sec;   /* seconds after the minute, 0 to 60(0 - 60 allows for the occasional leap second) */int tm_min;   /* minutes after the hour, 0 to 59 */int tm_hour;  /* hours since midnight, 0 to 23 */int tm_mday;  /* day of the month, 1 to 31 */int tm_mon;   /* months since January, 0 to 11 */int tm_year;  /* years since 1900 */int tm_wday;  /* days since Sunday, 0 to 6 */int tm_yday;  /* days since January 1, 0 to 365 */int tm_isdst; /* Daylight Savings Time flag */union {       /* ABI-required extra fields, in a variety of types */struct {int __extra_1, __extra_2;};struct {long __extra_1_long, __extra_2_long;};struct {char *__extra_1_cptr, *__extra_2_cptr;};struct {void *__extra_1_vptr, *__extra_2_vptr;};};
};

初始化函数的内部如下。

void rtc_config(struct tm *t)
{/* 使能PMU时钟 */rcu_periph_clock_enable(RCU_PMU);/* 使能RTC寄存器访问 */pmu_backup_write_enable();/* 使用外部低速晶振 */rcu_osci_on(RCU_LXTAL);rcu_osci_stab_wait(RCU_LXTAL);rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);rcu_periph_clock_enable(RCU_RTC);rtc_register_sync_wait();/* 初始化时钟 */rtc_set_time(t);
}

因为RTC使用的是VBAT供电域,默认配置下该供电域的寄存器是写禁止的,因此需要调用pmu_backup_write_enable函数使能写操作。下面就是配置外部低速时钟,然后调用rtc_register_sync_wait等待影子寄存器同步数据。初始化完毕就可以配置日历了。

void rtc_set_time(const struct tm *time_struct)
{rtc_parameter_struct rtc_initpara = {0};/* RTC时钟频率 = 32.768kHz / (255 + 1) / (127 + 1) = 1Hz */rtc_initpara.factor_asyn = 127;rtc_initpara.factor_syn = 255;rtc_initpara.display_format = RTC_24HOUR;rtc_initpara.year = BIN_TO_BCD(time_struct->tm_year - 1970);rtc_initpara.month = BIN_TO_BCD(time_struct->tm_mon);rtc_initpara.date = BIN_TO_BCD(time_struct->tm_mday);rtc_initpara.hour = BIN_TO_BCD(time_struct->tm_hour);rtc_initpara.minute = BIN_TO_BCD(time_struct->tm_min);rtc_initpara.second = BIN_TO_BCD(time_struct->tm_sec);rtc_initpara.day_of_week = time_struct->tm_wday;rtc_init(&rtc_initpara);
}

配置日历使用rtc_init函数,按需要填充结构体即可;factor_asyn成员是异步分频器的值,factor_syn是同步分频器的值。另外需要注意日历寄存器内的值是以BCD码形式保存,因此需要写一个简单的转换宏,像下面。

#define BIN_TO_BCD(x) ((((x) / 10) << 4) + ((x) % 10))

还有就是RTC的寄存器年份内容只能保存2个数字,即只能计算99年,所以根据需要填合适的起始值进去,像我这里就是起始年份定为1970年,把当前年份减去1970转换为BCD码后填进寄存器。

 RTC运行时可以随时调用rtc_current_time_get获取当前时间。

void rtc_get_time(struct tm *time_struct)
{rtc_parameter_struct rtc_initpara = {0};rtc_current_time_get(&rtc_initpara);time_struct->tm_year = BCD_TO_BIN(rtc_initpara.year) + 1970;time_struct->tm_mon = BCD_TO_BIN(rtc_initpara.month);time_struct->tm_mday = BCD_TO_BIN(rtc_initpara.date);time_struct->tm_hour = BCD_TO_BIN(rtc_initpara.hour);time_struct->tm_min = BCD_TO_BIN(rtc_initpara.minute);time_struct->tm_sec = BCD_TO_BIN(rtc_initpara.second);time_struct->tm_wday = rtc_initpara.day_of_week;
}

 取值的时候也是要将BCD码转成对应的数字,用下面的宏。

#define BCD_TO_BIN(x) (10 * ((x) >> 4) + ((x) & 0x0F))

下面是demo的输出。 

相关文章:

【GD32】从零开始学兆易创新32位微处理器——RTC实时时钟+日历例程

1 简介 RTC实时时钟顾名思义作用和墙上挂的时钟差不多&#xff0c;都是用于记录时间和日历&#xff0c;同时也有闹钟的功能。从硬件实现上来说&#xff0c;其实它就是一个特殊的计时器&#xff0c;它内部有一个32位的寄存器用于计时。RTC在低功耗应用中可以说相当重要&#xf…...

HTTP网络协议

1.HTTP &#xff08;1&#xff09;概念&#xff1a; Hyper Text Transfer Protocol&#xff0c;超文本传输协议规定了浏览器和服务器之间数据传输的规则。 &#xff08;2&#xff09;特点 基于TCP协议:面向连接&#xff0c;安全基于请求-响应模型的:一次请求对应一次响应HTTP协…...

Kubernetes相关生态

1、Prometheus、Metrics Server与Kubernetes监控体系 简介&#xff1a; Prometheus 项目与 Kubernetes 项目一样&#xff0c;也来自于 Google 的 Borg 体系&#xff0c;它的原型系统&#xff0c;叫作 BorgMon&#xff0c;是一个几乎与 Borg 同时诞生的内部监控系统 Pro…...

C语言入门4-函数和程序结构

函数举例 读取字符串&#xff0c;如果字符串中含有ould则输出该字符串&#xff0c;否则不输出。 #include <stdio.h>// 函数声明 int getLine(char s[], int lim); int strindex(char s[], char t[]);int main() {char t[] "ould"; // 要查找的目标子字符串…...

分行业二氧化碳排放数据

分行业二氧化碳排放量 资源名称&#xff1a;分行业二氧化碳排放量 数据来源&#xff1a;中国能源统计年鉴 时间范围&#xff1a;1995-2018年指标&#xff1a;八类能源和总量&#xff1a;煤炭、焦炭、原油、汽油、煤油、柴油、燃料油、天然气...

【OS基础】符合AUTOSAR标准的RTAOS-Alarms详解

目录 前言 正文 7.报警Alarms 7.1配置Alarms 7.1.1激活一个任务 7.1.2 设置一个事件 7.1.3报警回调Alarm Callback 7.1.4 增加计数器值 7.2设置Alarms 7.2.1 绝对Alarms 7.2.2 相对Alarm 7.3自启动Alarms 7.4 删除Alarms 7.5确认何时会发生Alarm 7.6非周期Alarm…...

基于Java的学生成绩管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术&#xff0c;B/S结构 工具&#xff1a;MyEclipse&#xff0c;MySQL 系统展示 首页 个人中…...

都2024年了,还有人不懂动态代理么?

文章目录 一、定义二、静态代理三、动态代理1. JDK代理1.1 JDK代理实现流程1.2 动态生成的类字节码 2. Cglib代理2.1 Cglib实现流程 四、总结 一、定义 静态代理和动态代理都反映了一个代理模式&#xff0c;代理模式是一种经典的设计模式&#xff0c;常用于为其他对象提供一种…...

ARM功耗管理框架之PPU

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理框架&#xff1f;SCP&#xff1f;PPU&#xff1f;LPI&#xff1f;之间的关系&#xff1f;如何配合&#xff1f; 目录 一、功耗管理框架中的PPU 二、PPU的结构与连接关系 三、PPU操作模式和电源模式及其之间的转…...

说说 SSL 的错误认识和不足之处

最近明月在学习折腾 LNMP 期间无意中建了一个 Typecho 的博客小站&#xff0c;近一周的折腾下来&#xff0c;收获真的不少&#xff0c;致使兴趣也越来越浓了&#xff0c;在升级 LNMP 的时候捎带手的给这个 Typecho 博客也启用了 SSL。并且开启了 memcached 和 OPcache 优化加速…...

Go语言day1

下载go语言的安装程序&#xff1a; All releases - The Go Programming Language 配置go语言的环境变量&#xff1a; 写第一个go语言 在E:\go_workspace当前窗口使用cmd命令: 输入 go run test.go...

【Python机器学习】利用t-SNE进行流形学习

虽然PCA通常是用于变换数据的首选方法&#xff0c;使你能够用散点图将其可视化&#xff0c;但这一方法的性质限制了其有效性。 有一类用于可视化的算法叫做流形学习算法&#xff0c;它允许进行更复杂的映射&#xff0c;通常也可以给出更好的可视化。其中特别有用的一个就是t-S…...

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系(m_coord)

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系&#xff08;m_coord&#xff09; 0. 引言1. m_proj使用方法2. 结语 0. 引言 上一篇介绍了m_proj函数用于初始化投影&#xff0c;本篇介绍的函数m_coord用于初始化地理坐标系或地磁坐标系&#xff0c;地理/地磁坐标系和投影…...

UEC++ 虚幻5第三人称射击游戏(一)

UEC 虚幻5第三人称射击游戏&#xff08;一&#xff09; 创建一个空白的C工程 人物角色基本移动 创建一个Character类添加一些虚幻商城中的基础动画 给角色类添加Camera与SPringArm组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "SpringArm")clas…...

java小代码(1)

代码 &#xff1a; 今日总结到此结束&#xff0c;拜拜&#xff01;...

SLAM ORB-SLAM2(27)词袋模型

SLAM ORB-SLAM2(27)词袋模型 1. 词袋模型1.1. 词汇树1.2. 逆向索引表1.3. 逆向索引表2. 词袋向量3. 匹配候选帧3.1. 找出和当前帧具有公共单词的所有关键帧3.2. 找出和当前帧最多公共单词的关键帧3.3. 剔除共享单词数较少的关键帧3.4. 计算关键帧的共视关键帧组的总得分3.5. …...

OpenAI 的 GPT-5:CTO米拉-穆拉提说,到 2026 年将实现博士级智能(Ph.D.-Level))

据首席技术官米拉-穆拉提&#xff08;Mira Murati&#xff09;介绍&#xff0c;GPT-5 是 OpenAI 人工智能的下一代进化产品&#xff0c;将于 2025 年底或 2026 年初在特定任务中实现博士级智能。 GPT-5 内部代号为 "Gobi "和 “Arrakis”&#xff0c;将是一个多模态…...

macbook配置adb环境和用adb操作安卓手机

&#xff08;参考&#xff1a;ADB工具包的安装与使用_adb工具箱-CSDN博客&#xff09; 第一步&#xff1a;从Android开发者网站下载Android SDK&#xff08;软件开发工具包&#xff09;。下载地址为&#xff1a; 第二步&#xff1a;解压下载的SDK压缩文件到某个目录中。 进入解…...

微软TTS最新模型,发布9种更真实的AI语音

很高兴与大家分享 Azure AI 语音翻译产品套件的两个重大更新&#xff1a; 视频翻译和增强的实时语音翻译 API。 视频翻译&#xff08;批量&#xff09; 今天&#xff0c;我们宣布推出视频翻译预览版&#xff0c;这是一项突破性的服务&#xff0c;旨在改变企业本地化视频内容…...

python爬虫 -爬取 json 格式数据

在Python中&#xff0c;爬取JSON格式的数据通常涉及到发送 HTTP请求到某个URL&#xff0c;并解析返回的JSON数据。以下是一个简单的示例&#xff0c;说明如何使用Python的requests库来爬取JSON格式的数据&#xff1a; 1. 首先&#xff0c;确保你已经安装了requests库。如果没…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...