STM32L1开发心得(一、RCC/PWR篇)" \$ j" M5 p& x" _+ e% D
- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。4 y" d2 V8 {! @: N! D
- STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。
: @- M6 Y8 S% x- ]. \ - 本篇主要说说RCC/PWR的配置。- I2 O, U. x) h7 v$ T5 l! b
- 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:
+ C: h2 [- @( ~ - 1、 L1系列的最高频率只能达到32M
8 l) d9 a1 A+ M - 2、L1系列的HSI是16M的; L" r. F' l. A% E# c- _
- 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源; @2 u N* T0 v. g3 b0 w
- 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合
; N$ ?' q& W, }- ?1 I) m* V% b - 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置
; N/ A% i& [3 z' n% p- X - 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V8 \. r/ I5 U& X4 m2 X: g
- 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上# [& k7 G. T7 B6 Z. Z8 Q, K
- 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):/ }- b/ G& X0 g6 D; z! U" Q
- RCC_DeInit();
1 I' l2 R/ D# z8 _9 t7 I; C9 }# N - RCC_HSICmd(ENABLE); //开启内部晶振HSI' Q; ` l$ o% K4 A( o' T' @3 V3 B
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪3 |! p' d$ n8 X
- FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH$ T1 E _5 s8 I$ m
- FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能# Z. c& ?5 `. q5 ?5 h' s/ F5 R3 x) s
- FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期
- e! U" Y! o: _ - RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER8 M) V2 k; `* W9 @4 B
- PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V)$ u, B1 A" x5 g$ s6 Q9 A' M
- while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定4 `$ D( \4 z' D
- RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK" s9 k$ C5 z" I4 a
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2
- x* }. }# P5 x" G! l9 M% R - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK1
+ n# d" B' c5 ]& G& I - // PLL =16MHZ*2=32MHZ ) Y' F1 N& f) o& ~0 M/ J8 Z
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |# @: O* a' x& D: G" d
- RCC_CFGR_PLLDIV));" ]1 f# E0 j* l# f
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);
" L, a9 P( e, C7 i, k6 j - RCC->CR |= RCC_CR_PLLON; //使能RCC
. u1 [9 s0 @* q/ u2 @, A) Y/ V: F - while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定6 z( ], D% l# @
- //选择PLL做为系统时钟
( m" k3 Y# x) x - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
r0 H, ?' V$ e! N7 l- ^ F+ k. n; t - RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; # g4 Y' y5 M0 q! m$ R9 v# F9 ~
- //等待PLL稳定6 }- ^$ W4 o) g" X+ X: \
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}$ @" I( z2 {* s2 z5 c
- //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA! h6 w0 x- D8 @* t; q, S2 u2 \8 g. f
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码
0 F2 }1 @% \+ l! y; G7 \: M5 C6 j. c# V# P2 y% T. T# M$ W
- U3 P1 W4 p% L |