最近有个项目,用到STM32L151,原设计者使用外部8MHz晶振。有一天晚上调试过程中,突然发现程序跑不动了,翻到背面瞧见HSE脱落了~~~再用RCC_GetClocksFreq(&RCC_ClockFreq);观察RCC_ClockFreq.SYSCLK_Frequency,只有2.09MHz。手扶着HSE重新上电,单片机运转正常。看来就是它的锅。 s7 u% f' w) p1 i) O9 R ( E+ p5 ` x. q/ f3 V 但是,家里没有电烙铁。! ], B0 n `5 r2 i& ^6 k$ w 9 s" [8 X$ ?, A: F9 o. [1 B 那怎么办呢?只能换用16MHz的HSI了,MSI非整就不考虑了。我从来都只是用SystemInit();初始化的,除了修改一下HSE的频率,从来没碰过里面的其他语句。 一开始,我写了一个HSI倍频到32MHz的程序,替换掉.s文件里的SystemInit,结果失败。可能是因为我写的程序本身有问题。 . D5 l. w& e" Y% a1 j 后来想想,不如向SystemInit();里面添加HSE启动失败后的代码。它里面负责将HSE倍频到32MHz的程序是/ E% X1 s3 i3 W % {6 ?& a9 y- g" G. N /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ SetSysClock();9 `2 Y( z* @! x2 o: d 在它里面,除了详细描述了HSE+PLL的启动方式,还有下列注释: ; I( {& s4 f2 f2 ?, ~( Y% A9 ~1 ? if (HSEStatus == (uint32_t)0x01) { ……省略…… }. p s( F3 v6 w% h; z' X' f else { /* If HSE fails to start-up, the application will have wrong clock( z5 n( `8 o8 l+ y+ x v! e% K configuration. User can add here some code to deal with this error */3 [/ ]1 {' F8 W/ U# N 1 B: O. u3 k" P# h7 T //翻译:如果HSE无法启动,程序将以错误的时钟运行。用户可自行添加勘正代码# D( v) d0 `; [9 @0 a1 J A } 3 `7 C1 S, Y5 d9 J4 d+ V ST官方竟然提前留好了坑!9 A3 S; b/ ]7 L 6 P/ x( Q5 K) J4 Z2 j 于是,仿照着HSE+PLL启动方式,我写了下面的代码,使用HSI+PLL,并添加到else{}中,观察RCC_ClockFreq.SYSCLK_Frequency=32000000,一次性通过。5 a( ]$ [$ ?* E' h" R+ a0 [7 M+ g " n4 }8 P* p) A9 i$ p /* Enable HSI */ RCC->CR |= ((uint32_t)RCC_CR_HSION);+ d% |; c1 c* k R /* Wait till HSI is ready and if Time out is reached exit */ do {9 F* W/ P( O2 O, c6 f HSIStatus = RCC->CR & RCC_CR_HSIRDY;9 h( Q9 p4 O/ }3 J" X6 a$ S1 M' R StartUpCounter++;6 s5 O7 E+ k2 B9 G% J! e7 e } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); ' m6 @4 d6 D* e+ [2 x+ u R if ((RCC->CR & RCC_CR_HSIRDY) != RESET) { HSIStatus = (uint32_t)0x01;) Y: e% U7 i, M$ n) B' Z& x* f Z }$ p& } d2 }! i7 R: ]9 a else& }1 Q5 z7 h9 k& j- X7 l7 m4 P {7 e4 X) E z6 Q# B1 W+ M HSIStatus = (uint32_t)0x00;; b; l" z4 z( E5 u" d } if (HSIStatus == (uint32_t)0x01)# ^" ~% [9 a2 M {5 I: e8 K8 L% L6 s" x. ^9 a) \- W /* Turn OFF the HSE oscillator */ RCC_HSEConfig( RCC_HSE_OFF );4 q$ F/ B$ o' v& L# `/ G5 R 7 ]$ ?. q7 H1 a+ v8 {, w /* Enable 64-bit access */, M% e. N( R) q9 ~7 n0 R! v FLASH->ACR |= FLASH_ACR_ACC64;2 }2 p, [+ x7 {7 m ( Y+ p3 |9 } M /* Enable Prefetch Buffer */4 g# Y. U* A! k FLASH->ACR |= FLASH_ACR_PRFTEN; /* Flash 1 wait state *// [0 V# {5 L+ N6 ?$ {$ y FLASH->ACR |= FLASH_ACR_LATENCY; /* Power enable */ RCC->APB1ENR |= RCC_APB1ENR_PWREN;1 j* K! z- V* W) O- @ /* Select the Voltage Range 1 (1.8 V) */5 _+ C* C8 s% P* @2 c6 t PWR->CR = PWR_CR_VOS_0; . I$ f- [/ f7 \5 F. ?9 [' E /* Wait Until the Voltage Regulator is ready */. a+ C: D2 G1 A+ j' Y) n; h+ H while((PWR->CSR & PWR_CSR_VOSF) != RESET)! R: x9 J& ~/ ?' K {6 a- ?" v8 @4 r, j6 B } 2 w0 I) O# n7 X( P3 _, c /* HCLK = SYSCLK /1*/ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;6 q: h3 a" c0 e% T8 [6 G& v /* PCLK2 = HCLK /1*/ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;" W, G4 v [5 L& V 5 f$ I* x, @: h9 c/ N /* PCLK1 = HCLK /1*/* ~& W# Q' ?* y5 s& ^ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;4 x; t1 R) S& N2 S4 [ % c9 \# u# S! w! J6 W! w8 P, t4 F /* PLL configuration */) m4 t5 p, i! F3 ~0 R N/ K$ ~ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2);2 c; F9 l0 z- U. |- d+ [ /* Enable PLL */ RCC->CR |= RCC_CR_PLLON;) s/ \8 M$ M+ l; |4 b$ ^- L8 v 9 v4 c& M$ o5 h$ i; y% }$ Q# L /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) B3 c$ d2 G6 [: K- V* _ { } ; N2 G6 _( V: q% b6 W0 s0 f /* Select PLL as system clock source */6 N9 _3 A: ^- M, q, H RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; * {# @; c: m7 y- I, B. s /* Wait till PLL is used as system clock source */ J% ?/ B* @5 s8 d( e+ s1 t while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL) { } }3 }" m; n7 e, w: k8 d ' \. V7 H7 _4 k3 _, Y3 f' h 1 a% H% T1 C1 }+ t$ o* X( H5 G 记得在static void SetSysClock(void)的第一行添加HSIStatus的定义,即:* n' x* M1 @! _& {( Q$ N p* N. P __IO uint32_t StartUpCounter = 0, HSEStatus = 0, HSIStatus = 0;- E, W! ]" E, Y0 h4 y( c 4 P& u* [' e$ m3 z' }* P |
基于STM32L协议传输数据到阿里云物联网平台
stm32L451比较器使用
在 STM32 F0、 F2、 F3、 F4 和 L1 系列MCU 中使用硬件实时时钟 (RTC)
使用 STM32L1xx 微控制器与外部 I2S 音频编解码器 播放音频文件
STM32L1xx 与 STM32L1xx-A 的差别
从 STM32L1 系列移植到 STM32L4 系列微控制器
如何校准 STM32L1xx 内部 RC 振荡器
使用 STM32L1xx 微控制器与外部 I2S 音频编解码器播放音频文件
STM32L1x 温度传感器应用举例
STM32L1xxx 硬件开发入门