STM32CubeIDE开发(十一), STM32实时时钟(RTC)写入及读取日历时间开发要点

这篇具有很好参考价值的文章主要介绍了STM32CubeIDE开发(十一), STM32实时时钟(RTC)写入及读取日历时间开发要点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、RTC简介

二、工程创建及配置

 三、驱动代码设计实现

四、编译及测试


一、RTC简介

        实时时钟的缩写是RTC(Real_Time Clock),核心是晶振,晶振频率一般为32768 Hz 。它为分频计数器提供精确的与低功耗的实基信号。它可以用于产生秒、分、时、日等信息。为了确保时钟长期的准确性,晶振必须正常工作,不能够受到干扰。RTC的晶振又分为:外部晶振和内置晶振。

        RTC时间信息存储在后备寄存器(RTC_BKUP)中,在STM32中,通常采用一个32位计数器来计时,而不是用年月日时分秒的分组寄存器,因此在处理STM32的时间信息时(设置或读取),通常要求先处理时分秒时间,再处理年月日时间,以确保时间和日期值之间的一致性。

        RTC和后备寄存器一般不会被系统或电源复原源复位,当从待机模式唤醒时,也不会复位,但是要注意的是,停止供电会出现重置,数值恢复到初始设置,因此如果要保持长期有效,尤其是断电重启依然有效,需要配置独立供电电源。

        RTC时间是以振荡频率来计算的。故它本质上是一个计数器,只是通过换算呈现出日历时间信息。而一般的计数器都是16位的。又因为时间的准确性很重要,故震荡次数越低,时间的准确性越低。所以必定是个高次数。2^15 = 32768 ,而 32768 Hz = 2^15 即分频15次后为1Hz,周期 = 1s,因此RTC的时间基准是1秒。16位计数器最大值0XFFFFFFFF,按秒计算,能支持136年时长计算。

二、工程创建及配置

        本文采用STM32L496VGTx-ali开发板来实现,该开发板是没有给RTC独立供电的,因此断电后会出现时间重置,但功能模拟演示还是OK的。本文假设已经移植了前面工程,并实现了lpuart1串口通信与电脑端的调试输出以及按键、LED灯驱动,这部分的实现请参考本专栏博客:

cubeIDE快速开发流程_py_free的博客-CSDN博客_ide开发流程

cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客_stm32串口显示

        假设已经实现了lpuart1串口通信及按键、LED灯功能,现在双击.ioc打开cubeMX配置界面,开启RTC功能。数据格式支持二进制格式和BCD格式,在HAL中采用RTC_FORMAT_BIN(0x00000000u)和RTC_FORMAT_BCD(0x00000001u)标识。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

         BCD(Binary Coded Decimal),即二-十进制编码,是用四位二进制码的 10 种组合表示十进制数0-9。这种编码至少需要用四位二进制码元,而四位二进制码元可以有16种组合。当用这些组合表示十进制数0-9时,有六种组合不用。

        RTC功能开启后,时钟树视图可以关于RTC的选择器可以选择外部高速时钟、外部低速时钟、内部低速时钟,本文选择外部低速时钟(LSE)。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

         完成配置保存输出按钮(本文是为每个外设生成独立.h/.c源码),在生成的rtc.c文件中可以看到RTC初始化函数关于年月日、时分秒的设值和cubeMX上配置信息一致。

        备注:如果在cubeMX配置界面没有选择数据格式,年日、时分秒默认是0X前缀的。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

 三、驱动代码设计实现

        【1】在Core/Src/rtc.c文件中,调整RTC初始化函数,在RTC设置初始化时间、日期之前,加入后备寄存器的读取,判定是否已经进行过初始化,避免重复设置时间、日期而改写本该持续计数的RTC计数。

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 */
    //新增
  __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟PWR
   HAL_PWR_EnableBkUpAccess();//取消备份区域写保护
  /* 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.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  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)!=0X8888)//判断是否首次上电
  {
	  HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1,0X8888); //标记数值(写入上电检查数值)
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 12;
  sTime.Minutes = 30;
  sTime.Seconds = 30;
  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_DECEMBER;
  sDate.Date = 20;
  sDate.Year = 22;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
    //新增
//  printf("手动初始化测试!\r\n");//显示初始化信息
  }
  /* USER CODE END RTC_Init 2 */

}

        在main.c文件中,加入按键、LED灯、串口外设驱动头文件,

