STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)

发布者:JoyfulLife最新更新时间:2021-07-19 来源: eefocus关键字:STM32CubeMX  实时时钟  RTC 手机看文章 扫描二维码
随时随地手机看文章

本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的 RTC 外设。


1. 准备工作

硬件准备

首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi):

软件准备

  • 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码。

2.生成MDK工程

选择芯片型号

打开STM32CubeMX,打开MCU选择器:
mark

搜索并选中芯片STM32L431RCT6:
mark

配置时钟源

  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;

  • 如果使用默认内部时钟(HSI),这一步可以略过;

这里我都使用外部时钟:
mark

配置串口

开发板板载了一个CH340换串口,连接到USART1。

接下来开始配置USART1:

配置RTC

RTC外设全称 Real-Time Clock,主要用处为:

  • 日历:输出年月日、时分秒、星期

  • 闹钟:提供闹钟中断

  • 唤醒:低功耗模式唤醒中断

① 配置RTC外设的时钟来源

首先选中RTC外设,激活时钟源:

RTC外设的时钟来源有三种:

  • 外部低速时钟(LSE):产生32.768KHz的时钟信号

  • 内部低速时钟(LSI):产生的32KHz时钟信号

  • 外部高速时钟分频(HSE_RTC):产生的32KHz时钟信号

小熊派开发板上设计了外部晶振,切换到 Clock Configuration 页面,配置为使用外部晶振(若无法选择,检查LSE时钟是否配置为外部晶振):

② 配置预分频器

RTC外设时钟源信号进来后经过两个预分频器,如图中红框所示:

  • 异步预分频器(async):7bit、默认值为128,产生ck_apre时钟信号,为亚秒级计数器RTC_***提供时钟;

  • 同步预分频器(sync):15bit、默认值为256,产生ck_spre时钟信号,为日历更新提供时钟;

    本文中采用LSE作为RTC外设时钟源,在两个分频器的值都是默认值的情况下,最后产生的时钟节拍为 1Hz。

f s p r e = 32768 / 128 / 256 = 1 H z f_{spre} = 32768/128/256=1Hz fspre=32768/128/256=1Hz
所以,此处两个预分频器的值保持默认即可:

③ 配置日历

激活日历功能,并设置日期和时间初始值:

关于二进制码和BCD码,比如当前是36秒(十进制),换算为十六进制就是一个字节0x24,但BCD码是用一个字节的高4位和低4位分别来表示3和6,3的十六进制是0x03,6的十六进制是0x06,合在一起BCD码就是0x36。

配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:
mark

生成工程设置

代码生成设置

最后设置生成独立的初始化文件:

生成代码

点击GENERATE CODE即可生成MDK-V5工程:
mark

3. 在MDK中编写、编译、下载用户代码

printf重定向

STM32CubeMX_09 | 重定向printf函数到串口输出的多种方法

RTC时间/日期设置与读取

时分秒可以从RTC时间寄存器(RTC_TR)中读出:

日期可以从RTC日期寄存器(RTC_DR)中读出:


在HAL库中提供了读取时间、读取日期、设置时间、设置日期的API:


/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions

* @{

*/

/* RTC Time and Date functions ************************************************/

HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);

HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);

HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);

HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);

/**

* @}

*/

其中时间结构体RTC_TimeTypedef的设计如下:


/**

* @brief RTC Time structure definition

*/

typedef struct

