STM32L1开发心得(一、RCC/PWR篇)# u8 ^' B) z0 [! ^* f9 X+ A
- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。
' h& X! _/ d1 k# G - STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。
& X3 t+ k: E; Z! f) a - 本篇主要说说RCC/PWR的配置。 [- [* ]1 O; {+ \6 b T
- 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:
: G" h9 P* D4 H X0 X7 q- n. Z - 1、 L1系列的最高频率只能达到32M# H# y4 p; ]& c* _
- 2、L1系列的HSI是16M的
3 p3 o* t4 p. H - 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源
/ Z8 A; F9 U9 A# V - 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合. t& D ~/ Z- z6 ?0 Z
- 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置/ P6 k+ _; b/ | u) `7 X T
- 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V
. H& g. a5 g; e: f - 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上
" o3 O& C) ?7 T$ I" R5 O& G - 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):7 G# P1 x! O8 Y8 \
- RCC_DeInit();
7 `: ]! Y/ T& Y- D6 p - RCC_HSICmd(ENABLE); //开启内部晶振HSI
# h. G$ W! z( ?* D2 _ - while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪$ Q! B# j$ |+ X3 _4 `% f& \
- FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH
- l9 ~ u) D6 L: @6 o' d0 T - FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能
+ E: }2 t& h6 ]2 H8 u1 h - FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期8 m( Q' p, L8 w. r; W! U5 p
- RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER) B7 l0 H s$ |% K' X0 ?. `- r
- PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V). U6 y$ y) J' p
- while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定" S+ D. O/ L, ?! B
- RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK
+ `% Y; k4 N) ?& T$ _ - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2
5 @# W2 s- f# f6 E0 |1 i k& h - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK13 w7 f- {( E. o' X9 }# Y, e
- // PLL =16MHZ*2=32MHZ ( R1 H+ S+ H( z# n
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |0 X& y' @' z* c7 P. J
- RCC_CFGR_PLLDIV));/ c& G- w" g" l
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);
% s& C! U" `) k) o; o - RCC->CR |= RCC_CR_PLLON; //使能RCC! q9 _5 ^" b' ^2 z" _ |
- while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定
0 _7 C. W6 u0 o. [: k - //选择PLL做为系统时钟
% D% q9 n0 V) H5 j# R& | - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));' h- l) g4 e2 q: h( A5 f8 x) J/ u
- RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
' O2 K/ a% J: P - //等待PLL稳定
# l" u- R6 H" Y - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}% c. }8 q" [8 N! e9 w; T# i
- //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA3 y' N1 o6 c X, H" M2 u
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码 - s+ b$ S& W! }+ o: V
: v6 y0 z. A0 r" h; _ ?3 P2 j( Y4 v1 Q' `) N: J) H1 k A$ ^
|