【STM32】详解RTC实时时钟的概念和配置&示例代码

简介: 【STM32】详解RTC实时时钟的概念和配置&示例代码

一、什么是RTC

RTC(Real-time Clock):实时时钟,本质上是一个支持BCD编码的定时器/计数器。主电源断电后能够由电池供电,使其时钟跳转依然正常。


二、STM32F4芯片内的RTC功能

①日历时钟(时分秒、年月日、星期)

②两个闹钟——闹钟动作出发可支持中断

③定时唤醒功能(周期性唤醒)

④自动唤醒

⑤可以使用数字校准功能对晶振精度的偏差进行补偿。

⑥上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。


三、官方文档

1、RTC框图

LSE配置——RCC配置

异步通道分频器:1-128分频(RTC_PRER)

同步通道分频器:1-256分频(RTC_PRER)

日历寄存器:RTC_TR(时间寄存器),RTC_DR(日期寄存器)

RTC_SSR本质上是一个递减计数器:辅助更新日历

2、RTC初始化和配置(官方文档截取)

3、日历初始化配置


四、总结

1、RTC的寄存器属于后备区域——电池供电可继续工作,RTC内有20个后备寄存器

2、不是所有RTC寄存器都有写保护

默认无写保护的RTC寄存器:RTC_ISR[13:8]位、RTC_TAFCR、RTC_BKPxR(20个)。

其他RTC寄存器想要解除写保护需要:

①PWR使能

②开启后备区域访问权限

③通过向RTC_WPR写入指定密钥“0xCA”“0x53”

3、影子寄存器:SSR TR DR

RTC本身有这些寄存器,但是他们有写保护,所以每次想读取时间太麻烦,给这些RTC内的时间、日期、亚秒寄存器设置一个备份(在普通APB1外设),不用管写保护问题,直接访问即可。


五、RTC编程

1、读取RTC备份寄存器

RTC_ReadBackupRegister(RTC_BKP_DR0) == 0x32F2

2、开始第一次配置RTC

①使能PWR时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);//开启后备寄存器区域访问

使能RTC时钟

RCC_LSEConfig(RCC_LSE_ON);//开启外部低速晶振
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//等待LSE稳定就
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RCC中选择LSE作为RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能RTC时钟不管你是LSI 还是LSE
RTC_WaitForSynchro();//等待寄存器同步标志位置位

②RTC配置

同步和异步分频系数(RTC_PRER)和时制(12/24)

RTC_Init(&RTC_InitStructure);

③设置日期

RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);

④设置时间

RTC_RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);

⑤写入备份寄存器一个独特的标志值,用来区分是否是第一次初始化RTC

RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);


六、示例代码

void RTC_Config(void)
{
  RTC_InitTypeDef RTC_InitStructure;
  RTC_DateTypeDef RTC_DateStructure;
  RTC_TimeTypeDef RTC_TimeStructure;
  
  //读取备份区域的寄存器  看看是否是第一次初始化
  if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x1224)
  {
    //第一次初始化
    //1-使能PWR时钟 和RTC时钟配置
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    
    PWR_BackupAccessCmd(ENABLE);//PWR_CR---DBP
    
//    RCC_LSEConfig(RCC_LSE_ON);//开启LSE晶振
//    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==0);//等待LSE稳定就绪
//    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RCC中选择LSE作为RTC时钟
//    
    RCC_LSICmd(ENABLE);

     /* Wait till LSI is ready */  
     while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
     {
    }

    /* Select the RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

    
    RCC_RTCCLKCmd(ENABLE);//使能RTC时钟不管你是LSI 还是LSE
    
    RTC_WaitForSynchro();//等待寄存器同步标志位置位 ISR--RSF
    
    
    //2-初始化RTC
    RTC_InitStructure.RTC_AsynchPrediv = 128-1;//异步分频系数 0x00~0x7F
    RTC_InitStructure.RTC_SynchPrediv  = 256-1;//同步分频系数 0x00~0x7FFF
    RTC_InitStructure.RTC_HourFormat   = RTC_HourFormat_24;//24
    RTC_Init(&RTC_InitStructure);
    
    //3-设置日期
    RTC_DateStructure.RTC_Year  = 0x21;//21年
    RTC_DateStructure.RTC_Month = 0x09;//9月
    RTC_DateStructure.RTC_Date  = 0x14;//14号
    RTC_DateStructure.RTC_WeekDay = 0x02;//周二
    RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
    
    //4-时间设置  时分秒  16:06:00
    RTC_TimeStructure.RTC_Hours = 0x16;
    RTC_TimeStructure.RTC_Minutes = 0x06;
    RTC_TimeStructure.RTC_Seconds = 0x00;
    RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);   
    
    RTC_WriteBackupRegister(RTC_BKP_DR0,0x1224);
    
  }
  else
  {
    RCC_LSICmd(ENABLE);

     /* Wait till LSI is ready */  
     while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
     {
    }

    /* Select the RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
    
    if(RCC_GetFlagStatus(RCC_FLAG_PINRST) == 1)
    {
      PFout(10)= 1;//亮第二盏灯
      delay_s(1);
      //表示复位按键按下 复位
      PFout(10)= 0;//亮第二盏灯
    }
    
    //非第一次执行此初始化
    if(RCC_GetFlagStatus(RCC_FLAG_PORRST) == 1)
    {
      PFout(9)= 1;//亮第二盏灯
      delay_s(1);
      //表示上电复位
      PFout(9)=0;//亮第一盏灯
      RCC_ClearFlag();
      
    }
    //只要使能后备区域访问 和 等待影子寄存器同步
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    
    PWR_BackupAccessCmd(ENABLE);//PWR_CR---DBP
    
    RTC_WaitForSynchro();//等待寄存器同步标志位置位 ISR--RSF
  }
}
相关文章
|
2月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
398 0
|
2月前
|
前端开发 安全
stm32f407探索者开发板(十一)——SystemInit时钟系统初始化剖析
stm32f407探索者开发板(十一)——SystemInit时钟系统初始化剖析
|
2月前
stm32f407探索者开发板(十)——时钟系统精讲
stm32f407探索者开发板(十)——时钟系统精讲
|
3月前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
398 2
|
3月前
|
开发者
【经典案例】使用HAL库配置STM32F407的SPI外设
在嵌入式系统开发中,STM32F407是一款广泛应用的微控制器,而SPI(Serial Peripheral Interface)是一种常用的通信接口。本文将详细介绍如何使用STM32的硬件抽象层(HAL)库配置STM32F407的SPI外设,并提供完整的代码示例。
289 1
|
2月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
|
2月前
|
数据安全/隐私保护
STM32F103C8T6实现简易密码锁(CubeMax配置)(一),Oled显示。
项目功能:实现设置密码,登陆密码,后期还可以通过E2PROM实现掉电不丢失数据。通过Oled的显示去判断我们是否设置或者登陆成功。
|
3月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
235 2