你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F103单片机RTC实时时钟的使用

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:26
  实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
) ?2 w$ ]9 m1 {6 ?
9 j. U% S; S" K" ^5 h  RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。
" a& l0 v, q* S# H+ F) o! P% }. q! C) T  ~, m( V! G1 ^
  系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:2 [' y0 \" t# }5 I

( a, X6 Q2 Y& b5 _设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟* C' _2 K. i7 L6 w2 F
设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。8 s; J  h* _' K5 b& O7 q# e0 {# M, b  d
  下面直接通过代码来演示如何操作RTC。
6 J# t$ b4 ]. k+ Y
- m* e% f1 h7 K; Q1 c. r1 h
  1. static void RTC_NVIC_Config( void )
    0 l4 J. j7 [& ^! j
  2. {* ?+ w3 g, Y8 F. I4 D
  3.     NVIC_InitTypeDef NVIC_InitStructure;
    4 \( i% B: u5 J8 i" |

  4. . O: X, E- B! }8 z1 l
  5.     NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;. E% _3 h8 |; ]
  6.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;8 v& T- @" {/ A7 e. H
  7.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    ! ~/ z  J) L& ~& Z8 k
  8.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;2 O( L, T+ u, W' H
  9.     NVIC_Init( &NVIC_InitStructure );
    ) _+ {0 O! x' L8 y- ]9 v- \' _
  10. }4 e7 C  ^8 w6 q* N8 R0 D! ~1 K( I

  11. 2 b5 }5 q7 w8 `( t7 K
  12. //实时时钟配置
      l4 U; W1 U  z% P. T, J
  13. //初始化RTC时钟,同时检测时钟是否工作正常1 ?4 Y6 n8 S1 u
  14. //BKP->DR1用于保存是否第一次配置的设置
    5 g/ A# O1 i1 o  T8 y+ i
  15. //返回0:正常
    ! B- q; f- E0 i9 G# S# n# a
  16. //其他:错误代码
    ) L9 @8 l, i6 e1 S
  17. u8 RTC_Init( void )
    0 G. p! ?: o2 a. X  g! Q& d. E
  18. {  x- g. o/ {* g" g
  19.     u8 temp = 0;
    0 c$ r8 o# i' W6 V# R, ~: r! O
  20.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );: K9 S0 Z! ~+ z2 Y$ W& W, a9 Q9 {/ D
  21.     PWR_BackupAccessCmd( ENABLE );        //使能后备寄存器访问$ m& I2 p$ a( i
  22. . E  R& C5 Q1 h! n
  23.     if( BKP_ReadBackupRegister( BKP_DR1 ) != 0x5055 )                //检查是不是第一次配置时钟& G' O$ }; g1 t  J6 i/ U5 ]
  24.     {& R! e5 C& `. V
  25.         BKP_DeInit();            //复位备份区域
    * B# p# F  Z) O- M& f# Z
  26.         RCC_LSEConfig( RCC_LSE_ON );      //设置外部低速晶振(LSE),使用外设低速晶振: g: N3 t4 d. j. l
  27.         //检查指定的RCC标志位设置与否,等待低速晶振就绪
    % T, L2 n% U1 }
  28.         while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET && temp < 250 )
    ! x7 W( h/ [4 U4 T! N5 j0 E
  29.         {
    2 l7 K2 O7 U# P. }* Q, A3 c2 ^! y
  30.             temp++;  e+ E, i2 H" T: w  {" M4 Z- L( l2 }
  31.             delay_ms( 10 );
    + x/ B/ Q. ]- f) D( L% t
  32.         }/ m3 `! N+ |. d2 M, d" k
  33.         if( temp >= 250 )
      r& h1 h5 I4 _+ c# I' a
  34.             return 1;          //初始化时钟失败,晶振有问题
    " x4 {; L! U7 O
  35.         RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );   //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟( o& |' I0 \8 x6 W
  36.         RCC_RTCCLKCmd( ENABLE );     //使能RTC时钟1 A7 o0 G" }2 R9 d. O7 z/ E
  37.         RTC_WaitForLastTask();      //等待最近一次对RTC寄存器的写操作完成
    0 J* i* f" t7 `, w) B
  38.         RTC_WaitForSynchro();       //等待RTC寄存器同步
    / S6 e6 t- I9 I
  39.         RTC_ITConfig( RTC_IT_SEC, ENABLE );     //使能RTC秒中断
    * R$ ?8 |, |- I
  40.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
    ! z' q0 c3 ^, c& D. ^% o
  41.         RTC_EnterConfigMode();        // 允许配置
    ; q  Q) n1 n! Z# F1 w$ ]
  42.         RTC_SetPrescaler( 32767 );    //设置RTC预分频的值: I0 w) Y( }1 `
  43.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成  
      Q* C" T* b8 a
  44.         RTC_ExitConfigMode();         //退出配置模式9 J! [9 x! @$ d$ K( N
  45.         BKP_WriteBackupRegister( BKP_DR1, 0x5055 ); //向指定的后备寄存器中写入用户程序数据. {( c2 o) L. S5 v' A
  46.     }
    $ v3 _7 n) ?6 x" g9 \
  47.     else            //系统继续计时4 i- k2 H4 @1 Q; [' K8 V
  48.     {
    1 V0 _: _) X" D+ S- b( L
  49.         RTC_WaitForSynchro();       //等待最近一次对RTC寄存器的写操作完成
    ) e6 R4 U" k' a$ X$ W2 _# u; x7 }% B
  50.         RTC_ITConfig( RTC_IT_SEC | RTC_IT_ALR, ENABLE );        //使能RTC秒中断、闹钟中断9 A. U" a% J0 O) R
  51.         RTC_WaitForLastTask();       //等待最近一次对RTC寄存器的写操作完成
    7 `% ~' m) I+ Y: f( D  \
  52.     }$ y! u9 x* u9 `" p  W- K
  53.     RTC_NVIC_Config();         //RCT中断分组设置  
    7 i8 f" [: _- {; s) P
  54.     return 0;                  //OK, y( T2 ^% B3 U) F
  55. }
    $ Y7 \" W9 o7 I% @" ^  c6 Q

  56. 1 y6 r& _3 ~( [7 S' Q1 W* h$ n: n# e  g
  57. //RTC时钟中断# w3 T5 v/ ]' R8 d- g
  58. //每秒钟触发一次! x4 r% n$ g/ h9 z# `
  59. void RTC_IRQHandler( void )
    5 c5 u2 C5 \1 H$ U- i
  60. {
      x7 T/ r; a( v) O0 U
  61.     if( RTC_GetITStatus( RTC_IT_SEC ) != RESET )                        //秒钟中断
    ) ^$ K9 y6 F) F
  62.     {                                                                              5 G1 x+ q8 i8 {+ S/ p
  63.         printf( "RTC INT!\r\n" ); 2 B' N2 u: z) \+ S6 x/ {/ K
  64.     }. J4 H$ C3 @1 G' V3 \

  65. ' n  i+ r2 M. S, _
  66.     //RTC_ClearITPendingBit(RTC_IT_SEC | RTC_IT_OW);( s, u" Z/ x: v0 P
  67.     RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_ALR );
    + U3 \: m9 c: M! g# s
  68.     RTC_WaitForLastTask();, o3 T# h& `6 @
  69. }
