【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟
程序员文章站
2022-06-09 16:49:06
...
RTC实时时钟用来获取当前的日期和时间,在一些嵌入式的设备里十分常见,F767 的RTC相对于F1 来说,带了日历功能,提供年月日时分秒信息、两个可编程闹钟(ALARM A 和 ALARM B)中断和其他一些功能。Nucleo开发板板载了32.768KHz的时钟晶振,但是却没有板载RTC电池。
一、RTC实时时钟
1、配置CubeMX
开启RCC的低速时钟,选择外部晶体振荡器。RTC选择内部唤醒。
选择外部的32.768KHz的时钟:
配置RTC选项卡:日期为 2018.2.8.23:15:00,周四
2、生成代码,主函数添加如下代码:
/* USER CODE BEGIN 1 */
RTC_DateTypeDef sDate;
RTC_TimeTypeDef sTime;
/* USER CODE END 1 */
定义存储时间信息的结构体变量
HAL_Delay(1000);
HAL_RTC_GetTime(&hrtc, &sTime,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate,RTC_FORMAT_BIN);
printf("20%d %d %d 周%d %d:%d:%d \n",sDate.Year,sDate.Month,sDate.Date,sDate.WeekDay,
sTime.Hours,sTime.Minutes,sTime.Seconds);
3、编译下载到开发板,打开串口,可以看到输出的时间
注意:必须要先读取时间,再去读取日期,否则会出现先错误:
在“stm32f7xx_hal_rtc.c”文件里的
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
函数定义部分,有这样的说明“You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values”
二、设置闹钟
在刚刚的工程中配置:
1、打开RTC的闹钟1
2、开启闹钟的中断
3、设置优先级分组:
4、生成代码,在主函数下面的用户代码区编写闹钟中断回调函数:
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
printf("定时时间到!");
}
5、在“MX_RTC_Init()”的函数定义部分,CubeMX生成的代码是 先去检测:
if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2)
条件成立才会设置日期时间和闹钟,设置好之后,会自动往RTC的后备寄存器中写入0x32F2,表示已经设置过时间了。所以下载代码之后,需要给板子重新上电,来清空后备寄存器里的值。对于板载RTC电池的开发板来说,就要在程序中进行修改了。
/* RTC init function */
void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;
/**Initialize RTC Only
*/
hrtc.Instance = RTC;
if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){
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;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x23;
sTime.Minutes = 0x15;
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(__FILE__, __LINE__);
}
sDate.WeekDay = RTC_WEEKDAY_THURSDAY;
sDate.Month = RTC_MONTH_FEBRUARY;
sDate.Date = 0x8;
sDate.Year = 0x18;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Enable the Alarm A
*/
sAlarm.AlarmTime.Hours = 0x23;
sAlarm.AlarmTime.Minutes = 0x15;
sAlarm.AlarmTime.Seconds = 0x30;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
sAlarm.AlarmDateWeekDay = RTC_WEEKDAY_THURSDAY;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Enable the WakeUp
*/
if (HAL_RTCEx_SetWakeUpTimer(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
}
}
效果如下图:在23:15:30 时发来了定时时间到的字样。