STM32L1开发心得(一、RCC/PWR篇)
& {8 p2 y+ u9 K- ]4 o- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。
! R" z. H- T) B1 R# ] - STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。
. r1 \1 L+ V3 ^; b6 X! }7 m - 本篇主要说说RCC/PWR的配置。
1 U1 W* A3 o! H8 q* p% w8 Z7 K/ H - 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:
% R7 k3 b4 N1 s4 @8 y! T( k2 @ V - 1、 L1系列的最高频率只能达到32M0 [( A, o2 ]& h& H7 P; y; s
- 2、L1系列的HSI是16M的
' X3 Y2 M6 Q% `9 v6 k6 _# O - 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源
: t# v. @) H6 \# K1 I0 U - 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合
9 i, U: o# q* v1 a9 ^ - 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置, O& p/ `/ v$ Y1 i9 | C- q
- 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V
5 N5 p; W/ a5 f3 T - 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上" j! f# z: x' {; X6 F
- 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):
. }, W' J' u% B3 \( y. g; J, ^' e& T - RCC_DeInit();
- v D' x( Q6 s1 I6 I. i0 [ - RCC_HSICmd(ENABLE); //开启内部晶振HSI
: |7 J, U0 j. N: K2 T6 g c - while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪! I% l$ Y* q, P5 V
- FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH# G- T- R0 m3 A& t# O
- FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能" @4 [- y' I, F8 b( z9 \# `
- FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期, ~ w+ q, E' ?/ E+ Z
- RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER6 L' a% H- }- M; T: p1 ?$ Y9 C
- PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V)
( t# Z* H J+ z0 `' H* } - while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定
3 ~$ w$ o0 E/ E: y - RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK& ~% w$ p! B! @5 l
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2/ K& h9 I! r# G2 w% a: Y
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK1
1 p& h- z: g/ t+ ^# M - // PLL =16MHZ*2=32MHZ
2 H: F% n1 H! Y8 h) G" w - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
% z* @3 a. j# }; P% g: z# a( T# G. ? - RCC_CFGR_PLLDIV));
1 I& g% @5 A' C }5 x( B) T) E) X - RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);
% Y% a" x( B( v# X/ z, ~" [ - RCC->CR |= RCC_CR_PLLON; //使能RCC
: o. J+ n5 |6 b( e; Q1 p" { - while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定
% A- z7 ?# v7 Q4 Y$ Z - //选择PLL做为系统时钟
. W( U) H$ c9 L0 \8 v8 ~4 I - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));! P# \# S" X& B3 B
- RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + d/ \. S6 P% |! B6 D$ m! \
- //等待PLL稳定5 U1 a$ Z( j4 B1 [) z
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}
* ]( @2 K# |4 o" G! n0 _ - //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA
) R2 _, S* i ^# ~" \: G - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码 : j7 Z! v) g& F6 W
. C, ~5 H& i* c0 {8 o0 x
; _! R) H& ]) s
|