STM32L1开发心得(一、RCC/PWR篇)
5 G% d0 J1 V3 x) `) v+ Q- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。" c0 [8 k$ P& V! y5 E
- STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。: m- M A+ F9 m& q
- 本篇主要说说RCC/PWR的配置。1 ^# A" `3 E# E: |, q3 z, [
- 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:; V/ S! d& u- j7 H
- 1、 L1系列的最高频率只能达到32M
$ L' y! Q- _" P, ]/ ]* { - 2、L1系列的HSI是16M的' v2 X. x* c. e2 N2 N/ \9 U
- 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源
5 l1 X/ ~& ~* t3 X - 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合8 r; j8 B6 n' _& W' s: x9 r
- 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置+ I6 E3 l: o! G4 ~6 j
- 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V
9 n2 D' h2 h2 ^% U' c% z p8 B# } - 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上, `1 B- m5 f2 v5 d0 L
- 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):& A; R) C1 Y* D" I' V8 [0 g& p
- RCC_DeInit();6 j$ H+ P+ B% B: n
- RCC_HSICmd(ENABLE); //开启内部晶振HSI6 P$ `2 M" D+ ^8 D
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪
( y+ Y) R8 x6 V- T1 P - FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH O# \" L' N1 H+ A. ]
- FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能3 P# Y$ Z# J6 e% d2 ]( \4 P) |# K
- FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期% t' u0 M/ n7 N5 {0 h5 j7 W
- RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER
2 b2 ^/ w: O* C9 K - PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V)
! z9 P: G \* Z. V9 s - while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定
3 x$ q3 E" g" ?. G H' Z - RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK: f$ V" `; b) N: n3 T- j' R
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2
1 D' _* G: p9 p5 M6 n/ C- a2 q - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK14 c8 U! a, R$ w+ j, i5 ?- W
- // PLL =16MHZ*2=32MHZ . a- N6 Z# C- z, _) }& o. m
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |: @1 d6 [+ e5 O1 s f! t, t
- RCC_CFGR_PLLDIV));; C. e4 W: H. X) d
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);% j2 F' A6 f# |8 A! z! ^
- RCC->CR |= RCC_CR_PLLON; //使能RCC+ V$ P }0 u/ b' v
- while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定% m. ~0 H8 [) |1 t7 S9 G$ F
- //选择PLL做为系统时钟 - |. j/ h5 s0 g# V' Y
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
; V% x1 v; z3 H - RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; + l1 |. i- _! z `9 f" i. P( Q
- //等待PLL稳定6 f# X! q l; f; o
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}
1 p( ?+ h6 U) P8 K: P# Z; a - //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA) A5 W7 C5 ^3 Z9 t
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码 / q- H7 d# j {& L3 p
* o- D1 m! k4 s& y9 V
) }, f9 A! ^2 Y8 C f6 g7 i
|