/* USER CODE BEGIN Includes */
#include "../../ICore/key/key.h"
#include "../../ICore/led/led.h"
#include "../../ICore/print/print.h"
#include "../../ICore/usart/usart.h"
/* USER CODE END Includes */

        在main函数中声明RTC日期、时间读取缓存变量。

  /* USER CODE BEGIN 1 */
  RTC_DateTypeDef RtcDate;
  RTC_TimeTypeDef RtcTime;
  uint8_t time_set = 0;//用户设置时间标记
  /* USER CODE END 1 */

        在main函数中开启串口lpuart1的中断接收。

  /* USER CODE BEGIN 2 */
  ResetPrintInit(&hlpuart1);
  HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
  HLPUSART_RX_STA = 0;
  printf("APP reset now!\r\n");
  /* USER CODE END 2 */

        在main函数循环体中,实现按键KEY1获取RTC时间以及按键KEY2设置RCT时间,注意RTC设置时间、日期和RTC读取时间、日期时,数据格式保持一致,最好和CubeMX设置时一致,例如读取、写入RTC时间日期都采用RTC_FORMAT_BCD格式。

 /* USER CODE BEGIN WHILE */
  while (1)
  {
	  if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
  		  printf("lpuart1:%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  		  if(time_set){
  			  //将超级终端发过来的数据换算并写入RTC,读取数据为字符内容需要转换为数值
  	          RtcDate.Year =  (HLPUSART_RX_BUF[2]-0x30)*10+HLPUSART_RX_BUF[3]-0x30;//减0x30后才能得到十进制0~9的数据
	          RtcDate.Month =  (HLPUSART_RX_BUF[4]-0x30)*10+HLPUSART_RX_BUF[5]-0x30;
	          RtcDate.Date =  (HLPUSART_RX_BUF[6]-0x30)*10+HLPUSART_RX_BUF[7]-0x30;
	          RtcTime.Hours =  (HLPUSART_RX_BUF[8]-0x30)*10+HLPUSART_RX_BUF[9]-0x30;
	          RtcTime.Minutes =  (HLPUSART_RX_BUF[10]-0x30)*10+HLPUSART_RX_BUF[11]-0x30;
	          RtcTime.Seconds =  (HLPUSART_RX_BUF[12]-0x30)*10+HLPUSART_RX_BUF[13]-0x30;
	          //写入格式RTC_FORMAT_BCD或RTC_FORMAT_BIN,确保写入及读取数据格式一致即可
  	          if (HAL_RTC_SetTime(&hrtc,  &RtcTime, RTC_FORMAT_BCD) != HAL_OK)//将数据写入RTC程序
  	          {
  	              printf("写入时间失败!\r\n"); //显示写入失败
  	          }else if (HAL_RTC_SetDate(&hrtc,  &RtcDate, RTC_FORMAT_BCD) != HAL_OK)//将数据写入RTC程序
  	          {
  	              printf("写入日期失败!\r\n"); //显示写入失败
  	          }else printf("写入成功!\r\n");//显示写入成功
  	          time_set=0;
	  	  }
  		  HLPUSART_RX_STA=0;//接收错误,重新开始
  		  HAL_Delay(100);//等待
  	  }
  	  if(KEY_1())
	  {
  		  HAL_RTC_GetTime(&hrtc, &RtcTime,  RTC_FORMAT_BCD);//读出时间值
          HAL_RTC_GetDate(&hrtc, &RtcDate,  RTC_FORMAT_BCD);//一定要先读时间后读日期
          printf(" RTC实时时钟测试\r\n");
          printf(" 实时时间:%04d-%02d-%02d  %02d:%02d:%02d  \r\n",2000+RtcDate.Year,
       		   RtcDate.Month, RtcDate.Date,RtcTime.Hours, RtcTime.Minutes, RtcTime.Seconds);//显示日期时间
	  }
  	  if(KEY_2())
	  {
  		  printf(" 请输入设置时间,格式20221220183030,按回车键确定! \r\n");
  		  time_set=1;
	  }
    /* USER CODE END WHILE */

         注意和前面简介说过,确保时间和日期值之间的一致性,先处理时间(时分秒),在处理日期(年月日),在stm32l4xx_hal_rtc.c的HAL_RTC_GetTime函数注释中也有明确要求如下,“您必须在HAL_RTC_GetTime()之后调用HAL_RTC_GetDate()来解锁值以确保时间和日期值之间的一致性。读取RTC当前时间锁定日历阴影寄存器中的值,直到读取当前日期以确保时间和日期值之间的一致性。”:

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

四、编译及测试

        和本专栏其他博文一样,设置好工程输出目标格式支持,配置好运行调试支持后,点击编译工程及运行按钮,完成工程编辑及下载。       

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

        打开串口助手工具,连接到开发板,测试

        【1】按键KEY1,读取RTC时间,读取出的时间就去前面在cubeMX 设置的时间,并开始计数,因此分秒有差异。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

         【2】按键KEY2设置时间,并按格式输入时间,然后在按键KEY1读取新的RTC时间,如下图所示,设置时间生效。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

         【3】按开发板上的Reset按键,系统复位,再按键KEY2读取RTC时间,时间依然正常计数

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX

         【4】断电一会,然后重新上电,再按键KEY2读取RTC时间,时间恢复到CubeMX设置的初始时间(即为断电后,原来写入的标识无法保持,HAL_RTCEx_BKUPRead读取标记失败重新初始化)。

