STM32CubMX自学笔记(六)—RTC实时时钟实验

STM32CubMX自学笔记(六)—RTC实时时钟实验

主要介绍

RTC是STM32单片机的内置外设,配置RTC的时候不需要配置额外的引脚即可完成RTC的使用。由于RTC拥有掉电不丢失的功能,导致RTC的价值非常大,因此在这里介绍一下RTC的使用。只要添加一颗纽扣电池即可实时显示单片机的时间,即使是断点了也可以在下次上电的时候继续显示实时时间。可用性非常强。
RTC 模块和时钟配置是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时 间维持不变,只要后备区域供电正常,那么 RTC 将可以一直运行。但是在系统复位后,会自动 禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。
两个32位寄存器(TR 和 DR)包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或 24 小时制)、星期、日期、月份和年份。此外,还可提供二进制格式的亚秒值。

二、工程配置

下面介绍通过STM32cubmx软件来配置RTC实时时钟并且完成掉电不丢失的功能。

打开CubMx软件,首先配置系统时钟,主控制器采用的是探索者STM32F407,打开HSE时钟。如下图所示。
在这里插入图片描述紧接着进入时钟配置,这里最要注意的是我们的RTC时钟选择的时钟源是低速外部时钟(LSE)。查阅资料,选择其他时钟源可能会发生晶振不起振的问题,为了避免不必要的问题,我们选择的是LSE时钟源。
在这里插入图片描述

打开调试的DeBug。
在这里插入图片描述

开启一个GPIO引脚显示实验运行状态。
在这里插入图片描述最后,开启RTC功能。如下图所示。
在这里插入图片描述STM32F407系列有两个闹钟,分别是闹钟A和闹钟B,这里是不使能。下面看参数设置,hourformat显示的是24小时制,第二个和第三个参数是配置时钟源频率最终为1Hz。
具体配置的公式如下。STM32F4 的可编程预分配器 (RTC_PRER)分为 2 个部分:
1、一个通过 RTC_PRER 寄存器的 PREDIV_A 位配置的 7 位异步预分频器。
2、一个通过 RTC_PRER 寄存器的 PREDIV_S 位配置的 15 位同步预分频器。
ck_spre 的时钟可由如下计算公式计算:
Fck_spre = Frtcclk/[(PREDIV_S+1)( PREDIV_A+1)]
Fck_spre = 32.768kHz/(255+1)
(127+1) = 1Hz
经过计算,可以得到最后的频率是1Hz,也是就每秒计算一次时间。

在这里插入图片描述下面的参数分别对应的是日历时间和日历日期,格式采用的是BCD数据格式。配置完成之后即可生成工程文件。
打开mdk5文件。可以看到如下初始化的代码,系统自动完成了初始化的配置:

void MX_RTC_Init(void)
{
  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
  /* USER CODE BEGIN RTC_Init 1 */
  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  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;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN Check_RTC_BKUP */
	if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1) == 1)
		{
				return ;
		}
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x11;
  sTime.Minutes = 0x0;
  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_MONDAY;
  sDate.Month = RTC_MONTH_NOVEMBER;
  sDate.Date = 0x1;
  sDate.Year = 0x21;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
  /* USER CODE END RTC_Init 2 */

}

因为要用到串口打印,因此需要进行重定向。

int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口DEBUG_USART */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}

系统代码编写
首先,结构体是局部变量,因此,我们要在主函数中将其定义为全局变量,之后方可引用,并且还要完成RTC代码掉电不丢失功能,代码如下。在rtc.c中添加如下代码。

void user_CheckRtcBkup()
{
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1,1);
}

如下功能代码实现了每秒打印一次时间数据并且实现掉电不丢失。

	RTC_TimeTypeDef Time;
	RTC_DateTypeDef Date;
	user_CheckRtcBkup();
	while (1)
  {
		HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc,&Date,RTC_FORMAT_BIN);
		printf("%2d/%2d/%2d \r\n",Date.Year,Date.Month,Date.Date);
		printf("%2d-%2d-%2d \r\n",Time.Hours,Time.Minutes,Time.Seconds);
		HAL_Delay(1000);		
  }

代码验证

直接上图
在这里插入图片描述

结语

系统仅仅完成了RTC的最简单的功能测试,打印系统时间,掉电不丢失,后续还有待完善。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值