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

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


一、RTC实时时钟

1、配置CubeMX

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第1张图片

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


选择外部的32.768KHz的时钟:

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第2张图片


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

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第3张图片


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实时时钟+闹钟_第4张图片


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

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第5张图片

在“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实时时钟+闹钟_第6张图片


二、设置闹钟

在刚刚的工程中配置:

1、打开RTC的闹钟1

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第7张图片【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第8张图片

2、开启闹钟的中断

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第9张图片

3、设置优先级分组:

【NUCLEO_F767ZI开发板系列】八、RTC实时时钟+闹钟_第10张图片

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实时时钟+闹钟_第11张图片


你可能感兴趣的:(STM32,Nucleo,RTC,F767,闹钟)