STM32L1开发心得(一、RCC/PWR篇)
; y L: G! e$ m ^7 y0 b) ]: K- 因为电压及功耗方面的要求,需要从STM32F103将程序移植到STM32L151上面,以下内容就是程序移植过程中的心得体会。' U: B* v' |2 k$ A) s
- STM32F系列的应用很多,网上大把都是F系列的经验文章和例程,但是L系列的文章就很少,尤其是中文的资料就更少,所以使用L系列最痛苦的就是必须啃英文资料,这里写的开发心得就算是为同样英文不好工程师参考吧。7 L# V1 |2 v' Z4 V. \4 P. M& ^
- 本篇主要说说RCC/PWR的配置。
$ V. Q) `7 Z7 h3 T+ P! S" Q/ w! P0 s - 与F1系列相比,L1系列有以下几个关键地方不太一样,需要特别注意:. m! `! A' M; V" A+ A+ M5 M
- 1、 L1系列的最高频率只能达到32M3 L4 e" r1 o x# D8 D' l& M
- 2、L1系列的HSI是16M的
+ L# G+ ?3 ?: `& E- \3 l - 3、L1系列的内部RC振荡器除了HSI外,还增加了一个MSI,但MSI不能做为PLL的源% z# G8 j/ J' ~4 q$ [' u
- 4、MSI提供了从64K到4M之间几种超低频率,特别适合那种不能睡眠又没多少事干的节能应用场合! _4 c O c r \# h+ i
- 5、内核电压Vcore是可以配置的,而Vcore的不同也影响最大工作频率和FLASH的配置3 I, _' w5 c c# U5 E# g* g0 D$ _
- 6、L1的最低可运行电压为1.65V,用ADC或DAC时最低1.8V
8 a7 x7 ]7 u3 N9 V4 O8 m7 s Z7 ? - 7、某些外设的总线改变,比如GPIOA在L1系列被映射到AHB总线上
+ C9 @) K v; ]3 U' n7 q - 除了以上需要注意的事项外,笔者在调试RCC时,发现按照F1系列的通常例程修改后很难调通,建议编程时以ST公司提供的例程为蓝本,在此基础上修改成自已所需要的参数,以下是例程(HSI源的PLL):
' M2 T( a" p5 A/ w0 G5 K - RCC_DeInit();
" g& q. c+ r3 l2 U% ]& a - RCC_HSICmd(ENABLE); //开启内部晶振HSI$ _4 a& _5 m) ~0 ~& b* h: E
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待HSI就绪. i' J0 t% C/ O( a
- FLASH->ACR |= FLASH_ACR_ACC64; //使能64位FLASH
0 d4 b$ Y% k% P7 R4 }9 G - FLASH->ACR |= FLASH_ACR_PRFTEN; //使能FLASH预取功能0 \! p: S7 N5 S. D7 v7 A5 S
- FLASH->ACR |= FLASH_ACR_LATENCY; //1个等待周期( s% P% {+ D' C7 r5 O' v( T7 r
- RCC->APB1ENR |= RCC_APB1ENR_PWREN; //使能POWER
7 q: ?2 l) z! A5 |# R - PWR->CR = PWR_CR_VOS_0; //选择内核电压1级(1.8V)
9 \+ z, B; G! ?% x$ H* k - while((PWR->CSR & PWR_CSR_VOSF) != RESET) {}; //等待内核电压稳定
+ O: Q' X* c7 v* i& V - RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //HCLK5 O \$ s1 k1 i, _6 L8 w* e" y
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //PCLK2- w% A, A/ v! r7 y2 k8 j
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; //PCLK1
( D. a+ r0 t% Z - // PLL =16MHZ*2=32MHZ 0 }8 P' o1 B' N. a/ t, [
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |" }+ Q% _# u' G3 M0 {
- RCC_CFGR_PLLDIV));( W3 Y& V. i' C( L4 ?
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3);1 @+ a; Y2 _$ g9 W$ F
- RCC->CR |= RCC_CR_PLLON; //使能RCC& `* ]6 y( @( S5 i% a) {
- while((RCC->CR & RCC_CR_PLLRDY) == 0){} //等待PLL稳定5 J& _5 f. U8 c. Y7 T: `
- //选择PLL做为系统时钟
+ ^! |/ P) B; }. ], [. g7 K - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));( |7 F& x3 t; [' `3 `# i
- RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 9 v: a1 L; Z/ A0 [( O3 F
- //等待PLL稳定
O' d' P$ f, }- v2 N - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}9 s7 [' d5 I0 q- w7 }! W6 o
- //上面配置完成后,就可以将外设联接到时钟总线上了,比如联接GPIOA) h% ^( x7 u0 h
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码
j( @" L/ X* y2 k/ Y8 M9 Q1 D' P% }3 q1 e3 h0 G/ @
8 D: |( c* m- s1 \0 T) m- G |