4、RTC 实时时钟Demo(STM32F407)

RTC是个独立的BCD定时器/计数器。RTC 提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。

(RTC实质:一个掉电(主电源)后还继续运行(由VBAT供电)的32位的向上计数器,STM32F103没有分组的时间寄存器,需要自己解析,而F4有分组的时间寄存器。)

两个32位寄存器包含二进码十进制格式(BCD)的秒,分钟,小时(12或24小时制),星期几,日期,月份和年份。此外,还可以提供二进制的亚秒值。

系统可以自动将月份的天数补偿为28,29(闰年),30,31天。并且还可以进行夏令时补偿。

其他32位寄存器还包含可编程的闹钟亚秒,秒,分钟,小时,星期几和日期。

此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。

上电复位后,所有的RTC寄存器都会受到保护,以防止可能的非正常写访问。

RTC模块和时钟配置是在后备区域,即在系统复位或者待机模式唤醒后RTC的设置和时间维持不变,只要后备区域供电正常,RTC将一直工作下去。但是在系统复位之后会自动禁止访问后备区域和RTC,以防止意外操作,所以在设置时间之前,要先取消后备区域写保护。

 RTC工作原理框图

 RTC时钟源:

 RTC BKP备份寄存器

提醒:一共有20个32位备份寄存器。常用来保存一些系统配置信息和相关标志位。

 RTC相关常用寄存器

  1. RTC时间寄存器(RTC_TR)  
  2. RTC日期寄存器(RTC_DR)
  3. RTC亚秒寄存器(RTC_SSR)
  4. RTC控制寄存器(RTC_CR)
  5. RTC初始化和状态寄存器(RTC_ISR)
  6. RTC预分频寄存器(RTC_PRER)
  7. RTC唤醒定时器寄存器(RTC_WUTR)
  8. RTC闹钟A寄存器(RTC_ALRMAR)
  9. RTC闹钟A亚秒寄存器(RTC_ALRMASSR)
  10. RTC闹钟B寄存器( RTC_ALRMBR)
  11. RTC闹钟B亚秒寄存器(RTC_ALRMBSSR)
  12. RTC写保护寄存器(RTC_WPR)
  13. RTC备份寄存器(RTC_BKPxR)
  14. RTC时间戳时间寄存器(RTC_TSTR)
  15. RTC时间戳日期寄存器(RTC_TSDR)
  16. RTC时间戳亚秒寄存器(RTC_TSSSR)

RTC预分频寄存器(RTC_PRER)

 RTC时间寄存器(RTC_TR)  

 RTC日期寄存器(RTC_DR) 

 RTC亚秒寄存器(RTC_SSR)

 RTC控制寄存器(RTC_CR)

 RTC初始化和状态寄存器(RTC_ISR)

 RTC唤醒定时器寄存器(RTC_WUTR)

 RTC闹钟A/B寄存器(RTC_ALRMAR/ RTC_ALRMBR)

 RTC闹钟A/B亚秒寄存器(RTC_ALRMASSR/ RTC_ALRMBSSR)

 RTC写保护寄存器(RTC_WPR)

 程序源码

rtc.h 

#ifndef __RTC_H
#define __RTC_H
#include "sys.h"u8 My_RTC_Init(void);                                          // RTC初始化
ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm);    // RTC时间设置
ErrorStatus RTC_Set_Date(u8 year, u8 month, u8 date, u8 week); // RTC日期设置
void RTC_Set_AlarmA(u8 week, u8 hour, u8 min, u8 sec);         // 设置闹钟时间(按星期闹铃,24小时制)
void RTC_Set_WakeUp(u32 wksel, u16 cnt);                       // 周期性唤醒定时器设置#endif

rtc.c

