|
最近有个项目,用到STM32L151,原设计者使用外部8MHz晶振。有一天晚上调试过程中,突然发现程序跑不动了,翻到背面瞧见HSE脱落了~~~再用RCC_GetClocksFreq(&RCC_ClockFreq);观察RCC_ClockFreq.SYSCLK_Frequency,只有2.09MHz。手扶着HSE重新上电,单片机运转正常。看来就是它的锅。' _8 V+ I5 c5 {2 R9 `4 a( \- A 4 M3 b; N* ?" i# |$ K 2 a( C! o0 x! W( _ 但是,家里没有电烙铁。 : Q5 s+ s9 p0 w7 e1 _ 那怎么办呢?只能换用16MHz的HSI了,MSI非整就不考虑了。我从来都只是用SystemInit();初始化的,除了修改一下HSE的频率,从来没碰过里面的其他语句。6 n' n# U, e, H( ^" ]* c& e 一开始,我写了一个HSI倍频到32MHz的程序,替换掉.s文件里的SystemInit,结果失败。可能是因为我写的程序本身有问题。 3 d: x6 ~# H* o5 |5 C1 h, D 后来想想,不如向SystemInit();里面添加HSE启动失败后的代码。它里面负责将HSE倍频到32MHz的程序是 % ?, {8 X1 c' S+ Z' A/ a 6 I! }' H( o6 J! c /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ SetSysClock();" h# J P9 n" Y9 d2 m( L. c # \5 Y% x" b5 A$ ?5 c7 B5 k2 k( \/ S5 o 在它里面,除了详细描述了HSE+PLL的启动方式,还有下列注释: ' L% W! _8 z+ Z" s0 s9 M; K! M ; K2 V8 B. |+ h4 `' o if (HSEStatus == (uint32_t)0x01) { ……省略…… } else# V Z; T" O' D2 t, L1 \ {; `$ ^. O" f% ^ { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ //翻译:如果HSE无法启动,程序将以错误的时钟运行。用户可自行添加勘正代码5 T4 t; I; T+ R s" j. X. V }0 `1 d! Z+ _9 e; U9 l ( J/ L! G" L1 s. m6 g; ^. c ST官方竟然提前留好了坑!2 i5 B& g% N, r" b6 F% S , T, x8 f8 m" z. B& @* [* q" W3 M 于是,仿照着HSE+PLL启动方式,我写了下面的代码,使用HSI+PLL,并添加到else{}中,观察RCC_ClockFreq.SYSCLK_Frequency=32000000,一次性通过。 1 b" A- Z) a* I+ @5 E* P& ]8 t' } /* Enable HSI */ RCC->CR |= ((uint32_t)RCC_CR_HSION); /* Wait till HSI is ready and if Time out is reached exit */ X' E) T( r, t4 o! _- h/ U do) }" o3 u+ `; L. A8 ^0 [$ w {9 S* u0 G3 U4 ~) Y* P HSIStatus = RCC->CR & RCC_CR_HSIRDY;/ N" G, S4 U3 n ]8 d StartUpCounter++;/ V! B& @3 d; \% Q- _7 U } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));7 | L6 V$ U* T" Y if ((RCC->CR & RCC_CR_HSIRDY) != RESET) {6 w( Q0 O$ n$ [, B0 w1 U HSIStatus = (uint32_t)0x01; }8 a- D' g: q" W! I2 K* D else { HSIStatus = (uint32_t)0x00;2 d/ w! x7 Y- O" [ }" H) k' d* }9 N, [0 ~) h" s if (HSIStatus == (uint32_t)0x01) {, Z0 ~7 W8 Y \0 ?+ ?5 f/ y /* Turn OFF the HSE oscillator */9 t: p, \9 X5 l+ w* b6 ? RCC_HSEConfig( RCC_HSE_OFF );! S7 k9 e0 L F6 x' Y6 X7 s9 d - Z1 T$ N! b; r3 W8 |9 a /* Enable 64-bit access */8 X4 d) [. v# j6 Z- Y! Q" s$ n$ U FLASH->ACR |= FLASH_ACR_ACC64;' T9 Q9 E& R: q0 R$ Q ) a2 A/ h; T; R" ~, Q7 m, W& q /* Enable Prefetch Buffer */# V& ^+ M: Y# m2 |2 k, N FLASH->ACR |= FLASH_ACR_PRFTEN;: u; Q! o3 D u3 F" l; X. A \. Z N" R7 Q /* Flash 1 wait state */ FLASH->ACR |= FLASH_ACR_LATENCY; & W7 F) T, Q; ]& e; L H /* Power enable */ RCC->APB1ENR |= RCC_APB1ENR_PWREN;; ^6 f8 m+ ~ ?9 ~ D# }2 _# p7 {. r /* Select the Voltage Range 1 (1.8 V) */ PWR->CR = PWR_CR_VOS_0;' {! }& J% c/ x' e8 w /* Wait Until the Voltage Regulator is ready */ while((PWR->CSR & PWR_CSR_VOSF) != RESET) {$ Q) _! x# z* D* A9 R }3 Z1 H) N# o! G* E4 v* I0 R( y ! x$ _+ R& f; g" s /* HCLK = SYSCLK /1*/0 l& V" T' M' L0 @6 T4 k RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK /1*/# F& S8 K- r1 K- q, w1 ?. G& p RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; T5 z3 q3 N) a q/ D: u/ u& y " Z7 w& ^9 f" a /* PCLK1 = HCLK /1*/ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 2 T% p9 V( p$ V: u6 G /* PLL configuration */; [# h- Z5 b& c( h2 j$ Z: _9 H RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |- E6 Q' G% c1 W* O- s2 t6 ^8 q RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2);" Y1 m u* _; ^0 B 8 P9 t( C& K6 V- x) r /* Enable PLL */ RCC->CR |= RCC_CR_PLLON;: a7 s0 e7 T- I5 | x /* Wait till PLL is ready */+ [$ W" e; V% Y* C* ? while((RCC->CR & RCC_CR_PLLRDY) == 0) {+ K& o( m/ F: C" g4 f& | } /* Select PLL as system clock source */' e8 U3 m$ j+ N( t# K RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));4 G0 Q% M8 q; L6 e" f8 j" b3 k# M RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; T0 f/ a0 t/ k& l4 P2 E /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL) { } ( O/ I5 b8 V! k8 e } 3 S0 Q6 X7 R- [. A0 d7 O$ d 记得在static void SetSysClock(void)的第一行添加HSIStatus的定义,即: __IO uint32_t StartUpCounter = 0, HSEStatus = 0, HSIStatus = 0;" J5 K3 ~* T G8 _1 j* P : \, |5 ?' ^7 H/ j |
微信公众号
手机版