GD32F10X ----RTC

 1. RTC的简介 

STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
        RTC 模块和时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。


 2. RTC的框图

这里用的是STM32其实与GD都是差不多。

 RTC 由两个主要部分组成 第一部分(APB1 接口),第二部分是后备区域。

 RT_DIV寄存器设置可编程产生 1 秒的 RTC 时间基准 TR_CLK。每一秒到来RTC_CNT

寄存器的值就会加1。RTC_CNT是32位的寄存器。1秒到还可以产生中断。以及溢出中断。以及闹钟中断。(当RTC_ALR寄存器与RTC_CNT一样)。

我们通过读取RTC_CNT的大小(多少秒)然后转换成实时时钟(年,月,日,时,分,秒)

如果我要设置一个实时时钟转成秒然后设置到RTC_CNT。

不管是设置与获取都是操作RTC_CNT并且单位是秒。具体怎么转成实时时钟要自己写逻辑。

实时时钟都是以1970年1月1日00 :00:00为开始。(红色字是重点)

由于RTC_CNT是32位的,可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒,约合 136 年左右。所以最大:1970 + 136。如果大于这个年就会溢出。

3. 代码实现

 RTC.h

#ifndef _RTC_H
#define _RTC_H#include "gd32f10x.h"
#include <stdio.h>//日期时间结构体
typedef struct{//时间uint8_t hour;uint8_t min;uint8_t sec;//日期uint16_t w_year;uint8_t w_month;uint8_t w_day;
}_calender_obj;extern _calender_obj calender;  //日期、时间结构体变量
extern uint8_t const month_table[12];void RTC_Config(void);  //RTC配置
uint8_t RTC_Init(void);    //RTC初始化
void RTC_NVIC_Config(void); //配置RTC中断uint8_t RTC_Set(uint16_t syear, uint8_t smonth, uint8_t sday, uint8_t shour, uint8_t smin, uint8_t ssec); //将设置时间转化为秒数,给到RTC_CNT
uint8_t RTC_Get(void);  //得到RTC_CNT的值并转换为日期时间
uint8_t Is_Leap_Year(uint16_t year); //判断year是否闰年
uint8_t RTC_Get_Week(uint16_t year,uint8_t month,uint8_t day);
#endif

RTC.c