#include "rtc.h"
#include "led.h"
#include "delay.h"
#include "usart.h"NVIC_InitTypeDef NVIC_InitStructure;// RTC时间设置
// hour,min,sec:小时,分钟,秒钟
// ampm:@RTC_AM_PM_Definitions  :RTC_H12_AM/RTC_H12_PM
// 返回值:SUCEE(1),成功
//        ERROR(0),进入初始化模式失败
ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm)
{RTC_TimeTypeDef RTC_TimeTypeInitStructure;RTC_TimeTypeInitStructure.RTC_Hours = hour;RTC_TimeTypeInitStructure.RTC_Minutes = min;RTC_TimeTypeInitStructure.RTC_Seconds = sec;RTC_TimeTypeInitStructure.RTC_H12 = ampm;return RTC_SetTime(RTC_Format_BIN, &RTC_TimeTypeInitStructure);
}
// RTC日期设置
// year,month,date:年(0~99),月(1~12),日(0~31)
// week:星期(1~7,0,非法!)
// 返回值:SUCEE(1),成功
//        ERROR(0),进入初始化模式失败
ErrorStatus RTC_Set_Date(u8 year, u8 month, u8 date, u8 week)
{RTC_DateTypeDef RTC_DateTypeInitStructure;RTC_DateTypeInitStructure.RTC_Date = date;RTC_DateTypeInitStructure.RTC_Month = month;RTC_DateTypeInitStructure.RTC_WeekDay = week;RTC_DateTypeInitStructure.RTC_Year = year;return RTC_SetDate(RTC_Format_BIN, &RTC_DateTypeInitStructure);
}// RTC初始化
// 返回值:0,初始化成功;
//        1,LSE开启失败;
//        2,进入初始化模式失败;
u8 My_RTC_Init(void)
{RTC_InitTypeDef RTC_InitStructure;					// 定义RTC初始化结构体u16 retry = 0X1FFF;									// 定义重试次数RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // 使能PWR时钟PWR_BackupAccessCmd(ENABLE);						// 使能后备寄存器访问if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x5053) // 检查是否第一次配置{RCC_LSEConfig(RCC_LSE_ON);							// 开启LSE(低速外部晶振)while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) // 检查指定的RCC标志位设置与否,等待低速晶振就绪{retry++;delay_ms(10);}if (retry == 0)return 1; // LSE 开启失败.RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 设置RTC时钟(RTCCLK),选择LSE作为RTC时钟RCC_RTCCLKCmd(ENABLE);					// 使能RTC时钟RTC_InitStructure.RTC_AsynchPrediv = 0x7F;			  // RTC异步分频系数(1~0X7F)RTC_InitStructure.RTC_SynchPrediv = 0xFF;			  // RTC同步分频系数(0~7FFF)RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; // RTC设置为24小时格式RTC_Init(&RTC_InitStructure);						  // 初始化RTCRTC_Set_Time(23, 59, 56, RTC_H12_AM); // 设置时间,23 点 59 分 56 秒RTC_Set_Date(23, 11, 29, 3);		  // 设置日期,14 年 5 月 5 日星期 1RTC_WriteBackupRegister(RTC_BKP_DR0, 0x5053); // 标记已经初始化过了}return 0;
}// 设置闹钟时间(按星期闹铃,24小时制)
// week:星期几(1~7) @ref  RTC_Alarm_Definitions
// hour,min,sec:小时,分钟,秒钟
void RTC_Set_AlarmA(u8 week, u8 hour, u8 min, u8 sec)
{EXTI_InitTypeDef EXTI_InitStructure;		 // 定义外部中断线结构体RTC_AlarmTypeDef RTC_AlarmTypeInitStructure; // 定义RTC闹钟结构体RTC_TimeTypeDef RTC_TimeTypeInitStructure;	 // 定义RTC时间结构体RTC_AlarmCmd(RTC_Alarm_A, DISABLE); // 关闭闹钟ARTC_TimeTypeInitStructure.RTC_Hours = hour;		// 设置小时RTC_TimeTypeInitStructure.RTC_Minutes = min;	/// 设置分钟RTC_TimeTypeInitStructure.RTC_Seconds = sec;	// 设置秒钟RTC_TimeTypeInitStructure.RTC_H12 = RTC_H12_AM; // 设置为上午RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay = week;								  // 设置星期RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; // 按星期闹RTC_AlarmTypeInitStructure.RTC_AlarmMask = RTC_AlarmMask_None;						  // 精确匹配星期,时分秒RTC_AlarmTypeInitStructure.RTC_AlarmTime = RTC_TimeTypeInitStructure;				  // 设置闹钟时间RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmTypeInitStructure);				  // 设置闹钟RTC_ClearITPendingBit(RTC_IT_ALRA);	 // 清除RTC闹钟A的标志EXTI_ClearITPendingBit(EXTI_Line17); // 清除LINE17上的中断标志位RTC_ITConfig(RTC_IT_ALRA, ENABLE); // 开启闹钟A中断RTC_AlarmCmd(RTC_Alarm_A, ENABLE); // 开启闹钟AEXTI_InitStructure.EXTI_Line = EXTI_Line17;			   // LINE17EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	   // 中断事件EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;			   // 使能LINE17EXTI_Init(&EXTI_InitStructure);						   // 配置外部中断线NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;		 // 子优先级2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 // 使能外部中断通道NVIC_Init(&NVIC_InitStructure);								 // 配置中断向量表
}// 周期性唤醒定时器设置
/*wksel:  @ref RTC_Wakeup_Timer_Definitions
#define RTC_WakeUpClock_RTCCLK_Div16        ((uint32_t)0x00000000)
#define RTC_WakeUpClock_RTCCLK_Div8         ((uint32_t)0x00000001)
#define RTC_WakeUpClock_RTCCLK_Div4         ((uint32_t)0x00000002)
#define RTC_WakeUpClock_RTCCLK_Div2         ((uint32_t)0x00000003)
#define RTC_WakeUpClock_CK_SPRE_16bits      ((uint32_t)0x00000004)
#define RTC_WakeUpClock_CK_SPRE_17bits      ((uint32_t)0x00000006)
*/
// cnt:自动重装载值.减到0,产生中断.
/*唤醒功能可以让RTC实时时钟在设定的时间点或间隔后触发中断,
从而唤醒系统或执行特定的任务。例如,在低功耗应用中,
系统可能会进入睡眠模式以节省能量,但仍然需要在某个时间点或间隔后执行某些任务,
比如更新显示、采集传感器数据等。通过设置唤醒功能,
RTC实时时钟可以在预定的时间点或间隔后触发中断,从而唤醒系统并执行相应的任务。*/
void RTC_Set_WakeUp(u32 wksel, u16 cnt)
{EXTI_InitTypeDef EXTI_InitStructure;RTC_WakeUpCmd(DISABLE); // 关闭WAKE UPRTC_WakeUpClockConfig(wksel); // 唤醒时钟选择RTC_SetWakeUpCounter(cnt); // 设置WAKE UP自动重装载寄存器RTC_ClearITPendingBit(RTC_IT_WUT);	 // 清除RTC WAKE UP的标志EXTI_ClearITPendingBit(EXTI_Line22); // 清除LINE22上的中断标志位RTC_ITConfig(RTC_IT_WUT, ENABLE); // 开启WAKE UP 定时器中断RTC_WakeUpCmd(ENABLE);			  // 开启WAKE UP 定时器 EXTI_InitStructure.EXTI_Line = EXTI_Line22;			   // LINE22EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	   // 中断事件EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;			   // 使能LINE22EXTI_Init(&EXTI_InitStructure);						   // 配置NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;		 // 子优先级2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 // 使能外部中断通道NVIC_Init(&NVIC_InitStructure);								 // 配置NVIC中断向量表
}// RTC闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{if (RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET) // ALARM A中断?{RTC_ClearFlag(RTC_FLAG_ALRAF); // 清除中断标志printf("ALARM A!\r\n");}EXTI_ClearITPendingBit(EXTI_Line17); // 清除中断线17的中断标志
}// RTC WAKE UP中断服务函数
void RTC_WKUP_IRQHandler(void)
{if (RTC_GetFlagStatus(RTC_FLAG_WUTF) == SET) // WK_UP中断?{RTC_ClearFlag(RTC_FLAG_WUTF); // 清除中断标志LED1 = !LED1;}EXTI_ClearITPendingBit(EXTI_Line22); // 清除中断线22的中断标志
}

 main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "usmart.h"
