STM32H743-ARM例程15-RTC
目录
- 实验平台
- RTC
- RTC介绍
- RTC框图
- 1.时钟源
- 2.预分频器
- 3.日历时间(RTC_TR)和日期(RTC_DR)寄存器
- 4.可编程闹钟
- 5.周期性自动唤醒
- STM32CubeMX生成工程
- 实验代码
- 实验现象
实验平台
硬件:银杏科技GT7000双核心开发板-ARM-STM32H743XIH6,银杏科技iToolXE仿真器
软件:最新版本STM32CubeH7固件库,STM32CubeMX v6.10.0,开发板环境MDK v5.35,串口工具putty
RTC
RTC介绍
RTC(Real-Time Clock)是电子设备中的独立计时模块,功能类似于电子手表,用于管理所有低功耗模式的自动唤醒单元。实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供具有可编程闹钟中断功能的日历时钟/日历。RTC拥有独立电源域:通过VBAT引脚连接备份电池(典型3V CR2032),主电源关闭时保持计时。
主要特性如下:
- 包含亚秒、秒、分钟、小时(12/24 小时制)、星期几、日期、月份和年份的日历。
- 软件可编程的夏令时补偿,自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。
- 具有中断功能的可编程闹钟。可通过任意日历字段的组合触发闹钟。
- 自动唤醒单元,可周期性地生成标志以触发自动唤醒中断。
- 参考时钟检测:可使用更加精确的第二时钟源(50Hz 或 60Hz)来提高日历的精确度。
- 利用亚秒级移位特性与外部时钟实现精确同步。
- 数字校准电路(周期性计数器调整):精度为 0.95ppm,在数秒钟的校准窗口中获得。
- 用于事件保存的时间戳功能。
- 带可配置过滤器和内部上拉的入侵检测事件。
- 可屏蔽中断/事件:
- –闹钟 A
- –闹钟 B
- –唤醒中断
- –时间戳
- –入侵检测
- 32 备份寄存器。
RTC框图
1.时钟源
STM32H743 的 RTC 时钟(RTCCLK)通过时钟控制器,可以从 LSE 时钟、LSI 时钟以及HSE 时钟三者中选择(通过 RCC_BDCR寄存器选择)。一般我们选择 LSE,即外部 32.768Khz 晶振作为时钟源(RTCCLK),而 RTC时钟核心,要求提供 1Hz 的时钟,所以,我们要设置 RTC 的可编程预分配器。
2.预分频器
STM32H743的可编程预分配器(RTC_PRER)分为 2 个部分:
(1) 一个通过 RTC_PRER 寄存器的 PREDIV_A 位配置的 7 位异步预分频器。
(2) 一个通过 RTC_PRER 寄存器的 PREDIV_S 位配置的 15 位同步预分频器。
RTC 框图中,ck_spre 的时钟可由如下计算公式计算:
Fck_spre=Frtcclk/[(PREDIV_S+1)*(PREDIV_A+1)]
其中,Fck_spre 即可用于更新日历时间等信息。PREDIV_A 和 PREDIV_S 为 RTC 的异步和同步分频器。且推荐设置 7 位异步预分频器(PREDIV_A)的值较大,以最大程度降低功耗。
3.日历时间(RTC_TR)和日期(RTC_DR)寄存器
STM32H743 的 RTC 日历时间(RTC_TR)和日期(RTC_DR)寄存器,用于存储时间和日期(也可以用于设置时间和日期),可以通过与 PCLK1(APB1 时钟)同步的影子寄存器来访问,这些时间和日期寄存器也可以直接访问,这样可避免等待同步的持续时间。
每隔 2 个 RTCCLK 周期,当前日历值便会复制到影子寄存器,并置位 RTC_ISR 寄存器的 RSF 位。我们可以读取RTC_TR 和 RTC_DR 来得到当前时间和日期信息,不过需要注意的是:时间和日期都是以BCD 码的格式存储的,读出来要转换一下,才可以得到十进制的数据。
4.可编程闹钟
STM32H743 提供两个可编程闹钟:闹钟 A(ALARM_A)和闹钟 B(ALARM_B)。通过 RTC_CR 寄存器的 ALRAE 和 ALRBE 位置 1 来使能闹钟。当日历的亚秒、秒、分、小时、日期分别与闹钟寄存器RTC_ALRMASSR/RTC_ALRMAR和RTC_ALRMBSSR/RTC_ALRMBR 中的值匹配时,则可以产生闹钟(需要适当配置)。本章我们将利用闹钟A 产生闹铃,即设置RTC_ALRMASSR 和 RTC_ALRMAR 即可。
5.周期性自动唤醒
STM32H743 的 RTC 不带秒钟中断,但是多了一个周期性自动唤醒功能。周期性唤醒功能,由一个 16 位可编程自动重载递减计数器(RTC_WUTR)生成,可用于周期性中断/唤醒。
我们可以通过 RTC_CR 寄存器中的WUTE 位设置使能此唤醒功能。唤醒定时器的时钟输入可以是:2、4、8 或 16 分频的 RTC 时钟(RTCCLK),也可以是 ck_spre 时钟(一般为1 HZ)。
本实验中,通过软件对 RTC 计数器进行相关的配置,可以提供时钟功能,通过修改计时器的值可以调整时钟。最终通过串口在终端显示时间。
STM32CubeMX生成工程
我们参考前面章节STM32H743-结合CubeMX新建HAL库MDK工程,打开CubeMX软件,重复步骤不再展示,我们来看配置RTC部分如下图所示:
实验代码
1. 主函数
int main(void)
{RTC_TimeTypeDef sTime;//定义RTC_TimeTypeDef结构体类型下的结构体变量sTime(时间)RTC_DateTypeDef sDate;//(日期)int second_bak = 0;MPU_Config();HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART6_UART_Init();uart6.initialize(115200);//设置RTC日期和时间my_rtc.set_date(25,3,11,2);my_rtc.set_time(14,32,00);while (1){if(systick._500ms_flag == 1){systick._500ms_flag = 0;HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);//使用HAL库函数获取RTC的时间信息,将结果存储在sTime变量中HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);//使用HAL库函数获取RTC的日期信息,将结果存储在sDate变量中if(second_bak != sTime.Seconds) //上一秒的秒数second_bak是否与当前秒数sTime.Seconds不相等,用于实现每秒钟输出一次RTC时间{uart6.printf("\x0c"); //用于清屏操作uart6.printf("\033[1;32;40m"); //用于设置终端显示颜色uart6.printf("Hello,I am GT7000!\r\nThis is RTC TIME interface!\r\n");uart6.printf("RTC TIME:");uart6.printf(" %02d:%02d:%02d",sTime.Hours,sTime.Minutes,sTime.Seconds); //将格式化后的时间信息发送到UART6,格式为"时:分:秒"uart6.printf("20%02d-%02d-%02d星期期%01d\r\n\r\n",sDate.Year,sDate.Month,sDate.Date,sDate.WeekDay);//将格式化后的日期信息发送到UART6,格式为"年-月-日 星期-"second_bak = sTime.Seconds;}}}
}
2. RTC初始化
void MX_RTC_Init(void)
{RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef sDate = {0};hrtc.Instance = RTC;hrtc.Init.HourFormat = RTC_HOURFORMAT_24;hrtc.Init.AsynchPrediv = 127;hrtc.Init.SynchPrediv = 255;hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;if (HAL_RTC_Init(&hrtc) != HAL_OK){Error_Handler();}sTime.Hours = 0x11;sTime.Minutes = 0x40;sTime.Seconds = 0x0;sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;sTime.StoreOperation = RTC_STOREOPERATION_RESET;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK){Error_Handler();}sDate.WeekDay = RTC_WEEKDAY_TUESDAY;sDate.Month = RTC_MONTH_MARCH;sDate.Date = 0x11;sDate.Year = 0x0;if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK){Error_Handler();}if (HAL_RTCEx_SetWakeUpTimer(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK){Error_Handler();}
}
该函数用来初始化 RTC 配置以及日期和时钟,这里设置时间和日期,分别是通过
HAL_RTC_SetTime 函数和 HAL_RTC_SetDate 函数来实现。
3、设置时间和日期
主函数中调用设置时间和日期的自定义函数rtc_set_time 和rtc_set_date 来设置初始时间日期,这两个函数实际就是调用库函数里面的 HAL_RTC_SetTime 函数和HAL_RTC_SetDate函数来实现的,它们的定义如下:
static int rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec)
{RTC_TimeTypeDef sTime;sTime.Hours = hour;sTime.Minutes = min;sTime.Seconds = sec;sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;sTime.StoreOperation = RTC_STOREOPERATION_RESET;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){while(1);}return 0;
}
static int rtc_set_date(unsigned char year,unsigned char month,unsigned char date,unsigned char week)
{RTC_DateTypeDef sDate;sDate.WeekDay = week;sDate.Month = month;sDate.Date = date;sDate.Year = year;if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK){while(1);} return 0;
}
实验现象
在终端屏幕上可以看到显示的时间和日期。如图所示。