#include "RTC.h"_calender_obj calender;uint8_t const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
uint8_t const month_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年月份的天数uint32_t timecount = 0;//RTC配置
void RTC_Config(void){rcu_periph_clock_enable(RCU_BKPI); //备份区域的时钟要先使能rcu_periph_clock_enable(RCU_PMU);  //电源管理时钟使能pmu_backup_write_enable();         //使能备份域访问允许bkp_deinit();                      //备份域复位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时钟rtc_register_sync_wait();         //等待寄存器与APB1时钟同步rtc_lwoff_wait();   //等待RTC的最后一次操作完成rtc_interrupt_enable(RTC_INT_SECOND);//使能RTC的秒中断rtc_lwoff_wait();   //等待RTC的最后一次操作完成rtc_prescaler_set(32767); /* 配置RTC_PRL的值(时钟分频) */rtc_lwoff_wait();   //等待RTC的最后一次操作完成
}//RTC初始化
uint8_t RTC_Init(void){RTC_Config();RTC_Set(2023, 8, 21, 23, 13, 15);RTC_NVIC_Config();//配置中断的优先级return 0;
}// 配置RTC的中断优先级
void RTC_NVIC_Config(void){nvic_irq_enable(RTC_IRQn, 2, 0);
}//RTC的中断服务函数
void RTC_IRQHandler(void){if(rtc_flag_get(RTC_FLAG_SECOND) != RESET){ //判断是否为秒中断rtc_flag_clear(RTC_FLAG_SECOND);RTC_Get();printf("Now time is: %d-%d-%d %d:%d:%d\r\n", calender.w_year, calender.w_month, calender.w_day, calender.hour, calender.min, calender.sec);}
}//将设置时间转化为秒数,给到RTC_CNT
uint8_t RTC_Set(uint16_t syear, uint8_t smonth, uint8_t sday, uint8_t shour, uint8_t smin, uint8_t ssec){uint32_t seccounts = 0;uint16_t temp_year = 1970;uint8_t temp_month;if(syear<1970 || syear>2099){  //设置的时间不合理return 1;}//整年的秒数while(temp_year < syear){if(Is_Leap_Year(temp_year))seccounts += 31622400; //闰年,一年的秒数  366* 24 * 60 *60else seccounts += 31536000;  //平年,一年的秒数  365* 24 * 60 *60temp_year++;}//整月的秒数smonth--;for(temp_month = 0; temp_month<smonth; temp_month++){seccounts += (uint32_t)month_table[temp_month]*86400;if(Is_Leap_Year(syear)&&temp_month==1)seccounts += 86400; //如果设置的年份是闰年,在二月这个月份要加多一天}//日、时、分、秒的处理seccounts += (uint32_t)(sday-1)*86400; //整日的秒数  24 * 60 * 60seccounts += (uint32_t)shour*3600;//小时seccounts += (uint32_t)smin*60;   //分seccounts += ssec;      //秒rtc_lwoff_wait();rtc_counter_set(seccounts);return 0;
}//得到RTC_CNT的值并转换为日期时间
uint8_t RTC_Get(void){//把timecount转换为日期时间,并赋给calenderuint32_t temp_days = timecount/86400;uint16_t temp_year = 1970;uint16_t temp_month;uint32_t temp_seconds;timecount = rtc_counter_get();//读取RTC_CNT寄存器的值//处理天数中的整年,if(temp_days>0){while(temp_days>=365){if(Is_Leap_Year(temp_year)){//如果是闰年if(temp_days>365){temp_days -= 366;}else{break;}}else{temp_days -= 365;}temp_year++;}calender.w_year = temp_year;//剩下不足一年的,再处理整月temp_month = 1; //用来临时存放月份while(temp_days >= 28){ //超过了一个月if(Is_Leap_Year(calender.w_year) && temp_month == 2){if(temp_days>=29){ //闰年的2月是29天temp_days -= 29;}else{break;}}else{if(temp_days >= month_table[temp_month-1]){//剩余的天数是不是大于temp_month这个月整月的天数temp_days -= month_table[temp_month-1];}else{break;}}temp_month++;}}calender.w_month = temp_month;calender.w_day = temp_days+1;//处理剩下的不足一天的秒数,时:分:秒temp_seconds = timecount%86400; //不足一天的秒数calender.hour = temp_seconds/3600;calender.min = (temp_seconds%3600)/60;calender.sec = temp_seconds%60;return 0;
}uint8_t Is_Leap_Year(uint16_t year){ //判断year是否闰年if(year%4 == 0){if(year%100 == 0){if(year%400 == 0)return 1;elsereturn 0;}else{return 1;}}else{return 0;}
}//获得现在是星期几
//功能描述:输入公历日期得到星期(只允许1901-2099年)
//year,month,day:公历年月日 
//返回值:星期号																						 
uint8_t RTC_Get_Week(uint16_t year,uint8_t month,uint8_t day)
{	uint16_t temp2;uint8_t yearH,yearL;yearH=year/100;	yearL=year%100; // 如果为21世纪,年份数加100  if (yearH>19)yearL+=100;// 所过闰年数只算1900年之后的  temp2=yearL+yearL/4;temp2=temp2%7; temp2=temp2+day+table_week[month-1];if (yearL%4==0&&month<3)temp2--;return(temp2%7);
}

main.c

#include "gd32f10x_eval.h"#include "LED.h"
#include "SYSTICK_DELAY.h"
#include "RTC.h"int main(){gd_eval_com_init(EVAL_COM0);    // 初始化USART0LED_Init();my_systick_config();printf("This is a RTC DEMO test.\r\n");RTC_Init();while(1){LED1_Toggle();my_systick_delay_ms(1000);	//delay 1000 ms}
}/*重写fputc*/
int fputc(int ch, FILE *f)
{usart_data_transmit(EVAL_COM0,ch);  //通过串口把ch给发送出去while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));return ch;
}

通过串口工具来显示实时时钟。先设置然后在读取通过串口显示出来。

 

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

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

相关文章

格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断(Python代码,CNN模型)

1.运行效果&#xff1a;格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断&#xff08;Python代码&#xff0c;CNN模型&#xff09;_哔哩哔哩_bilibili 环境库 只要tensorflow版本大于等于2.4.0即可运行 2.GAF的内容 GAF是一种用于时间序列数据可视化和特征提…

LLM-TAP随笔——大语言模型基础【深度学习】【PyTorch】【LLM】

文章目录 2.大语言模型基础2.1、编码器和解码器架构2.2、注意力机制2.2.1、注意力机制&#xff08;Attention&#xff09;2.2.2、自注意力机制&#xff08;Self-attention&#xff09;2.2.3、多头自注意力&#xff08;Multi-headed Self-attention&#xff09; 2.3、transforme…

【C++】笔试训练(三)

目录 一、选择题二、编程题1、字符串中找出连续最长的数字串2、数组中出现次数超过一半的数字 一、选择题 1、以下程序的输出结果是&#xff08;&#xff09; #include <stdio.h> int main() {char a[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, * p;int i;i 8;p a i;p…

【JVM】双亲委派模型

双亲委派模型 1. 什么是双亲委派模型2. 双亲委派模型的优点 1. 什么是双亲委派模型 提到 类加载 机制&#xff0c;不得不提的一个概念就是“双亲委派模型”。 双亲委派模型指的就是 JVM 中的类加载器如何根据类的全限定名找到 .class 文件的过程 类加载器: JVM 里面专门提供…

【ESP32 + Edge Impulse平台】运行AI算法模拟多传感器数据融合实现异常检测

本篇博文主要以ESP32+MQ Sensor 气体传感器为例,通过连接 Edge Impulse 平台,实现数据的实时采集和训练,进而实现在嵌入式设备上部署 ML 机器学习。本教程介绍如何使用 Edge Impulse 和机器学习来实现ESP32 异常检测系统,系统使用一个机器学习模型,检测气体何时出现异常。…

OpenCV查找和绘制轮廓:findContours和drawContours

1 任务描述&#xff1a; 绘制图中粗线矩形的2个边界&#xff0c;并找到其边界的中心线 图1 原始图像 2.函数原型 findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, …

2021-06-11 51蛋骗鸡用小数点作秒指示,分钟计时.(怎么用二个数码管做分的倒计时,DP亮灭来计秒)

缘由怎么用二个数码管做分的倒计时&#xff0c;DP亮灭来计秒,求思路 - 24小时必答区 #include "REG52.h" sbit K1 P1^5; sbit K2 P1^6; sbit K3 P1^7; sbit BUZ1P1^0; bit k0; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111,128};//0-9. unsign…

Polygon Miden:扩展以太坊功能集的ZK-optimized rollup

1. 引言 Polygon Miden定位为zkVM&#xff0c;定于2023年Q4上公开测试网。 zk、zkVM、zkEVM及其未来中指出&#xff0c;当前主要有3种类型的zkVM&#xff0c;括号内为其相应的指令集&#xff1a; mainstream&#xff08;WASM, RISC-V&#xff09;EVM&#xff08;EVM bytecod…

Kubernetes 学习总结(38)—— Kubernetes 与云原生的联系

一、什么是云原生&#xff1f; 伴随着云计算的浪潮&#xff0c;云原生概念也应运而生&#xff0c;而且火得一塌糊涂&#xff0c;大家经常说云原生&#xff0c;却很少有人告诉你到底什么是云原生&#xff0c;云原生可以理解为“云”“原生”&#xff0c;Cloud 可以理解为应用程…

[NOIP2011 提高组] 选择客栈

[NOIP2011 提高组] 选择客栈 题目描述 丽江河边有 n n n 家很有特色的客栈&#xff0c;客栈按照其位置顺序从 1 1 1 到 n n n 编号。每家客栈都按照某一种色调进行装饰&#xff08;总共 k k k 种&#xff0c;用整数 0 ∼ k − 1 0 \sim k-1 0∼k−1 表示&#xff09;&am…

机器学习——seaborn实用画图方法简介

0、seaborn简介: 前言:下面的总结只是介绍seaborn有哪些方法和属性,至于具体使用,通过下面给出的名称稍作查找即可。重点应该关注本文介绍的seaborn的使用方法seaborn与机器学习的关系: 知识图谱 0.1、了解即可的知识: seaborn:在matplotlib的基础上画一些更好看的图,在…

Mysql集群高可用架构MHA

Mysql集群高可用架构MHA 一、MHA概述1.1、 MHA 是什么1.2、 MHA 的组成1.3、 MHA 的特点 二、MHA高可用实例2.1、配置主从复制2.1、 安装 MHA 软件2.2、故障模拟2.3、故障修复 一、MHA概述 1.1、 MHA 是什么 MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的M…

计算机毕设 大数据全国疫情数据分析与3D可视化 - python 大数据

文章目录 0 前言1 课题背景2 实现效果3 设计原理4 部分代码5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的…

OpenCV之直线曲线拟合

直线拟合fitLine void fitLine( InputArray points, OutputArray line, int distType,double param, double reps, double aeps ); points:二维点的数组或vector line:输出直线,Vec4f (2d)或Vec6f (3d)的vector distType:距离类型 param:距离参数 reps:径向的精度参数 a…

【2023集创赛】加速科技杯三等奖作品:私密性高精度刷手身份认证系统

本文为2023年第七届全国大学生集成电路创新创业大赛&#xff08;“集创赛”&#xff09;加速科技杯三等奖作品分享&#xff0c;参加极术社区的【有奖征集】分享你的2023集创赛作品&#xff0c;秀出作品风采&#xff0c;分享2023集创赛作品扩大影响力&#xff0c;更有丰富电子礼…

【数据结构】排序之插入排序和选择排序

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、排序的概念及其分类 &#x1f4d2;1.1排序的概念 &#x1f4d2;1.2排序…

HTML详细基础(二)文件路径

目录 一.相对路径 二.绝对路径 三.超链接标签 四.锚点链接 首先&#xff0c;扩展一些HTML执行的原理&#xff1a; htmL(hypertext markup Language) 是一种规范&#xff08;或者说是一种标准&#xff09;&#xff0c;它通过标记符&#xff08;tag&#xff09;来标记要显示…

【FreeRTOS】FreeRTOS移植stm32详细步骤介绍

我在查找FreeRTOS移植的相关教程特别少&#xff0c;所以想非常详细的介绍FreeRTOS移植stm32详细步骤&#xff0c;包括源码的下载&#xff0c;源码介绍&#xff0c;系统移植&#xff0c;代码验证等&#xff0c;每一步都有对应的介绍和解释&#xff0c;希望可以帮助到你们。 文章…

openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86

文章目录 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x8684.1 BIOS84.2 操作系统环境设置84.3 网络 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x86 …

基于vue+Element Table Popover 弹出框内置表格的封装

文章目录 项目场景&#xff1a;实现效果认识组件代码效果分析 封装&#xff1a;代码封装思路页面中使用 项目场景&#xff1a; 在选择数据的时候需要在已选择的数据中对比选择&#xff0c;具体就是点击一个按钮&#xff0c;弹出一个小的弹出框&#xff0c;但不像对话框那样还需…