最近有个项目,用到STM32L151,原设计者使用外部8MHz晶振。有一天晚上调试过程中,突然发现程序跑不动了,翻到背面瞧见HSE脱落了~~~再用RCC_GetClocksFreq(&RCC_ClockFreq);观察RCC_ClockFreq.SYSCLK_Frequency,只有2.09MHz。手扶着HSE重新上电,单片机运转正常。看来就是它的锅。 但是,家里没有电烙铁。) E: i; l4 k! Q, F# E# K' a+ | 那怎么办呢?只能换用16MHz的HSI了,MSI非整就不考虑了。我从来都只是用SystemInit();初始化的,除了修改一下HSE的频率,从来没碰过里面的其他语句。 一开始,我写了一个HSI倍频到32MHz的程序,替换掉.s文件里的SystemInit,结果失败。可能是因为我写的程序本身有问题。* T: g6 _& ?5 t& o 0 D! y- R$ D! u$ w0 y 后来想想,不如向SystemInit();里面添加HSE启动失败后的代码。它里面负责将HSE倍频到32MHz的程序是 * \( q9 l" ^6 R& B; C /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */0 q/ B+ u1 G9 h! t SetSysClock();; W2 `/ o" O3 U! K* h M0 [ * \/ h# m( T& w' N1 o4 q6 ` 在它里面,除了详细描述了HSE+PLL的启动方式,还有下列注释: # k! m |# \# N1 M3 e, k* | if (HSEStatus == (uint32_t)0x01)/ _ ~$ V1 k/ [! u {: l& L3 G, h) L0 ~* V# k ……省略……, V9 ~" I6 Z8 {, P9 V! l8 M } else- X" F {$ p U+ h0 u! j { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ 2 f$ A ]% n' z6 ^- G //翻译:如果HSE无法启动,程序将以错误的时钟运行。用户可自行添加勘正代码$ C" t+ O4 _9 f0 l& I4 l8 u& Y } ST官方竟然提前留好了坑! " @; S) C0 E% O* y+ Z# Z9 Q 于是,仿照着HSE+PLL启动方式,我写了下面的代码,使用HSI+PLL,并添加到else{}中,观察RCC_ClockFreq.SYSCLK_Frequency=32000000,一次性通过。4 j4 x; w) _( E6 i9 }, | 9 k4 |6 F- w4 {2 h /* Enable HSI */ RCC->CR |= ((uint32_t)RCC_CR_HSION);! t8 B4 q! s* F% O$ y* H /* Wait till HSI is ready and if Time out is reached exit */ do {7 w" E% A" v+ P6 k7 X" l HSIStatus = RCC->CR & RCC_CR_HSIRDY; StartUpCounter++;+ s! O. n! A/ C- _% } M1 } } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); % L$ u6 T- T( t+ O( e4 y/ M if ((RCC->CR & RCC_CR_HSIRDY) != RESET) i5 s& p% m7 k { HSIStatus = (uint32_t)0x01; } else/ M7 N& @9 @9 {% _0 J1 L3 e& r {$ ~1 A: `' u$ ? HSIStatus = (uint32_t)0x00; } 9 k1 t: ?3 j; c1 n' Q- L/ W$ ] if (HSIStatus == (uint32_t)0x01) { /* Turn OFF the HSE oscillator */ RCC_HSEConfig( RCC_HSE_OFF );6 B$ p4 s! B8 O1 }: Y( I, v/ U3 N /* Enable 64-bit access *// f* L2 q0 R' b; k7 w FLASH->ACR |= FLASH_ACR_ACC64;/ `4 Y% ?& j$ H$ A# e9 G c 5 }5 s1 _; B/ f /* Enable Prefetch Buffer */& r- Z$ C* M* X3 b K/ I/ g FLASH->ACR |= FLASH_ACR_PRFTEN; /* Flash 1 wait state */ FLASH->ACR |= FLASH_ACR_LATENCY;1 p; M" f* A6 M% q /* Power enable */ RCC->APB1ENR |= RCC_APB1ENR_PWREN;5 v. N9 U3 m. x6 x /* Select the Voltage Range 1 (1.8 V) */& P) j+ u3 w* P8 g PWR->CR = PWR_CR_VOS_0;' |& D8 F0 F& ]4 a2 A9 Q4 e: K5 m /* Wait Until the Voltage Regulator is ready */, {4 S- z9 j4 O6 H while((PWR->CSR & PWR_CSR_VOSF) != RESET) {7 C7 I- e e4 N! i! q" e }7 Z3 \! K) @3 E* z; l , A# E; O+ u* E ]# _4 U; i% } /* HCLK = SYSCLK /1*/* b6 N- f3 C/ q( V3 g5 w/ d5 G+ G RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK /1*/) I& i' j/ A3 U2 M4 w2 G RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/ S9 J% ]1 O# F: p /* PCLK1 = HCLK /1*/ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 5 o9 o$ _! ?3 D7 ? /* PLL configuration */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |, x$ a- E6 N* x2 q9 }1 w RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2); ; F" y3 i4 X/ w% t" f V: a /* Enable PLL *// C, {8 V' g# G' L5 `8 f RCC->CR |= RCC_CR_PLLON;' p R2 r9 [! U/ c5 q1 f ( T: J5 k# q' E /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0). E1 g6 @6 X% R" W8 y" B# A# ~ { } $ D. u E& W; ? /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));9 x. H- W; ?( o; q RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;7 l, n; _2 l( Q$ t0 y . ~4 `* i8 ^* a9 @: R7 k3 V /* Wait till PLL is used as system clock source */3 _) L' f, U; [! b6 x w( S% Q0 b while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL); O% j) A- H0 [1 u, n# h; G: C6 P- N {8 X/ s, n/ {! m* k4 [" f0 k2 u) { } }8 _' o% e; {1 z+ p9 _+ x/ y $ J# c) x5 o* o% P4 p4 } 5 F0 c; W- y/ E. S2 ^( R 5 h( l. B6 F6 ?1 M3 \0 j# d 记得在static void SetSysClock(void)的第一行添加HSIStatus的定义,即:+ t+ h3 ]! ~& N: s __IO uint32_t StartUpCounter = 0, HSEStatus = 0, HSIStatus = 0; |
基于STM32L协议传输数据到阿里云物联网平台
stm32L451比较器使用
在 STM32 F0、 F2、 F3、 F4 和 L1 系列MCU 中使用硬件实时时钟 (RTC)
使用 STM32L1xx 微控制器与外部 I2S 音频编解码器 播放音频文件
STM32L1xx 与 STM32L1xx-A 的差别
从 STM32L1 系列移植到 STM32L4 系列微控制器
如何校准 STM32L1xx 内部 RC 振荡器
使用 STM32L1xx 微控制器与外部 I2S 音频编解码器播放音频文件
STM32L1x 温度传感器应用举例
STM32L1xxx 硬件开发入门