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

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

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:26
  实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。$ \/ K: N- R% U

2 }4 f9 b' J0 h5 H: }' V  RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。! q! ^" d' T) g* b$ L
, x5 N8 |6 X: P1 A2 n
  系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:& `! q. N, r3 k

5 u/ M# I8 \+ j( X设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
% w- `7 P6 \4 w3 B% v! |7 A设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。
, X$ ~- F$ t' e  下面直接通过代码来演示如何操作RTC。5 x0 D# {. F6 P' g' ?! Q3 [8 q7 \
# s- L: n/ _; a3 P  ?
  1. static void RTC_NVIC_Config( void )
    5 o7 r" H- ]: z' u8 S
  2. {; M% N& [7 ]% `3 J* N  p
  3.     NVIC_InitTypeDef NVIC_InitStructure;
    1 }9 _' M8 o9 I8 }) r& ~; e

  4. / y; U+ z) k2 S& z) d/ G
  5.     NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;  n+ t( O$ s/ H% R6 s( l0 ^5 n# H0 Z
  6.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    + U& P; d- c* c" K
  7.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;( D& J3 ~) t* L+ h$ T6 h
  8.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    5 u6 f. e4 F8 J" M  J
  9.     NVIC_Init( &NVIC_InitStructure );
    1 q6 B& _' g" P+ Z" q  d. \
  10. }5 v! O) u' E- u: S- j; v+ I

  11. * d: T; E6 X" Q' E0 z6 }9 n5 X
  12. //实时时钟配置
    9 U1 N$ \0 k% X% @5 a4 c
  13. //初始化RTC时钟,同时检测时钟是否工作正常2 x0 y! T* _) i8 G$ i6 S
  14. //BKP->DR1用于保存是否第一次配置的设置
    ) ~7 T1 `+ r" `$ B; ^
  15. //返回0:正常0 E! g8 D0 l# }1 b" b0 q
  16. //其他:错误代码5 b% j* q, V3 A6 B, \" t  W
  17. u8 RTC_Init( void )
    0 `8 {& m6 {0 H2 l; [
  18. {8 n) a% o( Q2 Q6 e$ Z
  19.     u8 temp = 0;
    ; _' ?/ Y; y7 s( u
  20.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );
    0 u! t% t6 p9 f5 y3 H
  21.     PWR_BackupAccessCmd( ENABLE );        //使能后备寄存器访问5 N, k1 ~$ V: B% h% ]+ c3 G: ~1 E. P

  22. 7 r5 Q5 E  H5 v8 d8 T& F
  23.     if( BKP_ReadBackupRegister( BKP_DR1 ) != 0x5055 )                //检查是不是第一次配置时钟
    ! m* Z+ Y, [  l
  24.     {
    0 L( I; p4 N) M& O9 ?+ `: i# X
  25.         BKP_DeInit();            //复位备份区域
    7 k5 A+ Y" f1 X( F) a5 W- X/ z
  26.         RCC_LSEConfig( RCC_LSE_ON );      //设置外部低速晶振(LSE),使用外设低速晶振
    4 s. m' u9 X! Q% @
  27.         //检查指定的RCC标志位设置与否,等待低速晶振就绪9 Z- X9 S* Y: |3 @
  28.         while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET && temp < 250 )2 f3 `+ p! w1 s. o5 s
  29.         {
    ) J1 G2 l6 s# t! Z  s- ^6 i( Q
  30.             temp++;
    5 z) r& x7 f! u3 v% t6 T0 n
  31.             delay_ms( 10 );% H5 H0 x1 @4 g0 f
  32.         }* p. `( `! H4 \$ s% D" B+ a
  33.         if( temp >= 250 )9 w- _$ i! ?* Y2 W, m/ A
  34.             return 1;          //初始化时钟失败,晶振有问题
    ( N) C+ Z2 J: p- U( |
  35.         RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );   //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
    2 `) k4 E% T( E1 O+ b
  36.         RCC_RTCCLKCmd( ENABLE );     //使能RTC时钟
    1 W/ E9 C5 g; {& h
  37.         RTC_WaitForLastTask();      //等待最近一次对RTC寄存器的写操作完成8 f+ W  H( r# \# @# H: S  \4 @
  38.         RTC_WaitForSynchro();       //等待RTC寄存器同步* K1 {' L# ?0 Y% P& W
  39.         RTC_ITConfig( RTC_IT_SEC, ENABLE );     //使能RTC秒中断
    : j) ?: c$ _  q4 ^. m
  40.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
    1 g; d' s' {1 |/ ]) E: n
  41.         RTC_EnterConfigMode();        // 允许配置
    3 ~  t* M* S4 d+ V2 Y
  42.         RTC_SetPrescaler( 32767 );    //设置RTC预分频的值( q9 D% b( z& ?) X: y4 @7 G# M
  43.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成  % v9 R7 c" ]; f3 ]1 @0 h9 p! B
  44.         RTC_ExitConfigMode();         //退出配置模式# W; `& m) \, o4 f9 Y. ?
  45.         BKP_WriteBackupRegister( BKP_DR1, 0x5055 ); //向指定的后备寄存器中写入用户程序数据
    1 q1 E) m) k! F* c/ \" `5 A4 `
  46.     }9 m2 L% F6 j" l" m0 ^
  47.     else            //系统继续计时
    5 Y7 j1 \* z* J; b. A- O/ L4 z
  48.     {
    # o+ e2 z. [! ~1 m' _$ w
  49.         RTC_WaitForSynchro();       //等待最近一次对RTC寄存器的写操作完成
    7 N+ `( U8 P/ R: a! J; {
  50.         RTC_ITConfig( RTC_IT_SEC | RTC_IT_ALR, ENABLE );        //使能RTC秒中断、闹钟中断
    # C) v/ z; Q- G! \7 a( J' T
  51.         RTC_WaitForLastTask();       //等待最近一次对RTC寄存器的写操作完成; r. E* L& j$ @* @
  52.     }
    ! @0 M6 h, h; \/ v5 W- e
  53.     RTC_NVIC_Config();         //RCT中断分组设置  
      t. p+ H& q5 M" _
  54.     return 0;                  //OK+ E  F/ a* @" `8 P
  55. }- U) o0 J" M( H

  56. 2 h& @" B+ @0 Z
  57. //RTC时钟中断
    3 G- J' Q' ~2 D1 A2 g. w+ M
  58. //每秒钟触发一次+ F- W9 [8 `- B8 @3 H3 \4 `' O* E) R
  59. void RTC_IRQHandler( void )
    * ^9 A6 y3 f5 U
  60. {
    & v7 Z' b. Z( Y/ G; f( U
  61.     if( RTC_GetITStatus( RTC_IT_SEC ) != RESET )                        //秒钟中断+ D0 _# H( n" X' K2 v! \5 S% n: m. z
  62.     {                                                                              
    : ]1 j- [6 A7 d/ z5 Y
  63.         printf( "RTC INT!\r\n" );
    % l5 h, g8 `7 S: C1 [: Y' ]
  64.     }( M0 g0 h' A4 V( c0 }" X5 M

  65. + l) x1 L) Z# `. L5 b  [: W
  66.     //RTC_ClearITPendingBit(RTC_IT_SEC | RTC_IT_OW);
      R7 K( j0 t) ?' j
  67.     RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_ALR );( d" q- m$ f6 V$ Y+ W3 @
  68.     RTC_WaitForLastTask();4 {0 {: A) s! H3 E( B% ^) Y* \! q
  69. }
复制代码
% f$ ?2 R; W! z9 M
  在设置RTC时首先要判断一下RTC是否已经初始化过了,因为一般使用RTC时都会有电池供电,RTC的时候只需要设置一次就行。当系统关机后,只要电池有电,RTC就能正常工作,所以不需要每次开机都初始化一次时间,当没有初始化时初始化一次,初始化之后,以后开机就不需要再初始化了。为了标记当前设备是否已经初始化了,手动的给备份寄存器中写入特定的值。每次单片机启动后就会读取一次备份寄存器的值,当备份寄存器中的值不是写入的特定值,就说明当前设备还没有被初始化过,需要初始化一次。如果备份寄存器中的值是写入的特殊值,就说明当前设备已经被初始化过了,不需要再初始化了。
+ [/ u5 a" Q$ v! X) s% Z
: A' E, @: ~" j% K' d$ h  在初始化的时候,开启RTC的秒中断,这样RTC每一秒就会中断一次,在中断函数中通过串口打印数据。当程序运行后在串口工具中就可以看到每隔1秒,就会打印一个字符串。; L+ W" {; N+ Z" e5 q- F

$ {5 B& L9 ~' r. |3 e5 Q
0 ~, |: t4 K7 P; T
9 }8 W. \  Q& X9 `( I: H
收藏 评论0 发布时间:2022-3-19 20:26

举报

0个回答

所属标签

相似分享

官网相关资源

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