复制代码
, M! n, \' O# {# E0 _) K. G
  在设置RTC时首先要判断一下RTC是否已经初始化过了,因为一般使用RTC时都会有电池供电,RTC的时候只需要设置一次就行。当系统关机后,只要电池有电,RTC就能正常工作,所以不需要每次开机都初始化一次时间,当没有初始化时初始化一次,初始化之后,以后开机就不需要再初始化了。为了标记当前设备是否已经初始化了,手动的给备份寄存器中写入特定的值。每次单片机启动后就会读取一次备份寄存器的值,当备份寄存器中的值不是写入的特定值,就说明当前设备还没有被初始化过,需要初始化一次。如果备份寄存器中的值是写入的特殊值,就说明当前设备已经被初始化过了,不需要再初始化了。- f, M( I; F( [# Q4 @

, l( |, [# C5 T! g; p' {! K  在初始化的时候,开启RTC的秒中断,这样RTC每一秒就会中断一次,在中断函数中通过串口打印数据。当程序运行后在串口工具中就可以看到每隔1秒,就会打印一个字符串。
4 e4 q/ ]: k7 E" k# J2 F) B8 D7 e9 A% M3 z$ r/ I6 X8 w- A

7 j- J9 K+ P5 Y+ h9 s
$ e) r+ c# @  J( q! n  n0 K, r( A7 a& F
收藏 评论0 发布时间:2022-3-19 20:26

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版