|
[STM32 ] RTC 实时时钟的系统时间维护 STM32内部带有RTC时钟,可以使用内部LSI和外部晶振LSE提供时钟源。 ; p( M+ w7 s% S7 Q- `: m7 }: b LSI:单片机内部的晶振,受外部环境影响比较大,比如温度等因素;大概40Khz左右; " L% E: d8 B4 P- G" K- D% _& { LSE:外接32.768KHz的晶振,比较稳定; * b0 E' V- \" r" Q3 w ; D+ L' ^5 ?8 z9 F9 W F* q1 j! O 软件可配置选择时钟源,可判断识别是否起振。 驱动:% x. P1 \# s2 d- d5 V 5 ]) {( f; Z- p% [. m* O 5 l9 I5 W4 n, N 1、首先要启动对应的时钟0 ~* T. i6 }0 e( {6 n% {1 K 4 |- g% j# u1 g: o. Z RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);3 ?: D$ L* |0 r( |6 C, A0 @ " M$ x: i, i$ f3 j$ c g7 ] 2、使能RTC功能) e4 X1 D. ?, ]7 C+ t8 N) P: E PWR_BackupAccessCmd(ENABLE); ; m' d$ o- p' E0 r* u' e6 T ! l; [6 I4 {( w: e6 I1 Z) ^ 3、配置时钟" {* t2 S" ]8 n: O/ H8 V . i) t D, K: Z- M4 t# b; {+ Q" } RCC_LSICmd(ENABLE); //内部晶振 $ O; \; ^( w# I# [8 H0 C: F0 p RCC_LSECmd(ENABLE); //外部晶振 7 F4 n" Y; p" y8 W. ^# `5 j* }+ g 读取LSE状态3 a- c. Q. W( b/ F# G! a 0 g' D r8 g: R) j4 x, c 9 [, ^0 ^" Q: V# i+ I RCC_GetFlagStatus(RCC_FLAG_LSERDY) : x( j0 D5 Q, b+ t$ g 0 i4 S3 V7 M/ t, u* @ 读取LSI状态 RCC_GetFlagStatus(RCC_FLAG_LSIRDY) " _3 d) @) I F - e1 p1 N0 K$ S 4、操作RTC所有寄存器之前需要先确定总线为空闲才能操作成功;; P6 }! e+ d% T9 x0 z . [. H9 v( O' w' ?9 H" H9 S 0 r) I0 h, r1 V: o RTC_WaitForSynchro();//等待上一个指令执行完成;6 ~1 d# K; F. @* ]3 V$ L# M 9 z0 v6 E% W" H' p* F0 j0 o3 e s9 l 5、初始化配置属性* D5 D, Q' B5 D' e2 x# _ & W* k4 b7 A# H- w' V0 _ ! _* a) d! D: g //软件对时钟进行校准,HSE 按照32.768KHZ接入,公式如下:& k' P9 c3 Q1 } l7 U j: @ uwAsynchPrediv = 0xFF4 n8 p5 Y0 Y/ y' k. ^ - L! V. L' X' F1 Z: j # ^6 W# d4 S2 o- b4 U* U, B uwSynchPrediv = 0x7F9 A) p1 y; b: x8 i & y1 U' t$ V3 P9 S# A6 \4 d , T! _, z: D! v4 e+ X ck_spre(1Hz)=RTCCLK(LSE)/(uwAsynchPrediv + 1)*(uwSynchPrediv+1) 4 ?2 R& D" o: U$ c, j4 g( c% F% s RTC_InitStructure.RTC_AsynchPrediv=uwAsynchPrediv; RTC_InitStructure.RTC_SynchPrediv=uwSynchPrediv;$ h7 n( @9 F/ Z. i- i; g6 X //24/12小时制 ! B4 C) y5 D& M$ S! } ; G. d& [5 A0 M5 h; }( a " E8 f7 u$ w2 [$ _ RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; RTC_Init(&RTC_InitStructure); 7 w; j, I4 d$ n& K7 i! e3 q 6、时钟在不掉电的情况下只需要初始化一次即可,程序复位防止多次初始化,在BAK区域写初始化标志,可解决; 2 o( u0 T! S$ V$ v9 h" @ RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); : [ \4 k S+ P- N' } 初始化前,读取RTC_BKP_DR0,查看是否为0x32F2,如果是,表示已经初始化成功。4 u- l! q) X# I7 c- h- d4 X T8 ]. L if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2) 7、读取日期时间 * ]" k6 c& x5 Q3 b% Q 7 b Y/ [ E4 t4 S; e2 b { RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);4 z1 `# `/ v# S* C" T 6 h" C& o; W8 C z# _( o' x 8、写入日期时间- |# U% |9 ?' c) c* ~7 f * Y/ G( {2 S, L% d# e( U+ s1 z $ d% b8 H6 C$ @2 [ RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); 8 k: v, c$ f; w% s$ y7 U e2 H ; I1 `# }- A! s$ `2 p5 M9 d* Z- T % z3 w& D# m0 C* M7 @ 下面为此篇文章的重点 5 [: Q+ G# r, d" o0 Q 系统里面保存事件或者打印信息,都带有时标,不可能每次都去操作MCU的总线去读取RTC寄存器获取;或者是外部RTC芯片8025,IIC接口; + A8 G" @1 g( h( Z. I ) ]9 z2 O% C5 V, o# r9 P r7 v5 _ 直接操作硬件缺点如下:7 L; Q: Q& Y" L! | $ S m( B1 {! P3 k/ k 1、直接从硬件中获取事件,精度很难取到ms级别,芯片最小刻度为秒;; d0 u- e9 \! R/ u& @4 W: w 2、操作总线占用系统资源,降低MCU性能;% V8 Z7 p, X/ o* g9 s ! O4 Y# @, s" e1 ~ 为解决这个事情,需要系统中有个维护软时钟功能,接替RTC的走时; ) s( z; Y+ l4 @+ K 具体做法为:% J. l8 F1 q; ^6 R 1、开启定时器,具体根据需求定义周期,可开启一个1ms定时器; 2、软时钟1ms累加计数,1S=1000ms;累加到1000,秒数加1; 3、防止走时误差大,一小时建议同步一次时钟,从硬件RTC中,把时间读取一次到软时钟同步; |
实战经验 | 基于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库
微信公众号
手机版