{

uint8_t Hours; /*!< Specifies the RTC Time Hour.

This parameter must be a number between Min_Data = 0 and Max_Data = 12 if the RTC_HourFormat_12 is selected.

This parameter must be a number between Min_Data = 0 and Max_Data = 23 if the RTC_HourFormat_24 is selected */


uint8_t Minutes; /*!< Specifies the RTC Time Minutes.

This parameter must be a number between Min_Data = 0 and Max_Data = 59 */


uint8_t Seconds; /*!< Specifies the RTC Time Seconds.

This parameter must be a number between Min_Data = 0 and Max_Data = 59 */


uint8_t TimeFormat; /*!< Specifies the RTC AM/PM Time.

This parameter can be a value of @ref RTC_AM_PM_Definitions */


uint32_t SubSeconds; /*!< Specifies the RTC_*** RTC Sub Second register content.

This parameter corresponds to a time unit range between [0-1] Second

with [1 Sec / SecondFraction +1] granularity */


uint32_t SecondFraction; /*!< Specifies the range or granularity of Sub Second register content

corresponding to Synchronous pre-scaler factor value (PREDIV_S)

This parameter corresponds to a time unit range between [0-1] Second

with [1 Sec / SecondFraction +1] granularity.

This field will be used only by HAL_RTC_GetTime function */


uint32_t DayLightSaving; /*!< Specifies RTC_DayLightSaveOperation: the value of hour adjustment.

This parameter can be a value of @ref RTC_DayLightSaving_Definitions */


uint32_t StoreOperation; /*!< Specifies RTC_StoreOperation value to be written in the BKP bit

in CR register to store the operation.

This parameter can be a value of @ref RTC_StoreOperation_Definitions */

} RTC_TimeTypeDef;

其中日期结构体RTC_DataTypedef的设计如下:


/**

* @brief RTC Date structure definition

*/

typedef struct

{

uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay.

This parameter can be a value of @ref RTC_WeekDay_Definitions */


uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format).

This parameter can be a value of @ref RTC_Month_Date_Definitions */


uint8_t Date; /*!< Specifies the RTC Date.

This parameter must be a number between Min_Data = 1 and Max_Data = 31 */


uint8_t Year; /*!< Specifies the RTC Date Year.

This parameter must be a number between Min_Data = 0 and Max_Data = 99 */


} RTC_DateTypeDef;


编写测试程序

基于上述API,编写测试程序:每秒读取一次日期和时间。


首先在main函数中创建变量:


/* USER CODE BEGIN 1 */

HAL_StatusTypeDef status;

RTC_TimeTypeDef sTime;

RTC_DateTypeDef sDate;


/* USER CODE END 1 */

接着编写初始化部分的代码:


/* USER CODE BEGIN 2 */

printf("RTC test on bearpi borad by mculover666!rn");


/* USER CODE END 2 */

最后编写循环中的代码:


/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */


/* USER CODE BEGIN 3 */

// read rtc time

status = HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);

if (status != HAL_OK) {

printf("get time fail, status is %drn", status);

}


// read rtc date

status = HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);

if (status != HAL_OK) {

printf("get date fail, status is %drn", status);

}

printf("%d-%d-%d(%d) %d:%d:%d:%drn", sDate.Year, sDate.Month, sDate.Date, sDate.WeekDay,

sTime.Hours, sTime.Minutes, sTime.Seconds, sTime.SubSeconds);


HAL_Delay(1000);

}

/* USER CODE END 3 */


测试结果为:


4. RTC闹钟功能

设置闹钟

RTC外设带有Alarm A和 Alarm B两个闹钟,两个闹钟用法相同,这里我用 Alarm A 演示如何使用。


配置开启闹钟:

设定闹钟值,MASK用来决定闹钟匹配时是否屏蔽该字段:

当RTC当前值和闹钟设定值相同时,会将RTC初始值和状态寄存器(RTC_ISR)中的 ALRAF 标志位硬件置位:

RTC闹钟的中断

RTC外设没有独立的中断,但是ST巧妙的将RTC外设都连接到了外部中断EXTI,通过触发EXTI来产生RTC外设中断。

通过查阅参考手册可以看到使能 RTC 闹钟中断的步骤:

前两步配置并使能EXTI、选择上升沿有效,配置并使能 RTC_Alarm 中断,在cubemx中直接使能即可:

第三步配置RTC生成闹钟中断,在上一小节设置闹钟时间时,cubemx生成的代码中会自动生成该步代码。


至此,配置完成,生成代码。

编写闹钟中断回调函数

cubemx中默认配置了生成外设中断服务函数,并在其中调用HAL的处理函数:

所以在stm32l4xx_it.c文件中可以看到闹钟中断处理函数:

按照HAL库的中断处理思想,编写回调函数,这里需要注意,因为RTC外设所有的中断都是通过EXTI触发的,所以中断触发后,HAL会根据不同的标志位去调用不同的回调函数。

HAL库提供了两种机制供我们使用,通过宏定义USE_HAL_RTC_REGISTER_CALLBACKS的值来判断。


① 当宏定义USE_HAL_RTC_REGISTER_CALLBACKS的值为0时,HAL库默认提供了弱定义的回调函数:


我们只需要重新实现即可,如下:


/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

// RTC Alarm A Event callback

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)

{

/* Prevent unused argument(s) compilation warning */

UNUSED(hrtc);


printf("---> alarm a callback! <---rn");

}

/* USER CODE END 0 */

② 当宏定义USE_HAL_RTC_REGISTER_CALLBACKS的值为1时,HAL库并提供了回调函数注册机制,API如下:


/* Callbacks Register/UnRegister functions ***********************************/

#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)

HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback);

HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID);

#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */


其中CallbackID是一个枚举类型,pCallback 是一个函数指针,定义如下:


所以我们可以在main.c中编写如下的回调函数,用于处理Alarm A闹钟中断:


/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

// RTC Alarm A Event callback

void AlarmAEventCallback(RTC_HandleTypeDef *hrtc)

{

printf("---> alarm a callback! <---rn");

}


/* USER CODE END 0 */

最后在main函数初始化代码之后,注册该回调函数:


/* USER CODE BEGIN 2 */

printf("RTC test on bearpi borad by mculover666!rn");


status = HAL_RTC_RegisterCallback(&hrtc, HAL_RTC_ALARM_A_EVENT_CB_ID, AlarmAEventCallback);

if (status != HAL_OK) {

printf("rtc register callback fail!rn");

} else {

printf("rtc register callback success!rn");

}

/* USER CODE END 2 */


测试结果

关键字:STM32CubeMX  实时时钟  RTC 引用地址:STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)

上一篇:基于STM32的多路电压测量设计方案
下一篇:Linux下开发stm32(一) | 使用gcc-arm-none-eabi工具链编译

推荐阅读最新更新时间:2024-11-14 00:38

