对于使用STM32单片开发项目的同志,经常会使用到STM32的RTC功能,而在配置RTC的功能时需要配置晶振的使用,可以使用内部晶振或外部晶振,配置流程参考官方的示例代码即可。 但在之前的项目中遇到一个问题,由于一些产品的外部晶振损坏(时间长了有些外部晶振容易坏掉),导致RTC实时时钟时间异常。为了降低公司的维护成本,所以考虑通过修改程序,重新配置为STM32内部晶振来解决问题(我们的应用场景可以采用这种方法,因为服务器会固定时间同步产品时间)。. R. `* u0 r3 v( H3 Q1 t 采用外部晶振的RTC部分配置代码:' P8 W% X8 K. u! Y, F. p$ Y9 J /* Enable the PWR clock */) X9 C4 V: _/ ^) E; W3 u# P RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE);6 W' [( B! s& R O; W /* Enable the LSE OSC */5 D; A* q, v2 x7 p5 w- W' f RCC_LSEConfig(RCC_LSE_ON);* d. [8 k! ~ E4 z7 G. [/ W /* Wait till LSE is ready */ do{ tick++; }while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && tick < 20000);# D4 z' ? D- l: H. s' t. [ tick = 0;8 e0 |# s- r8 y* ?: E# ] /* Select the RTC Clock Source */* B8 z O: z+ I: ^ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); /* Enable the RTC Clock */ RCC_RTCCLKCmd(ENABLE); 0 d% K& A t: C i7 J7 ]% ^4 D* c RTC_StructInit(&RTC_InitStructure);+ H. J. E+ x1 H5 [% i RTC_Init(&RTC_InitStructure);/ y+ w/ L. M% n5 g /* Wait for RTC APB registers synchronisation */ RTC_WaitForSynchro();6 W( r3 `* W* ^ U 最初以为改为内部晶振配置比较简单,只要将和外部晶振有关的配置代码改为内部晶振即可。后来发现,STM32芯片的RTC时钟选择一旦配置了之后,想要切切换的话需要多配置一点东西,后来查了手册果然如此,这里给出配置代码,具体手册的说明有时间再放过来,以下部分供同志们参考。 RTC从外部晶振切换为内部晶振配置代码:+ ]/ D N4 s! | uint32_t tick = 0; uint32_t tmpreg1 = 0;) L7 X' j8 U- N /* Enable the PWR clock */6 k: A9 G0 C, w' R+ Q* p4 P y' ? RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);7 ]' k9 D# l' I) \# o2 G- [ /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE);) _- z4 C! i* ]8 T' f /* 晶振切换时必须执行的步骤,但不能每次上电都执行,否则会清空时间,同志们根据实际需求自行考虑执行位置 */ tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL)); RCC_BackupResetCmd(ENABLE); 1 v4 u A2 f3 y) E, H4 S RCC_BackupResetCmd(DISABLE);0 o8 ~2 @; Q6 h. h RCC->BDCR = tmpreg1; 8 C" {4 J- M1 t7 X; e' \( ~ f /* Enable the LSI OSC */+ f0 v% K4 J( X4 Q a RCC_LSICmd(ENABLE);: R& z! ?! w' e$ x6 ` /* Wait till LSI is ready */ - p: n" R+ o! f3 Q do{- }! Q) e1 R! N0 R% K( N ; Z- t+ R, T9 r5 {" H& c# \8 f3 y# m tick++;1 v% |4 L/ L, [# E1 j }while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && tick < 20000); tick = 0; /* Select the RTC Clock Source */. f! n0 T3 e/ Z RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); /* Enable the RTC Clock */9 M% S$ C7 O8 K# p RCC_RTCCLKCmd(ENABLE);* |( H" @. Y- [+ \+ R5 D! w RTC_StructInit(&RTC_InitStructure); RTC_Init(&RTC_InitStructure); /* Wait for RTC APB registers synchronisation */ RTC_WaitForSynchro(); 7 b! t) M* C6 x) e u 天道酬勤! j- U% X6 B4 C" E |
原子的程序不是这样写的,也能够在外部晶振损坏的情况下,调用内部的 |