#include "rtc.h"int main(void)
{RTC_TimeTypeDef RTC_TimeStruct; // 用于存储RTC的时间RTC_DateTypeDef RTC_DateStruct; // 用于存储日期信息u8 tbuf[40]; // 用于存储格式化后的时间和日期字符串u8 t = 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置系统中断优先级分组2delay_init(168);								// 初始化延时函数uart_init(115200);								// 初始化串口波特率为115200usmart_dev.init(84); // 初始化USMARTLED_Init();			 // 初始化LEDLCD_Init();			 // 初始化LCDMy_RTC_Init();		 // 初始化RTCRTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits, 0); // 配置WAKE UP中断,1秒钟中断一次POINT_COLOR = RED;LCD_ShowString(30, 50, 200, 16, 16, "Explorer STM32F4");LCD_ShowString(30, 70, 200, 16, 16, "RTC TEST");LCD_ShowString(30, 90, 200, 16, 16, "ATOM@ALIENTEK");LCD_ShowString(30, 110, 200, 16, 16, "2023/11/29");while (1){t++;if ((t % 10) == 0) // 每100ms更新一次显示数据{RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct); // 获取当前的时间信息// 将其格式化为字符串存储在tbuf中,然后通过LCD显示出来sprintf((char *)tbuf, "Time:%02d:%02d:%02d", RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes, RTC_TimeStruct.RTC_Seconds);LCD_ShowString(30, 140, 210, 16, 16, tbuf);RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct); // 获取当前的日期信息// 将其格式化为字符串存储在tbuf中,再通过LCD显示出来sprintf((char *)tbuf, "Date:20%02d-%02d-%02d", RTC_DateStruct.RTC_Year, RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date);LCD_ShowString(30, 160, 210, 16, 16, tbuf);sprintf((char *)tbuf, "Week:%d", RTC_DateStruct.RTC_WeekDay);LCD_ShowString(30, 180, 210, 16, 16, tbuf);}if ((t % 20) == 0)LED0 = !LED0; // 每200ms,翻转一次LED0delay_ms(10);	  // 当循环执行了10次,即经过了10次delay_ms(10)的暂停,总共的时间就是10毫秒乘以10次,即100毫秒}
}