STM32L051的RTC的坑 基于HAL库
条件1:STM32L051K8T6 条件2:HAL库1.10.0 坑:在调用HAL_Get_Date()前必需先调用HAL_Get_Time,否则取出来的时间,会存在延时,即取值错误! 错误示例: 200ms打印一次,输出结果 : 正确示例: 200ms打印一次,输出结果 : 其实在HAL库的HAL_Get_Time()和HAL_Get_Date()函数说明中有说明: 如果粗心没看到的话,容易卡在这里好几天,比如说我。
[单片机]
STM32L051的<font color='red'>RTC</font>的坑 基于HAL库
STM32CubeMX串口接收中断
才接触到cube,目前只实现了固定长度的接收。配置好后,在while(1)前加入配置接收中断。我也是跟踪代码慢慢找到这句的,目前对于cube的库函数一点都不了解。 if(HAL_UART_Receive_IT(&huart1,usart1_rxBuf,5)!=HAL_OK)Error_Handler(); 打开it.c。找到 void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEG
[单片机]
[正点原子]STM32开发板F103 第41讲 RTC实时时钟备份区域BKP原理
RTC模块与 时钟配置系统在后备区域,在复位时候不会被清除(框图: 中文参考手册) 如何使用RTC实现时钟?RTCCLK RTC的时钟有几个来源有三种 32.768khz 8Mhz 40khz RTC_PRL是自动重装载寄存器 RTC_DIV 预分频余数寄存器 RTC_DIV的作用就是 可以提供一个更加精确的时钟, 时钟开启之后会给RTC_PRL写一个值(比如100),那么RTCCLK就会被 /100 之后得到 TR_CLK。 TR_CLK的一个周期有100个 RTCCLK ,RTC_DIV在你装载之后它的值就是100,他在 RTCCLK的控制下每一个时钟 减一, 假如RTCCLK=100hz,那么 RT
[单片机]
[正点原子]STM32开发板F103 第41讲 <font color='red'>RTC</font><font color='red'>实时时钟</font>备份区域BKP原理
STM32CubeMX开发环境的搭建
1、安装包下载 由于STM32CubeMX软件是基于JAVA环境运行的,所以需要安装JRE才能使用,JRE、STM32CubeMX工具和库可以到官网下载。TM32CubeMX要求JRE最低版本是1.7.0_45,如果你电脑已安装JRE版本大于1.7.0_45,则可以不用再下载安装。 1.1 Oracle官方下载JRE http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html 接受许可,根据自己电脑系统选择下载,如下图: 1.2 ST官方下载STM32CubeMX工具、库 官网可以下载最新版本的软件,STM32C
[单片机]
<font color='red'>STM32CubeMX</font>开发环境的搭建
STM32入门学习笔记之RTC实验(下)
(2)创建rtc.c文件并输入以下代码。 #include rtc.h /*************************************************** Name :RTC_Init Fuction :RTC初始化 Parameter :None Return :None ***************************************************/ void RTC_Init() { if( BKP- DR1!=0x5050 ) { RCC- APB1ENR |= 1 28 ; //使能PWR时钟
[单片机]
stm32cubemx 多路adc采集
采用的软件是STM32CUBEMX+KEIL5 硬件为stm32F103C8T6 我与原文作者做的区别在于 External Trigger Conversion Edge,我在进行配置的时间没有None选项,我选择的是默认的Regular Conversion launched by software 原文地址: http://www.eemaker.com/stm32cubemxadc.html 实现功能:stm32cubeMX配置ADC多通道采集(非dma和中断方式) Stm32ADC的转换模式还是很灵活,很强大,模式种类很多,那么这也导致很多人使用的时候没细心研究参考手册的情况下容易混淆。不知道该用哪种方
[单片机]
<font color='red'>stm32cubemx</font> 多路adc采集
STM32cubeMX学习记录1-点亮LED
一、准备工作: 1、安装STM32cubeMX软件,注意我使用的是5.0版之前的 2、安装keil-ARM软件,注意版本最好是5.2.6以后的 3、准备一个开发板 二、点灯实验(PB5接一个LED灯,低电平灯亮,高电平灯灭) (后续涉及到多种方式操作的,只讲解一种,追求能实现目的即可) 1、打开STM32cubuMX软件 2、选择左边居中位置的“New Project”进行新建一个工程; 3、先输入开发板上芯片的型号,然后再双击选择实际的芯片封装; 4、晶振RCC设置,根据自己开发板上的情况选择。如图是开发板上的外部HSE和LSE都选择上了。 5、仿真器设置:使用ST
[单片机]
<font color='red'>STM32cubeMX</font>学习记录1-点亮LED
STM32L151C8周期性从待机模式唤醒(RTC Wakeup Timer)
#include stm32l1xx.h #include system_stm32l1xx.h #include OLED.h #include delay.h void RtcWakeUpConfig(void); u8 RtcInit(void); u8 RtcConfig(void); int main() { DelayInit(); //延时初始化 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR时钟 if(PWR_GetFlagStatus(PWR_FLAG_SB)) //从待机模式唤醒 { PWR_Cle
[单片机]
STM32L151C8周期性从待机模式唤醒(<font color='red'>RTC</font> Wakeup Timer)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved