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

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

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:26
  实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
: W' f4 \1 g# b
& o+ q2 g; |9 ^' M  RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。$ V; D$ ]8 m2 C* K8 q6 ~( D
' {- i5 s: a+ z$ m; m7 O3 G
  系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:
' ?* v9 K# w- k  i$ H% d2 u, {5 C! g  v' B8 v0 t, e; l6 M' f
设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
3 T4 U4 k! Q$ H6 T" Y4 {2 p9 g设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。+ P  S3 F3 W( H# F* E; v  c
  下面直接通过代码来演示如何操作RTC。
+ N  V% t6 z; O3 F# Y
% n9 H; w) C: l
  1. static void RTC_NVIC_Config( void )
    ) [+ J( n% H7 [1 {' Y
  2. {* g1 W$ z! Z9 ~6 H+ {% a( r
  3.     NVIC_InitTypeDef NVIC_InitStructure;' i, I3 @$ |+ {* [

  4. % f6 g3 B- |3 t+ e
  5.     NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;6 V  ]8 e, N; U, E. G+ W
  6.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;. y; }, Z; k& R2 w% S! M5 `
  7.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;4 T+ Q1 L$ a0 H& [$ B4 v
  8.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    ' P7 x# ]3 ?! B: Q- X& t- Q0 G1 O* ?7 G
  9.     NVIC_Init( &NVIC_InitStructure );
    ! e" ], z' a1 h7 {  d
  10. }& X& Q8 }4 \( _* ?; X6 _- S
  11. " W* x# x* P) O& D
  12. //实时时钟配置2 b1 j$ D  O3 r6 b. t( ^
  13. //初始化RTC时钟,同时检测时钟是否工作正常
    # y: x! i) \9 w! W5 k! R
  14. //BKP->DR1用于保存是否第一次配置的设置) }" n* y. \# z" i5 }
  15. //返回0:正常
    ; S; o  D' ^- c3 e: Z) ~
  16. //其他:错误代码0 t1 z& W/ P" ]9 {  T+ _, @
  17. u8 RTC_Init( void )
    " x" A+ R9 b* m+ T- n3 V
  18. {
    # c; W" b; E0 K6 X
  19.     u8 temp = 0;3 g& A# @- |) m( ^
  20.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );
    2 f  D1 m4 @) F- _6 j, [( I# A
  21.     PWR_BackupAccessCmd( ENABLE );        //使能后备寄存器访问. u9 h8 x5 l6 u8 [% x
  22. 2 ]4 K; D3 s9 u1 `) {
  23.     if( BKP_ReadBackupRegister( BKP_DR1 ) != 0x5055 )                //检查是不是第一次配置时钟
    % P2 H7 Q4 T8 J5 Y
  24.     {
    . b6 Q( q" \- J8 h
  25.         BKP_DeInit();            //复位备份区域
    , F! [% h1 O% J$ W
  26.         RCC_LSEConfig( RCC_LSE_ON );      //设置外部低速晶振(LSE),使用外设低速晶振
    ' X; a5 N% O' K" L4 O* G$ m* X
  27.         //检查指定的RCC标志位设置与否,等待低速晶振就绪, y3 h! V& |6 R8 l4 ~$ L
  28.         while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET && temp < 250 )& ?1 A8 m. t& ?" @
  29.         {5 D2 O" C  G* u, h: @2 b" {
  30.             temp++;/ p2 z2 ~/ @5 A8 |# L3 N
  31.             delay_ms( 10 );
    4 x# u) X$ Y8 ]( D
  32.         }" S' h& K7 h. s7 B6 V
  33.         if( temp >= 250 )
    7 |* P" E) v: J7 B7 {% o- Z
  34.             return 1;          //初始化时钟失败,晶振有问题2 r, C( e+ ^: ^$ p
  35.         RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );   //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟: D0 p" x9 i% @" z$ z
  36.         RCC_RTCCLKCmd( ENABLE );     //使能RTC时钟; v4 w8 s, q5 d7 }; ?" o5 C- q% P% k
  37.         RTC_WaitForLastTask();      //等待最近一次对RTC寄存器的写操作完成- j2 y: G5 i' ~! V
  38.         RTC_WaitForSynchro();       //等待RTC寄存器同步) C* j9 m7 H) S
  39.         RTC_ITConfig( RTC_IT_SEC, ENABLE );     //使能RTC秒中断
    . c" o" v6 p& W' i  P
  40.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成2 l* |+ V* [/ }2 t7 b4 B/ Z
  41.         RTC_EnterConfigMode();        // 允许配置
    ! G! M( B6 I; J- ~; [; ]* `: W
  42.         RTC_SetPrescaler( 32767 );    //设置RTC预分频的值: [$ d5 R+ o, u
  43.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成  9 w& n8 n5 F' j- w8 e9 {. W
  44.         RTC_ExitConfigMode();         //退出配置模式' I. @0 U8 }' H. A5 h0 N
  45.         BKP_WriteBackupRegister( BKP_DR1, 0x5055 ); //向指定的后备寄存器中写入用户程序数据
    ) `5 T! H2 l9 a- ]0 f
  46.     }+ ?+ z  {4 J; W% |' H
  47.     else            //系统继续计时0 s' s' A& @/ d! x, X- @) |& Q
  48.     {
    + r7 y* o! n2 S% e' _
  49.         RTC_WaitForSynchro();       //等待最近一次对RTC寄存器的写操作完成
    7 x9 s- [6 R: }3 n1 A
  50.         RTC_ITConfig( RTC_IT_SEC | RTC_IT_ALR, ENABLE );        //使能RTC秒中断、闹钟中断
    " W7 O* k, O+ H2 b" z) k  g
  51.         RTC_WaitForLastTask();       //等待最近一次对RTC寄存器的写操作完成! c4 A. A9 R$ I8 d# M- z6 I
  52.     }
    9 Q5 ]* [' O; I* v+ G; u
  53.     RTC_NVIC_Config();         //RCT中断分组设置  % N8 |3 S4 T7 ~3 u
  54.     return 0;                  //OK
    ! C3 x+ j* N/ ~
  55. }
    ) |8 S' ^' c% z/ Z# u# E' r
  56. . D* E: _+ @# t, Z/ V( A
  57. //RTC时钟中断5 g- E7 ?  L: K
  58. //每秒钟触发一次
      |; @. H6 b" F
  59. void RTC_IRQHandler( void )
    7 c5 b* _  H: H2 _  W) S
  60. {
    3 G' Z' y: C5 A
  61.     if( RTC_GetITStatus( RTC_IT_SEC ) != RESET )                        //秒钟中断  T3 L; o( g5 i7 G8 |' ^
  62.     {                                                                              5 H! i1 z& O7 Q, H' F( ]5 {
  63.         printf( "RTC INT!\r\n" ); " p+ J$ Q5 C# j/ C" [0 L4 o3 {4 y
  64.     }9 K, C; ~  t+ q! o; S; d; |

  65. 3 t4 H# k" v- ~/ s% E3 C5 `4 C: ]
  66.     //RTC_ClearITPendingBit(RTC_IT_SEC | RTC_IT_OW);- N! n' E6 q9 e5 v
  67.     RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_ALR );9 b- s2 {7 z- n: P+ S
  68.     RTC_WaitForLastTask();
    ! Q) h/ U9 y6 K& @
  69. }
复制代码

  ], w' ~# }9 z1 a  在设置RTC时首先要判断一下RTC是否已经初始化过了,因为一般使用RTC时都会有电池供电,RTC的时候只需要设置一次就行。当系统关机后,只要电池有电,RTC就能正常工作,所以不需要每次开机都初始化一次时间,当没有初始化时初始化一次,初始化之后,以后开机就不需要再初始化了。为了标记当前设备是否已经初始化了,手动的给备份寄存器中写入特定的值。每次单片机启动后就会读取一次备份寄存器的值,当备份寄存器中的值不是写入的特定值,就说明当前设备还没有被初始化过,需要初始化一次。如果备份寄存器中的值是写入的特殊值,就说明当前设备已经被初始化过了,不需要再初始化了。8 G5 ^1 d9 T. E8 E/ Z% ]6 d

# [' ]$ E: h$ Z% o$ W  在初始化的时候,开启RTC的秒中断,这样RTC每一秒就会中断一次,在中断函数中通过串口打印数据。当程序运行后在串口工具中就可以看到每隔1秒,就会打印一个字符串。. `* f6 w6 q! n& t- M

$ P; y. p" O( g- c3 N, o7 O+ ]) [: c
# ]6 S- i% g0 c# S( T. V0 H
) J* T' B+ q5 |' L
赞 收藏 评论0 发布时间:2022-3-19 20:26

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版