效果视频

RTC实时时钟

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

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

相关文章

SpringBoot3.x + mp代码生成器(更新系列)

小伙伴们,有没有这样一个体验,每次开始写一个项目时,搭建项目环境,建entity,mapper,service,controller层文件的感到繁琐,这属实体力活呀!然而,自从有了Mybat…

JSP格式化标签 formatDate日期格式转换

我们继续来讲格式化标签 formatDate 这个标签 作用是 将一个date时间类型的值转成指定格式的字符串 语法格式如下 value 是需要格式化的数据 type 是确定你要转什么类型的数据 这里有 日期型 时间型 日期时间型 dateStyle 专门用来设置日期格式 timestyle 的话 是专门用来设…

海外IP罗拉rola正版去哪里找?

免费海外IP代理能用吗?和收费的有哪些差异? 如今在这个大数据时代,无论你从事哪个行业,都离不开数据,尤其是做跨境电商的,更一步都离不开海外IP代理,无论是网站引擎优化还是营销推广、数据抓取…

SpringBoot——Quartz 定时任务

优质博文&#xff1a;IT-BLOG-CN 一、Scheduled 定时任务 【1】添加Scheduled相关依赖&#xff0c;它是Spring自带的一个jar包因此引入Spring的依赖&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spring-context-su…

《opencv实用探索·六》简单理解图像膨胀

1、图像膨胀原理简单理解 膨胀是形态学最基本的操作&#xff0c;都是针对白色部分&#xff08;高亮部分&#xff09;而言的。膨胀就是使图像中高亮部分扩张&#xff0c;效果图拥有比原图更大的高亮区域。 2、图像膨胀的作用 注意一般情况下图像膨胀和腐蚀是联合使用的。 &…

Redis多机数据库

文章目录 Redis多机数据库一、主从复制1、旧版复制功能的实现a、同步b、命令传播 2、旧版复制功能的缺陷3、新版复制功能的实现a、部分同步功能b、复制实现步骤 4、心跳检测 二、哨兵1、Sentinel概念2、Sentinel初始化流程3、故障转移过程 三、集群1、几个概念2、集群创建流程a…

localStorage 和sessionStorage

localStorage 和 sessionStorage 是浏览器提供的两种客户端存储数据的方式&#xff1a; 生命周期&#xff1a; localStorage&#xff1a; 存储在 localStorage 中的数据在浏览器关闭后仍然保留&#xff0c;直到被显式删除或浏览器清除缓存。sessionStorage&#xff1a; 存储在 …

oops-framework框架 之 初始了解(一)

