[STM32F1] 【分享】STM32F103单片机RTC实时时钟的使用

[复制链接]
2932|5
 楼主| xyz549040622 发表于 2023-11-13 22:56 | 显示全部楼层 |阅读模式

  实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。

  RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。

  系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:

      设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
      设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。
  下面直接通过代码来演示如何操作RTC。

  1. static void RTC_NVIC_Config( void )
  2. {
  3.     NVIC_InitTypeDef NVIC_InitStructure;

  4.     NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  5.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  6.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  7.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  8.     NVIC_Init( &NVIC_InitStructure );
  9. }

  10. //实时时钟配置
  11. //初始化RTC时钟,同时检测时钟是否工作正常
  12. //BKP->DR1用于保存是否第一次配置的设置
  13. //返回0:正常
  14. //其他:错误代码
  15. u8 RTC_Init( void )
  16. {
  17.     u8 temp = 0;
  18.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );
  19.     PWR_BackupAccessCmd( ENABLE );        //使能后备寄存器访问

  20.     if( BKP_ReadBackupRegister( BKP_DR1 ) != 0x5055 )                //检查是不是第一次配置时钟
  21.     {
  22.         BKP_DeInit();            //复位备份区域
  23.         RCC_LSEConfig( RCC_LSE_ON );      //设置外部低速晶振(LSE),使用外设低速晶振
  24.         //检查指定的RCC标志位设置与否,等待低速晶振就绪
  25.         while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET && temp < 250 )
  26.         {
  27.             temp++;
  28.             delay_ms( 10 );
  29.         }
  30.         if( temp >= 250 )
  31.             return 1;          //初始化时钟失败,晶振有问题
  32.         RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );   //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
  33.         RCC_RTCCLKCmd( ENABLE );     //使能RTC时钟
  34.         RTC_WaitForLastTask();      //等待最近一次对RTC寄存器的写操作完成
  35.         RTC_WaitForSynchro();       //等待RTC寄存器同步
  36.         RTC_ITConfig( RTC_IT_SEC, ENABLE );     //使能RTC秒中断
  37.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  38.         RTC_EnterConfigMode();        // 允许配置
  39.         RTC_SetPrescaler( 32767 );    //设置RTC预分频的值
  40.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成  
  41.         RTC_ExitConfigMode();         //退出配置模式
  42.         BKP_WriteBackupRegister( BKP_DR1, 0x5055 ); //向指定的后备寄存器中写入用户程序数据
  43.     }
  44.     else            //系统继续计时
  45.     {
  46.         RTC_WaitForSynchro();       //等待最近一次对RTC寄存器的写操作完成
  47.         RTC_ITConfig( RTC_IT_SEC | RTC_IT_ALR, ENABLE );        //使能RTC秒中断、闹钟中断
  48.         RTC_WaitForLastTask();       //等待最近一次对RTC寄存器的写操作完成
  49.     }
  50.     RTC_NVIC_Config();         //RCT中断分组设置  
  51.     return 0;                  //OK
  52. }

  53. //RTC时钟中断
  54. //每秒钟触发一次
  55. void RTC_IRQHandler( void )
  56. {
  57.     if( RTC_GetITStatus( RTC_IT_SEC ) != RESET )                        //秒钟中断
  58.     {                                                                              
  59.         printf( "RTC INT!\r\n" );
  60.     }

  61.     //RTC_ClearITPendingBit(RTC_IT_SEC | RTC_IT_OW);
  62.     RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_ALR );
  63.     RTC_WaitForLastTask();
  64. }
  在设置RTC时首先要判断一下RTC是否已经初始化过了,因为一般使用RTC时都会有电池供电,RTC的时候只需要设置一次就行。当系统关机后,只要电池有电,RTC就能正常工作,所以不需要每次开机都初始化一次时间,当没有初始化时初始化一次,初始化之后,以后开机就不需要再初始化了。为了标记当前设备是否已经初始化了,手动的给备份寄存器中写入特定的值。每次单片机启动后就会读取一次备份寄存器的值,当备份寄存器中的值不是写入的特定值,就说明当前设备还没有被初始化过,需要初始化一次。如果备份寄存器中的值是写入的特殊值,就说明当前设备已经被初始化过了,不需要再初始化了。

  在初始化的时候,开启RTC的秒中断,这样RTC每一秒就会中断一次,在中断函数中通过串口打印数据。当程序运行后在串口工具中就可以看到每隔1秒,就会打印一个字符串。


国产芯片代理 发表于 2023-11-24 11:37 | 显示全部楼层
小夏天的大西瓜 发表于 2023-11-29 22:57 | 显示全部楼层
RTC每一秒就会中断一次,在中断函数中通过串口打印数据
jf101 发表于 2023-11-30 09:31 | 显示全部楼层
RTC占用MCU资源多嘛?
Undshing 发表于 2023-11-30 16:42 来自手机 | 显示全部楼层
rtc中断可以做什么用啊
dog_xin 发表于 2023-12-14 19:32 | 显示全部楼层
电池下停走,是啥回事?有的线路板工作正常,有的不行,估计啥原因?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群: 嵌入式系统arm初学者 224636155←← +→→点击-->小 i 精品课全集,21ic公开课~~←←→→点击-->小 i 精品课全集,给你全方位的技能策划~~←←

2841

主题

19330

帖子

110

粉丝
快速回复 在线客服 返回列表 返回顶部