基于stm32cube库设计的显示屏日历,STM32CubeIDE开发实践案例,stm32,RTC,实时时钟,stm32cubeIDE,stm32cubeMX文章来源地址https://www.toymoban.com/news/detail-792706.html

到了这里,关于STM32CubeIDE开发(十一), STM32实时时钟(RTC)写入及读取日历时间开发要点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32-RTC实时时钟

    目录 RTC实时时钟 功能框图 UNIX时间戳 初始化结构体 RTC时间结构体 RTC日期结构体 RTC闹钟结构体 进入和退出配置函数 实验环节1:显示日历 常规配置 RTC配置 测试环节 实验现象 实验环节2:闹钟 常规配置 RTC配置 测试环节 实验现象 STM32的RTC外设,实质上是一个 掉电后还继续运

    2024年02月06日
    浏览(41)
  • STM32-RTC实时时钟详解

    RTC的本质很简单,就是一个时钟经过精确分频最后得到的一个1Hz的时钟,也可以说是计数器,其他大部分功能都是基于这个计数器设计的数字逻辑。 本文讲的RTC是基于STM32F030来讲的,相比与F1系列的RTC来说,M0的将很多原本需要软件实现的功能硬件化了,使用起来更加便利。

    2024年02月04日
    浏览(39)
  • STM32-实时时钟RTC-2

                                     

    2024年01月20日
    浏览(38)
  • 【STM32学习】实时时钟 —— RTC

    STM32RTC实时时钟实验讲解,从入门到放弃 【STM32】RTC休眠唤醒(停机模式)、独立看门狗开启状态下 关于STM32使用RTC唤醒停止模式的设置 RTC(Real Time Clock):实时时钟,是指可以像时钟一样输出实际时间的电子设备,一般会是集成电路,因此也称为时钟芯片。总之,RTC只是个能靠电

    2024年02月01日
    浏览(41)
  • STM32基础10--实时时钟(RTC)

     目录 前言 RTC框图 STM32实时时钟电路 功能需要 STM32CubeMx配置RTC 配置RCC 配置RTC 配置时间,闹钟,唤醒 开启中断 设置中断优先级 功能代码实现 STM32Cude生成RTC初始化 自定义触发闹钟次数变量  重写周期唤醒回调函数 重写闹钟中断函数         在做51单片机项目时,如果需

    2023年04月11日
    浏览(29)
  • 【正点原子STM32】RTC实时时钟(RTC方案、BCD码、时间戳、RTC相关寄存器和HAL库驱动、RTC基本配置步骤、RTC基本驱动步骤、时间设置和读取、RTC闹钟配置和RTC周期性自动唤醒配置)

    一、RTC简介 二、STM32 RTC框图介绍 2.1、STM32 F1 RTC结构框图 2.2、STM32 F4 / F7 / H7 RTC结构框图 三、RTC相关寄存器介绍 3.1、RTC基本配置步骤 3.2、RTC相关寄存器(F1) 3.3、RTC相关寄存器(F4 / F7 / H7) 四、RTC相关HAL库驱动介绍 4.1、RTC相关HAL库驱动(F1) 4.2、RTC相关HAL库驱动(F4 / F7 /

    2024年03月27日
    浏览(61)
  • STM32学习笔记(十二)丨RTC实时时钟

    ​  本次课程采用单片机型号为STM32F103C8T6。 ​  课程链接:江协科技 STM32入门教程   往期笔记链接:   STM32学习笔记(一)丨建立工程丨GPIO 通用输入输出   STM32学习笔记(二)丨STM32程序调试丨OLED的使用   STM32学习笔记(三)丨中断系统丨EXTI外部中断   

    2024年02月16日
    浏览(41)
  • STM32中的RTC实时时钟和配套闹钟设置

    主要初始化函数,以及设置闹钟函数,闹钟中断函数 RTC.c RTC.h main.c

    2024年04月23日
    浏览(36)
  • stm32-OLED屏+RTC实现简易实时时钟(上篇)

    oled屏选择ssd1306,使用RTC实现简易实时时钟 1、MCU接口选择 SSD1306单片机接口由8个数据引脚和5个控制引脚组成。通过BS[2:0]引脚上的硬件选择可以设置不同的MCU模式    通过控制BS[2:0]引脚可以设置MCU与OLED屏的通信方式。因为我使用的是正点原子的开发板,所以我用了适配的接

    2024年01月17日
    浏览(39)
  • stm32-OLED屏+RTC实现简易实时时钟(下篇)

    一、RTC简介 实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可 提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒 后,R

    2024年01月18日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包