STM32L1开发心得(一、RCC/PWR篇)
; S9 r5 l, z" d) A- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。
# Z/ N( z3 n7 @! `$ D" [/ M - STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。/ Z1 L) q. A( [( Q& I8 [6 n+ a
- 本篇主要说说RCC/PWR的配置。& [4 \; G; y, B" Z
- 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:( i% S$ l. m. n2 V, h! y: q# \
- 1、 L1系列的最高频率只能达到32M2 y D) @& |# v4 g1 e! Q$ `
- 2、L1系列的HSI是16M的9 D& p( d* z T
- 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源$ m3 N! O& X1 K9 v' _( d9 a
- 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合
& c5 _, h; s/ N. s- j3 M7 x9 m$ w - 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置
4 g% h5 V5 }# I" p3 \+ ~ - 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V" s% n$ G" g5 w. x. B
- 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上' P8 t) g9 Y5 T9 }
- 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):
/ a4 q& m6 Q: e Z7 S - RCC_DeInit();/ \& U; h4 l+ P9 l2 ~9 L9 M
- RCC_HSICmd(ENABLE); //开启内部晶振HSI/ L7 i V& p6 \6 S% p
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪
( t% ]6 U% J, E: i2 j+ e, a1 f - FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH
% Y' {8 v! z$ J' }0 T, Y - FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能- h+ {/ ^, n' ?1 X, D& _% C8 c
- FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期
( F4 u- C0 G3 m - RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER
, V! t i" g u: g5 g - PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V)
) H, o. Z5 Z3 h3 h5 @6 m2 M - while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定
. C* ~4 [% n1 ?! s! o - RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK
! [3 B w: Q/ i/ J, @/ z4 D2 n - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2
8 d1 @+ @9 }% d& T2 ~4 m; b - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK1
- B! }9 X9 a( W" ~- V' h% c - // PLL =16MHZ*2=32MHZ
' U) b6 ^: \+ k. X( b - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |2 O; {% v7 l0 t0 `8 g, ^- Y% @
- RCC_CFGR_PLLDIV));+ [/ r) W6 N6 _( W+ _
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);& t0 q& j7 V$ P
- RCC->CR |= RCC_CR_PLLON; //使能RCC* g1 H# O; g U2 `0 |
- while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定
+ m5 y4 k8 `: [9 e9 \$ Y. c - //选择PLL做为系统时钟 6 z: ]% c1 q! L0 k$ G/ w+ e
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
+ ]4 O$ E0 k% w/ b; }% V7 M - RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 1 B' x- e C6 n/ _+ i8 e" R
- //等待PLL稳定( p& L: b' @; o, a
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}
! U/ E0 G5 {& N7 f - //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA+ ]9 o/ L7 Y9 ~) a% I. V" f% w
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码
0 R: L% i) D; `0 p5 A! y$ L$ ~ v0 S9 e) d5 |% H8 c' S9 @
% k- r! h- q( K0 r0 s
|