• 基于STM32CubeMX和keil采用RTC时钟周期唤醒和闹钟实现LED与BEEP周期开关


    前言

    RTC的功能有很多,这里主要介绍RTC的周期唤醒和闹钟功能。
    本篇博客先阐述RTC的概念以及周期唤醒和闹钟的原理,并对STM32CubeMX的配置参数进行阐述,最后结合LED与BEEP进行效果演示。

    最终效果:
    每分钟的第5秒翻转LED0状态.
    每分钟的第30秒翻转BEEP的状态。
    每秒翻转LED1状态。


    1. RTC概念

    RTC(Real-Time Clock),实时时钟。它是由时钟信号驱动的日历时钟,提供日期和时间数据。在STM32F407ZET6里面,有一个RTC,由普中的开发板后面的电源VBAT供电,这个的好处在于它可以提供不间断的日期时间数据。不像我们写程序配置的时间,一般我们关闭了开发板的电源就丢失了。这个RTC其实在我使用中觉得最有用的大概就是使用ssh连接linux系统的时候,往里面传文件,可以看到文件的修改日期。如果没有这个RTC,传输进嵌入式系统的文件的修改日期大概率就是系统最初始的时间,比如1970-1-1。
    RTC有两个可编程的闹钟,库函数中就是AlarmA和AlarmB。可以设定任意组合和重复性闹钟:有一个周期唤醒单元,可以作为一个普通定时器使用;还具有时间戳和入侵检测功能。这篇博客就写的是前半部分,后面会再写一篇后续的功能。

    1.1 RTC的时钟信号源

    我们RTC的时钟是哪里来的?打开看STM32CubeMX看一下时钟配置就知道了
    在这里插入图片描述

    通过上图可以看到RTC的时钟来源有三个:
    LSI:MCU内部的32kHz时钟信号。
    LSE:MCU外接的32.768kHz时钟信号。
    HSE_RTC:MCU外接的高速晶振HSE经过2到31分频后的时钟信号。
    在实际的时钟源选择上,我们一般选择LSE。因为外接的32.768kHz的时钟,经过多次二分频后就可以得到精确的1Hz的时钟信号,转成时间就是1s一个周期。

    STM32CubeMx只给出RTC的时钟来源,RTC的具体框图如下。
    在这里插入图片描述


    1.2 预分频器

    要想实现输出不同频率的时钟,就取决于预分频器的系数。对于给定的初始RTC时钟源信号,只有经过预分频器的分频,才可以在指定引脚输出我们想要的频率的时钟。

    在上图中,以32.768kHz的LSE时钟源为例,RTC的时钟源经过精密校准后,通过异步分频器128分频,得到ck_apre为256Hz。256Hz的时钟信号经过同步分频256分频,得到1Hz的ck_spre信号。

    ck_apre和ck_spre经过一个选择器后,可以选择其中一个时钟信号作为RTC_CALIB时钟信号,这个时钟信号经过输出控制选择,可以输出到复用引脚RTC_AF1,也就是可以向外部提供一个256Hz(异步分频)或1Hz(异步+同步分频)的时钟信号。


    1.3 实时时钟与日历数据

    上图RTC的总框图中有两个暗部的影子寄存器
    RTC_SSR:亚秒计数器
    RTC_TR:时间计数器
    RTC_DR:日期计数器

    系统每隔两个RTCCLK周期就讲当前的日历值复制到影子寄存器中。当程序读取日期时间数据时,读取的是影子寄存器的内容,而不会影响日历计数器的工作。
    本质上我认为影子寄存器就是用来做一个数据备份,主要备份的就是亚秒,时间,日期。


    1.4 周期性自动唤醒

    我在写定时器TIM的相关博客的时候写到过一个自动重装载值。比如我将该值设定为10,那么计数器到10就触发一次事件,同时计数器从0开始计数。这个周期自动唤醒的功能也类似。

    RTC内有一个16位自动重载递减计数器,可以产生周期性的唤醒中断,16位寄存器RTC_WURT存储用于设置定时周期的自动重载值。周期唤醒定时器的输入时钟有两个来源:

    1.同步预分频器输出的clk_spre时钟信号,通常是1Hz
    2.RTCCLK经过2、4、8、16分频后的时钟信号(结合一下RTC的原理框图)

    一般可以在周期性唤醒中断里读取RTC当前时间。例如,设置周期唤醒时钟源为1Hz的ck_spre信号,并且每秒中断一次。唤醒中断产生时间信号WUTF,这个信号可以配置到复用引脚RTC_AF1。


    1.5 可编程闹钟

    在STM32F407ZET6中有两个可编程闹钟,闹钟A,闹钟B。
    闹钟的时间和重复方式可以自定义,后面STM32CubeMX配置的时候阐述。闹钟触发的时候闹钟A,B分别产生事件信号ALRAF和ALRBF。这两个信号和周期唤醒事件WUTF一起经过一个选择器,可以选择一个信号作为输出信号RTC_ALARM,再通过输出控制可以输出到复用引脚RTC_AF1。
    在这里插入图片描述


    2. RTC相关中断

    我这里只介绍用到的时钟周期唤醒以及闹钟对应的中断名称和ISR。

    中断号中断名称说明ISR
    3RTC_WKUP连接到EXTI 22线的RTC唤醒中断RTC_WKUP_IRQHandler()
    41RTC_Alarm连接到EXTI 17线的RTC闹钟(A和B)中断RTC_Alarm_IRQHandler()

    两个中断可以触发的中断事件以及对应的回调函数如下表。

    中断名称中断事件源中断事件类型输出或输引脚回调函数
    RTC_Alarm闹钟ARTC_IT_ALRARTC_AF1HAL_RTC_AlarmAEventCallback()
    RTC_Alarm闹钟BRTC_IT_ALRBRTC_AF1HAL_RTCEx_AlarmBEventCallback()
    RTC_WKUP周期唤醒RTC_IT_WUTRTC_AF1HAL_RTCEx_WakeUpTimerEventCallback()

    对于STM32F407ZET6,复用引脚RTC_AF1是引脚PC13,RTC_AF2是引脚PI8。但是只有178个引脚的MCU才有PI8,所以普中这款STM32F407开发板上面是没有RTC_AF2只有RTC_AF1。

    写到这里,其实我们大概已经知道怎么做了。对于最终效果:
    每分钟的第5秒翻转LED状态.
    每分钟的第30秒翻转BEEP的状态。
    每秒翻转LED1状态。
    我们只需要在调用中断函数的时候翻转一下电平就可以了。
    现在的问题是什么时候调用中断,怎么判定设置闹钟以及周期唤醒。

    下面我们用STM32CubeMX来详细阐述一下。


    3. STM32CubeMX配置

    3.1 时钟配置

    刚才讲到RTC的1Hz的分频,最好选择的是时钟源是外部的低速晶振。
    在这里插入图片描述
    在这里插入图片描述

    3.2 引脚配置

    LED和蜂鸣器配置
    在这里插入图片描述

    在这里插入图片描述

    RTC时钟输出引脚
    在这里插入图片描述

    在这里插入图片描述

    3.3 RTC配置

    这里我们不涉及到时间戳等RTC其他功能,只考虑我们用到的周期唤醒和闹钟。

    3.3.1 模式选择

    在这里插入图片描述

    对于Timers模块,我们需要启用时钟源以及日历。

    AlarmA和AlarmB都有三个选项。
    在这里插入图片描述

    Disable:禁用
    Internal Alarm:内部闹钟功能
    Routed to AF1:闹钟事件信号输出到复用引脚RTC_AF1。

    WakeUp也有三个选项。
    在这里插入图片描述

    Disable:禁用
    Internal WakeUp:内部唤醒功能
    Routed to AF1:闹钟事件信号输出到复用引脚RTC_AF1。

    这里注意,Routed to AF1这个选项,有且只能有一个支持配置。也就是说AlarmA ,AalarmB,WakeUp三种唤醒方式只能支持一种配置到AF1。一旦AF1被占用了,那么其他的唤醒方式不能配置输出到AF1。


    3.3.2 RTC基本参数配置

    在这里插入图片描述

    General
    Hour Format: 小时格式,可选12h制或者24小时制。
    Asynchronous Predivider value:异步分频器值。设置值为0~127,对应分频系数1-128。当RTCCLK为32.768kHz时,128分频后就是256Hz。
    Synchronous Predivider value:同步预分频器。设置值为0~32767,对应分频系数为1-32768。256Hz分频后就是1Hz。
    Output Polarity:输出极性。闹钟A,B以及周期唤醒中断事件信号有效时的输出极性,可设置为高电平或低电平。
    Output Polarity:输出类型。复用引脚RTC_AF1的输出类型,可选开漏输出或者推挽输出。

    Calendar Time
    Data Format:数据格式。可选择二进制格式或者BCD格式。
    Hours:初始化时间数据的时。
    Minutes:初始化时间数据的分。
    Seconds:初始化时间数据的秒。
    Day Light Saving: value of hour adjustment:夏令时设置。这里设置为不使用夏令时。啥叫夏令时?
    Store Operation:存储操作。表示是否已经对夏令时设置做修改。设置为Reset表示未修改夏令时。Set则表示已修改。

    Calendar Date
    这个分组主要设置的是初始化的日期。
    Week Day:周几
    Month:几月
    Date:几日
    Year:几年


    唤醒方式设置。
    在这里插入图片描述

    因为AlarmB和AlarmA的设置是一样的,我这里方便截图,就直接用AlarmB做解释了。

    AlarmA/B
    Hours:时 0-23
    Minutes:分 0-59
    Seconds:秒 0-59
    Sub Seconds:亚秒 0-59
    Alarm Mask Date Week day:屏蔽日期。设置为Enable表示屏蔽,即闹钟与日期无关。反之有关
    Alarm Mask Hours:屏蔽小时。Enable表示闹钟与小时数据无,反之有关。
    Alarm Mask Minutes:屏蔽分钟。Enable表示闹钟与分钟数据无,反之有关。
    Alarm Mask Seconds:屏蔽秒。Enable表示闹钟与秒数据无,反之有关。
    Alarm Sub Second Mask:屏蔽亚秒。Enable表示闹钟与亚秒数据无,反之有关。
    Alarm Date Week Day Sel:日期形式。有Date和Weekday两种选项。选项Date表示用1-31表示日期。选择后者则表示用Monday到Sunday表示星期几
    Alarm Date:日期。1-31或Monday-Sunday。

    这里屏蔽日期什么含义,具体来说就是,我正常设置一个闹钟是哪一天哪一时哪一分哪一秒,如果屏蔽了日期,那也就是说我每天的固定时分秒都会响闹钟。屏蔽日期与小时,则说明,每小时的第几分钟第几秒都会响闹钟。以此类推。

    Wake UP
    Wake Up Clock:周期唤醒的时钟源。
    Wake Up Counter:唤醒计数器的重载值。设定范围为0-65535。这个就是计数器到达设定值就触发中断,接着重新计数。如果这个值设置为0,则每个时钟周期中断一次。这里WakeUpClock设置为1Hz,WakeUpCounter设置为0,则表示每秒触发一次中断。

    这里WakeUpClock的值是通过分频来获得的。
    在这里插入图片描述

    3.3 中断配置

    这里中断这样设置,表明周期唤醒的优先级高于闹钟的中断。
    这里主

    在这里插入图片描述


    4. 代码编写

    实现我们想要的电平翻转其实就只需要对3个回调函数做一下处理就行。
    每次来一个中断就翻转一下电平

    void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
    {
    	HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
    }
    void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
    {
    	HAL_GPIO_TogglePin(BEEP_GPIO_Port,BEEP_Pin);
    }	
    void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
    {
    	HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总结

    这里WakeUp的输出到RTF_AF1的电平是高电平,可以用示波器抓一下看看。我这通过杜邦线引出来看LED,只能看到微弱的闪烁。
    这篇博客主要是RTC的一些基本概念以及简单运用,和TIM定时器相似,不过多了很多东西。要对比学习。

  • 相关阅读:
    网络框架重构之路plain2.0(c++23 without module) 环境
    [附源码]Python计算机毕业设计Django基于微信小程序的网络办公系统
    【软考:系统集成项目管理】之 项目成本管理
    FiberNode结构解析
    【RT-Thread】nxp rt10xx 设备驱动框架之--Pin搭建和使用
    使用docker安装RocketMQ
    基于ubuntu20.04的 ros2(foxy版本)安装
    如何用python制作炫酷的个人足迹地图?
    用已安装好的系统级别PsychoPy软件配置Python虚拟环境
    众和策略:小盘和大盘的关系?
  • 原文地址:https://blog.csdn.net/Edwinwzy/article/details/132842478