欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

程序员文章站 2022-06-09 16:49:06
...

  RTC实时时钟用来获取当前的日期和时间,在一些嵌入式的设备里十分常见,F767 的RTC相对于F1 来说,带了日历功能,提供年月日时分秒信息、两个可编程闹钟(ALARM A 和 ALARM B)中断和其他一些功能。Nucleo开发板板载了32.768KHz的时钟晶振,但是却没有板载RTC电池。


一、RTC实时时钟

1、配置CubeMX

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

开启RCC的低速时钟,选择外部晶体振荡器。RTC选择内部唤醒。


选择外部的32.768KHz的时钟:

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟


配置RTC选项卡:日期为 2018.2.8.23:15:00,周四

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟


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、编译下载到开发板,打开串口,可以看到输出的时间

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟


注意:必须要先读取时间,再去读取日期,否则会出现先错误:

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

在“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”

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟


二、设置闹钟

在刚刚的工程中配置:

1、打开RTC的闹钟1

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

2、开启闹钟的中断

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

3、设置优先级分组:

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟

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 时发来了定时时间到的字样。

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