引擎&#xff1a;CocosCreator 环境&#xff1a; Mac Gitee: oops-framework 简介 oops-framework是由作者dgflash编写&#xff0c;基于CocosCreator 3.x而实现的开源框架。 该框架以插件形式存在&#xff0c;主要目的是为了降低与项目的耦合&#xff0c;并且通过插件内部的…

【QuickSort】单边快排思路及实现

思路&#xff1a; &#xff08;1&#xff09;首先定义一个递归函数&#xff1a;qucikSort(int [ ] arr,int l,int r)。函数的定义&#xff1a;给定一个数组arr&#xff0c;对它在[l,r]这个区间内的元素进行排序&#xff0c;从而使得整个数组在[l,r]这个区间内有序。 &#xff0…

电梯安全远程监控系统解决方案

一、方案背景 随着万丈高楼的平地起&#xff0c;电梯也成为了我们出入高层建筑最常用的工具之一。面对电梯数量的不断增加&#xff0c;电梯安全事故也是相继频发&#xff0c;因此关于电梯的安全运行就越来越受到社会各界的关注。电梯的使用在给人们出入高层建筑带来便利的同时&…

一种LED驱动专用控制电路方案

一、基本的概述 TM1651 是一种带键盘扫描接口的LED&#xff08;发光二极管显示器&#xff09;驱动控制专用电路&#xff0c;内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。本产品性能优良&#xff0c;质量可靠。采用SOP16/DIP16的封装形式。 二、特性说…

金蝶Apusic应用服务器 任意文件上传漏洞复现

0x01 产品简介 金蝶Apusic应用服务器&#xff08;Apusic Application Server&#xff0c;AAS&#xff09;是一款标准、安全、高效、集成并具丰富功能的企业级应用服务器软件&#xff0c;全面支持JakartaEE8/9的技术规范&#xff0c;提供满足该规范的Web容器、EJB容器以及WebSer…

快速筛出EXCEL行中的重复项

比如A列是一些恶意IP需要导入防火墙&#xff0c;但包括一些重复项&#xff0c;为不产生错误&#xff0c;需要把重复项筛出来&#xff1a; 1、给A列排序&#xff0c;让重复项的内容排在相邻的行 2、在B列中写一个条件函数&#xff1a;IF(A1A2,1,0)&#xff0c;然后下拉至行尾完成…

如何在 AdsPower 浏览器中设置代理

AdsPower是一款反检测指纹浏览器&#xff0c;来自中国开发团队的一款对电子商务营销人员非常有用的强大工具&#xff0c;同时具有出色的英语支持。AdsPower浏览器的主要优势是其价格便宜&#xff0c;与竞争对手相比&#xff0c;但其功能和整体工作表现甚至不逊于Indigo。 AdsP…

基于springboot+vue的点餐系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

IDEA编译器技巧-提示词忽略大小写

IDEA编译器技巧-提示词忽略大小写 写代码时,每次创建对象都要按住 Shift 字母 做大写开头, 废手, 下面通过编译器配置解放Shift 键 setting -> Editor -> General -> Code Completion -> Match case 把这个√去掉, 创建对象就不需要再按住 Shift 键 示例: 1.…

浅谈UML的概念和模型之UML九种图

1、用例图&#xff08;use case diagrams&#xff09; 【概念】描述用户需求&#xff0c;从用户的角度描述系统的功能 【描述方式】椭圆表示某个用例&#xff1b;人形符号表示角色 【目的】帮组开发团队以一种可视化的方式理解系统的功能需求 【用例图】 2、静态图 类图&…

ClassCMS2.4漏洞复现

CMS源码在附件中 环境搭建 使用phpstudy2016搭建web环境&#xff0c;php版本为5.5 安装CMS 这里选择Mysql数据库进行安装 用户名和密码都写默认的admin方便记忆 输入完成后点击安装 点击安装 CMS的安装过程中有个报错忽略就好&#xff0c;登录不进后台的话刷新一下页面 进入了C…

springboot数据格式验证——自定义日期格式验证及list验证

我们在工作中经常需要对日期格式进行定义&#xff0c;如果客户端传来的日期字符串不符合要求&#xff0c;那么根本无法保存&#xff0c;但是已有的注解并没有日期格式的验证&#xff0c;那我们就自己实现一个 一、自定义日期格式验证的注解DateFormat import javax.validatio…

Jquery动画特效

1&#xff0c;Jquery提供的特效方法 2&#xff0c;实例代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…