|
[STM32 ] RTC 实时时钟的系统时间维护 ' @/ W0 b5 C' N6 X) I! @# V o$ Z STM32内部带有RTC时钟,可以使用内部LSI和外部晶振LSE提供时钟源。 + p% M& b7 N+ |' n+ {3 Q P) q LSI:单片机内部的晶振,受外部环境影响比较大,比如温度等因素;大概40Khz左右;. c' C' g. A* w% e LSE:外接32.768KHz的晶振,比较稳定; # U* z8 X8 G, B9 z* t: V% x7 d) c : A& G. D9 C7 d- w: B/ Y ^ 软件可配置选择时钟源,可判断识别是否起振。4 y" i, c* p! M6 n 6 Z3 N2 J3 ?% J7 L* D$ o 驱动: 1、首先要启动对应的时钟. c- q9 ?; N) Z1 n7 ` RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 0 G+ U2 z+ u( M7 U, T5 L D9 x 1 w# k. `! c) ?; G 2、使能RTC功能 ; _+ t- k3 L8 Q4 C6 K B3 X4 f& [ T' W5 Z PWR_BackupAccessCmd(ENABLE);% h* `- I ?, V( k- u 3、配置时钟 ; I% n7 o6 S7 d7 r0 J3 ` RCC_LSICmd(ENABLE); //内部晶振 + @0 A' @5 z- ]! O6 K/ e RCC_LSECmd(ENABLE); //外部晶振 u9 O T& E: R0 |" Z2 v/ t 读取LSE状态" I: J( m/ D" O* m ' B; k. i$ A1 q6 H; U 5 ^7 Y5 l+ ?$ P+ T5 b: g3 X RCC_GetFlagStatus(RCC_FLAG_LSERDY) ; Q% `2 z0 T9 t. [ 读取LSI状态* r* ~/ H0 j+ h- N! X, p - ~+ O7 p" `6 G( W7 p # y& P* g; u9 L5 j RCC_GetFlagStatus(RCC_FLAG_LSIRDY)( W. y; B, K! X8 p6 w0 Y 4、操作RTC所有寄存器之前需要先确定总线为空闲才能操作成功; RTC_WaitForSynchro();//等待上一个指令执行完成; % w5 j. T8 O) Q8 W1 N 5、初始化配置属性0 k: y1 i! Q6 X6 K% o //软件对时钟进行校准,HSE 按照32.768KHZ接入,公式如下: uwAsynchPrediv = 0xFF* M- g( G' D( i4 ` 2 Y0 ^' D* ], _/ X! y uwSynchPrediv = 0x7F ck_spre(1Hz)=RTCCLK(LSE)/(uwAsynchPrediv + 1)*(uwSynchPrediv+1) RTC_InitStructure.RTC_AsynchPrediv=uwAsynchPrediv; 3 b& r! o6 r) T' l7 H9 K+ `# I RTC_InitStructure.RTC_SynchPrediv=uwSynchPrediv;7 Y0 e$ N( h7 ~6 e& ^ 0 n! m" x4 G* b1 K, h; @5 U, V //24/12小时制 4 [9 ]3 m% D, A9 P. J RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; 8 {! s4 `! ?/ I5 s7 \2 Z: Q8 X# z4 V RTC_Init(&RTC_InitStructure);0 Z$ J4 e1 V5 h/ E7 Q. I 7 j8 r* H( c& ^3 b; t1 v # `/ J! Z- \) ~4 F 6、时钟在不掉电的情况下只需要初始化一次即可,程序复位防止多次初始化,在BAK区域写初始化标志,可解决;% W. ?0 ~* b7 F+ @! N 5 O9 v. Y+ B2 s RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); ! h! P- b8 ~ q9 P) G 初始化前,读取RTC_BKP_DR0,查看是否为0x32F2,如果是,表示已经初始化成功。2 X6 l2 c8 v3 R : V+ U) c- q' x, y% |0 r if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2) # P: p" B2 e3 i, V 7、读取日期时间 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);6 _% F7 C# K0 Z3 F _0 _3 P' p + c9 {; Y: ?; P4 u( u) @ 8、写入日期时间; z. ?" ~' j! R1 G9 U ; T. G* d. S r( x/ S RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); ; t/ o5 n* e1 Z" Q: P* a+ ?5 C& m& f 7 t) l; n, Q+ n/ o- V: p" [* g 9 k6 i- @, y- A p 3 Q. R/ s& v4 n4 p/ Y1 a 下面为此篇文章的重点 , H1 s( L# c) u2 f; N 系统里面保存事件或者打印信息,都带有时标,不可能每次都去操作MCU的总线去读取RTC寄存器获取;或者是外部RTC芯片8025,IIC接口; 9 b" z* n7 a7 z. X) Q( q3 q( u% k6 B) B" m 9 d' |+ A [4 M 直接操作硬件缺点如下: 1 ?. J: W/ l* i. A 1、直接从硬件中获取事件,精度很难取到ms级别,芯片最小刻度为秒;4 b6 U" ~% E; `0 O2 z* |7 i+ y/ v* v 2、操作总线占用系统资源,降低MCU性能; + M6 H6 d3 R. S( f; \8 _ 为解决这个事情,需要系统中有个维护软时钟功能,接替RTC的走时;4 {. C- i3 a( o4 r8 Y & f: t c \4 n ( Z R8 V& X6 ], O9 U 具体做法为: 1、开启定时器,具体根据需求定义周期,可开启一个1ms定时器;0 }3 m$ g d9 c 2、软时钟1ms累加计数,1S=1000ms;累加到1000,秒数加1; 3、防止走时误差大,一小时建议同步一次时钟,从硬件RTC中,把时间读取一次到软时钟同步; ( j ^4 y8 _/ D9 @" A2 h6 w2 T( g$ i |
实战经验 | 基于STM32G0B1的全桥移相+同步整流PWM解决方案
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
【福利三:逢7发帖赢大礼】8、基于STM32G070板子的Ymodem串口协议IAP Bootloader开发
【福利三:逢7发帖赢大礼】7、基于STM32G070板子TF卡的FATFS移植
【福利三:逢7发帖赢大礼】6、基于STM32G070板子spiflash的FATFS移植
【福利三:逢7发帖赢大礼】5、基于STM32G070板子IRDA红外遥控接收解码
【福利三:逢7发帖赢大礼】4、基于STM32G070板子SPI flash 移植SFUD库
【福利三:逢7发帖赢大礼】基于STM32G070板子的uart shell移植设计
【福利三:逢7发帖赢大礼】3、基于STM32G070板子的YModem串口协议通信
【福利三:逢7发帖赢大礼】2、基于STM32G070板子的OLED移植U8G2库
微信公众号
手机版