你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【MCU实战经验】STM32F407 Discovery开发实例心得分享

[复制链接]
仙人掌 发布时间:2014-4-19 11:11
      本人一直以来都在接触STM32方面的软硬件开发工作,最初的是做基于STM32F1的汽车电子相关的软件研发工作,有用到F1的一些基本功能,例如USART串口通信,IIC存储EEPROM芯片,SPI读写FLASH等等,内核的SYSTICKNVIC,中断,强大的定时器功能也总是用到,尤其是CAN总线,其稳定的工作机制和强大的纠错,适应能力,最适合汽车电子等工作环境不稳定的场合。最开始的这些研发工作使我对STM32情有独钟,其强大的外设资源,能满足绝大部分的应用需求,丰富的系列产品,能满足预算和功能的协调统一。* W& y1 U2 N0 \1 K$ S
      有了一些基础之后,我在网上看到了STM32F4 Discovery的出现,高达168MHz的主频,1M的片内FLASH192KSRAM,内置RNGFPU等等,并且包含了F1系列的几乎所有功能,尤其支持USB OTG,强化了音视频解码,能做出更多的功能和有意思的探索。接下来就STM32F4 Discovery官方开发板,本人自己研究的一些过程经验和体会,分享给大家,限于本人能力有限,仅代表个人观点,还请大家多多指教。. q/ i: g8 I1 r  Z7 }
   首先,对于开发方式,本人采用“MDK4.72 + 寄存器”进行开发,首先,此版本的MDK(keil)有在线纠错功能,让你能时刻看到自己写的语句是否有问题,虽然有时候的软件提示有少许BUG,但是瑕不掩瑜,还是很不错的功能,其次,新版本的MDK支持的芯片更多,可以方便你移植代码到其他平台上去。再就是用寄存器方式开发,这个纯属个人兴趣,我的方法是:比如我要写某个功能,我会先看官方或者网上一些高手写的库函数的代码,慢慢去分析他们的思路,和一些初始化或者配置的过程,最后总结出一个规律或者套路,再去看芯片的手册,找到相关寄存器,分析用到的每个位的作用,写出寄存器配置的代码,这个过程虽然枯燥无味,却能真正然你理解其中含义,非常清晰的看到一步步配置的过程,不会在云里雾里,所以我采用寄存器方式开发。这个适合时间充裕,想真正了解和学习内核的人。当然,萝卜白菜各有所爱。相关寄存器配置资料:
9 ]" M$ h! C& g+ a) H& j" XSTM32F4_DISCOVERY    --   官方开发板的说明手册,外设介绍等等
- a& T" b( C+ E- jRM0090 Reference Manual  --  寄存器手册,也是寄存器方式开发重点要看的
2 [5 H5 Q  F5 X: ISTM32F407数据手册        --   主芯片STM32F407VGT6的手册,主要看管脚对应功能,外设配置简介等
3 B" U; r# y; s. ~9 G0 J, k% {Cortex-M4 Devices Generic User Guide  --  Cortex-M4内核手册,包含NVIC,SYSTICK等等内核的详细说明8 x' ]; T8 b4 I" ~9 g
还可以去ST官网下载3.5的库函数,以及STM32F4 Discovery板的例程,经常看一看,借鉴学习下,非常有好处。  [! E0 W. V0 e+ ?& b
F4系列和F1系列的寄存器有少许差别,大家使用时可参考F1的相关例程,对照修改即可。2 t) d& B$ W1 `
, H0 l9 ]7 K$ n0 F4 \; p7 ~
以下发表一些自己研究过程中的心得体会:若有错误,还请指正(以下代码均对应官方的STM32F4 Discovery板子,部分代码仅贴出最关键部分)9 ~5 e9 x, X" u) E, C
一,IO' ]6 n6 r# G1 x9 y. P( u
最开始莫过于控制IO口的电平高低了,从这里开始,F4的寄存器就不同于F1,例如初始化LED的代码:9 a$ i/ D! S. r" a: ~, n
//PD12:绿灯,PD13:橙灯,PD14:红灯,PD15:蓝灯
9 H& h" x2 j2 w; h1 w4 A9 }void LED_Init(void)
: [) U7 `! B/ I7 X( P& @{* N1 |8 a* d7 h! y6 y
   RCC->AHB1ENR |= 1OTYPER &= 0xFFFF0FFF;//设置PD12,13,14,15推挽输出6 e, w9 ~, c2 v3 o8 s! i: c" Z
  GPIOD->OSPEEDR &= 0x00FFFFFF;//PD12,13,14,15速度100M
# C6 M/ G" a) e, v; a6 j& L  GPIOD->OSPEEDR |= 0xFF000000;5 q9 _' N8 p8 h# u' ^
  SYSCFG->CMPCR = 0x00000001;//GPIO速度超过50M的时候,使用IO补偿单元   
" w  q) I2 ^5 ?# j9 z$ C& S' R  GPIOD->UPDR &= 0x00FFFFFF;//PD12,13,14,15无上拉无下拉1 }9 W9 i( F6 ^# Y1 `
  GPIOD->BSRRH = 0xF000;//配置完成后使所有等保持熄灭状态& D8 Y# v4 g9 N3 \
}: ~2 B( t; ?+ V  F9 |9 e
配置过程:8 \3 m) r# z$ b4 ~6 K/ q
1,开启GPIOD时钟 2,配置IO为通用输出模式  3,配置IO为推挽输出  4,配置IO输出速度  5,配置上下拉模式  (其中,使用IO补偿单元不是必须,只是官方历程中写到,实测不加此句也可以)                                                                                                                                 2,相关寄存器为:GPIOD->MODER      GPIOD->OTYPER       GPIOD->OSPEEDR       GPIOD->UPDR" ?% y2 N! _6 g: _* k
二,USART9 t- ]$ V& T" H" D% Z
USART串口也是调试过程中,或者以后产品运行时与上位机软件通信的手段之一,十分重要,可以官方的开发板只有micro USB接到了USB OTG,虽说也可以配置通信,但是太复杂了,本人还没调通,暂时用把排针引线接到其他板子的USB转串口的芯片,再连接到电脑。
8 ~# ]* o( r; V& v注意:一开始我连接到的是USART1,也就是PA9,PA10,但是怎么也调试不通,一直在串口调试软件中显示乱码,一开始以为是波特率有问题,可是怎么也调不成功。后来我看官方开发板的原理图,才发现PA9,PA10已经连接到了板载的一个芯片上,可能是做USB设备的驱动芯片吧。所以我换成了USART3,对应发送接收引脚PD8,PD9,检查无冲突之后,仅更改引脚,使用之前的相同配置,调试通过。代码如下:
8 p. D, [6 o) O% I, HUSART初始化部分:7 G( ~8 n; P8 b% [( T
//初始化串口3
4 m0 ^8 n  t; h  w4 k/ g% T//USART1,6 84MHz  USART2,3,4,5 42MHz7 }$ @# A8 `# V. y. H* @; X7 q
//波特率不通过参数传入,直接通过计算得到,并写入USART_BRR
/ [/ W; M$ J! E0 s" n* yvoid MYUSART_Init(void)- X' u5 R9 t2 [& n
{, G+ n4 b3 a) o& R
         //使能PORTDUSART3时钟
$ R: h; U7 t3 n, l" M         RCC->AHB1ENR |= 1OTYPER &= ~(1PUPDR |= 0x00040000;  //PD9 上拉 % f7 ?4 k- m+ R* b1 Y
         //复位USART3
9 F& @' D; E- R8 N2 F5 u# M         RCC->APB1RSTR |= 1CFGR = 0x00000000;0 E: |: l, v5 N
  /* Reset HSEON, CSSON and PLLON bits */
8 Y. U6 r( s$ J% v" x% _  O0 W  RCC->CR &= (uint32_t)0xFEF6FFFF;
+ i" Q1 D0 ]0 M- l+ ~2 A( ]  /* Reset PLLCFGR register */
2 h/ q7 T: T* v0 W# E2 K( O9 F  RCC->LLCFGR = 0x24003010;9 w) \0 M! |4 z% G. K/ _* h
  /* Reset HSEBYP bit */
9 M, [9 q$ c0 J6 ?  RCC->CR &= (uint32_t)0xFFFBFFFF;
  ^; k9 `6 m9 X) t& [  /* Disable all interrupts */
( O0 F5 C0 H( N9 s" t2 B, T  RCC->CIR = 0x00000000;
; J- s# |# W( _0 G}
; _# x+ M4 c  P* V/ X
, i" {$ g& ?6 c( |2 n, a//STM32F4时钟配置. [4 E" ?( t* s  S; @3 P
//关键是粗体部分的参数配置,此四个参数决定了配置后的MCU的主频,进而决定了整个系统的时基  x5 R5 M* O. Q. f( s4 V+ `# C
//配置完成后系统主频为168MHz,注意,板载是8MHz晶振,所以要在MDK的设置里写为8
1 d% A8 I" `  e$ |//还需要在文件stm32f4xx.h中第92中把25000000改为8000000
' l  g  X" x& |& j: V+ o6 P2 q/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */# U" ?' V1 G- Q) Y: r5 s1 e
#define PLL_M      8
: Z' U/ \8 l5 \2 Y#define PLL_N      336) _3 R* G8 {2 c# c
/* SYSCLK = PLL_VCO / PLL_P */
. I9 x* t3 D$ M# W4 v9 o( O#define PLL_P      2/ P  ^! a$ T4 n0 M# W3 K. L0 Q
/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */8 v7 c0 v5 @# q3 E, V1 S
#define PLL_Q      75 e3 X' C. Y( \* T3 B! w* l$ f
void F4_Clock_Init(void)5 r; w; t7 H& d+ J; \* _3 z/ x
{' j. z$ c# i: B$ V1 `8 J1 ~; y- e# D5 G" z
         /* PLL (clocked by HSE) used as System clock source */
  }) I! w+ u6 C+ c. B __IO uint32_t StartUpCounter = 0, HSEStatus = 0;4 ?6 }! c; i/ j1 y# a  l6 L
         4 a3 R$ T& `/ V
         F4_Clock_DeInit();
$ U* Y, [+ E  K5 a4 y& g         % x6 z% T: M' s& f) J: a
         /* Enable HSE */
" H; r/ P# h- B4 i  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/ j+ W$ P8 ]4 w8 s; K$ `         ( b; T; T8 T/ f3 X" [" G. p
         /* Wait till HSE is ready and if Time out is reached exit */
5 N0 i8 `6 m. J$ @+ f4 H  do- L% [% [$ D% M, |& [, I
  {* A  n$ |+ M, K+ i3 u2 e- q7 T
    HSEStatus = RCC->CR & RCC_CR_HSERDY;- e8 X, Y* `% g5 [9 Y  g% B
    StartUpCounter++;4 c( t; q/ [% i" ?
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));5 q: y2 H4 `$ p: i! [* z2 E* N6 P
         
9 Z/ l: y% _. u$ L* a" k6 p         if ((RCC->CR & RCC_CR_HSERDY) != RESET)& V1 L' z* G6 [7 R. S2 ]7 ]
  {
  u2 J1 D6 b: t& u7 ^8 D' W    HSEStatus = (uint32_t)0x01;; Z" B% d7 V4 ^5 z, S- e: ^
  }/ N4 ]1 g. J) a8 E5 H3 i1 H6 x
  else* z5 B5 [: B; Q9 m0 q
  {0 Q/ j" M. V& h5 C2 F
    HSEStatus = (uint32_t)0x00;( r0 ^8 q" A, d. S9 p: G
  }3 e6 d! E" x# g  N  O' A6 q
- ?1 e2 Q' F% f! B( a
  if (HSEStatus == (uint32_t)0x01)* W) ]" a5 J4 r, Q6 X
  {5 w' o2 \8 p; J- r( t. v) A) `& w
    /* Enable high performance mode, System frequency up to 168 MHz */4 P( I7 h0 R4 n$ o) i/ J
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;% Q4 D6 p4 A3 g1 w2 b  Q
    PWR->CR |= PWR_CR_PMODE;  1 r) J6 c; k! f3 d8 g
& s: t. R/ k  s2 y
    /* HCLK = SYSCLK / 1*/: l( e( _! t/ t+ q2 F% |: {
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
, Z6 r/ \+ S/ K      : H  o3 [6 ?) e2 ~1 }
    /* PCLK2 = HCLK / 2*/
1 E/ H& _8 J; D, t( X, R$ |1 [" i; H8 W    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;' `+ e2 j* ?+ i* _4 k
    9 i" g+ _8 ?0 L  f$ Q. G
    /* PCLK1 = HCLK / 4*/
! ~6 t5 f- d: ]0 H3 E    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
$ C' L3 {; y, e3 J2 V1 v7 k
+ [8 [4 h& [- ?' U2 n    /* Configure the main PLL */
0 z  J2 g) _/ V7 v: i<strong>    RCC->LLCFGR = PLL_M | (PLL_N > 1) -1) CR & RCC_CR_PLLRDY) == 0)4 n; M/ b8 }% A, o: V' J8 G
    {
+ R" H- R+ h/ O    }
' K1 o! ~/ O" j0 h+ J- b                  
, X  w1 `2 C* U3 R                   /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
$ q/ V+ w3 B& T# ~1 \6 k9 @    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;( d/ d4 X4 l" S4 `; Y1 U, j+ `
  j. W( l! c  Z1 d+ d- f. X
    /* Select the main PLL as system clock source */
; a) h+ h7 O& L2 z+ ]2 m    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
: a. E% s  U9 x# F) m1 B- t    RCC->CFGR |= RCC_CFGR_SW_PLL;
: B1 B8 i1 e: f+ D! o
2 A6 p6 ?0 `0 a( @9 D* y1 W# T, f    /* Wait till the main PLL is used as system clock source */
1 B- d! ^% a7 d5 h$ Z    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
( x' F( f! _$ }/ S# h. j    {
* U4 D( S" O* [: b# g$ `    }( y( L# Y1 w8 o: ~+ {
  }
2 e# V) }8 B; O" }! B3 [- {0 {& m( m         else
- _# h' N: v, q4 X! |; `: p- Y& K  { /* If HSE fails to start-up, the application will have wrong clock. J4 M3 g" X% F) O# k7 X
         configuration. User can add here some code to deal with this error */
% d3 x: a4 v0 _  }
1 S/ s. u- q* d* N% z# }
% t! q0 s& P' P  C  K" d
( x# H' a6 m, n: o$ E+ Q说明:以上是初始化的关键部分,SYSTICK频率默认为系统时钟的8分频,配置好了时钟,自然就可以轻松设置SYSTICK了。' t! H9 Z$ s) V0 z# _
四,定时器 PWM 输出
: u! R+ K6 P# |' zSTM32的定时器很复杂功能也很多,此处仅说说TIM4作为PWM输出时的配置,效果是控制LED产生呼吸灯的效果。                                  此处仅配置TIM4-CH4的输出,其余几路输出同理:
; ]7 e. U; l/ s) L! y//PD15 BLUE   TIM4-CH4+ O/ g8 t' E4 C- X4 \" W
u16 TIM4_CCR4_Val = 0;$ L% _! P' H" O; v0 E9 |9 \
u16 PrescalerValue = 0;//预分频器值
, c  e6 R; b7 z/ Qu16 pwm_tempvalue=1;
  y! ?( t4 K7 w" I& R//TIM4-CH4 PWM输出初始化- E4 M4 Y5 W& E. q$ r; l
//必须对PD15的IO口进行重新配置
1 d  s8 o" A  i7 i* b5 evoid TIM4_CH4_PWM_Init(u16 arr)
& d& O* W% s0 n' ]{1 e5 k2 C6 ?' e  a5 A* Z
        //TIM4时钟使能
& ~- e/ D! q7 o+ J6 [1 a        RCC->APB1ENR |= 1OSPEEDR |= 0xC0000000;: k' w% M! V9 u
        //当速度超过50MHz时使用IO补偿单元
0 @# B$ T) z. D* q% W        SYSCFG->CMPCR = 0x00000001;3 X  q; d. K0 ?: C
        //PD15上拉,PUPDR15[1:0]即31,30位  01ull-up1 A6 A! j5 T/ k+ @
        GPIOD->UPDR |= 0x40000000;4 E  O  s8 A. p1 M
        //配置第二功能寄存器(必须开启),PD15对应GPIOD->AFRH
7 ]; }( ?. e$ M" g; W2 a        //31,30,29,28位 AF2:0010
' i& s% n1 |) A        GPIOD->AFR[1] |= 0x20000000;
" m' G& P* H7 F9 H* S% X9 A( U4 w5 P, x
2 h6 T( C0 ~4 b/ n, P3 X5 W0 u
        //计算预分频器值
- f% r+ @7 c0 S  \        PrescalerValue = (u16)((SystemCoreClock/2)/28000000)-1;        + ]: p! o4 g9 G( p3 @% ]+ U
        //设置计数器自动重装载值
: S: E+ b0 s% b& m6 Y% _        TIM4->ARR = arr;
) i& `, N" E  M8 X        //设置预分频器分频值# C& w; B/ h5 G; M
        TIM4->SC = PrescalerValue;
; Q* |, s. K; B* ~4 N1 U1 ~        //时基配置:Bits 9:8 00:t(DTS)=t(CK_INT)
, r. @! b9 N4 u        //TIM4->CR1 &= 0xFCFF;
" g; E* j* O% W* r0 h( B3 N2 a+ r        //计数模式配置:Bits 6:5 00
' W8 _, G0 O, }+ s9 [8 D2 ]& u; y! F        //TIM4->CR1 &= 0xFF9F;        & \6 K# F( @/ ^, C5 T
        //配置TIM4的CH4为WM1模式输出/ s: c! z# k( ?! s8 d
        //配置TIM4_CCMR2的OC4M(位14,13,12)为:110
  ~$ c3 T( f2 c; |0 H        TIM4->CCMR2 |= 6CCR4的值来该表占空比,从而控制LED的亮度
7 {! Q' r5 x* G6 x$ g' y        TIM4->CCR4 = TIM4_CCR4_Val;
3 j, ^. t8 M8 Q0 i( |}
5 C) T0 \  u- {& u: y4 I/ u
2 C1 M3 x4 u( \& |- N2 `主函数中:
, m5 N- l% U; n% N8 qTIM4_CH4_PWM_Init(800);//TIM4 CH4 PWM输出初始化
2 E7 j+ J& I! I7 |$ @  Z" m' _循环里调用TIM4_CH4_PWM_OutPut();  即可
% I  H) j+ e8 F. E3 j2 ~" M1 {: r " ?6 @$ s, B3 {
说明:1,粗体部分是重点    2,IO要配置成第二功能模式     3,延时控制了呼吸灯的节奏,占空比控制了LED亮和灭的范围,这个可以自己多次设置后调试体会。0 i' p& B5 F/ o* y( m# b0 o

% o! `! O. A8 {2 c3 I0 K0 E$ E五,RNG 随机数生成器" B% n7 E2 J$ \
这个是STM32F4比较有意思的一个功能,可以硬件产生一个随机数,更加方便易用,配置也相对简单:
. H& P; [; V7 O# j9 {7 T" Pvoid RNG_Init(void)//随机数寄存器初始化9 S3 K! z, X. F8 \% P
{- r5 X* E2 D0 L) w7 x
  RCC->AHB2ENR |= 1CR |= 0x00000004;; R: }* G9 N4 h: V- a/ U/ G% F
  RNG->SR &= 0xFFFFFFFE;
+ F" r$ o9 z3 m# ~  RNG->SR |= 0x00000001;  
+ X$ a2 u3 r; i4 _  ?. G0 C}7 Q: F- q5 j  c4 T& T4 S
3 G* p  b. f5 I2 n, ~8 ?
int RNG_Generate(int y)//生成随机数" _" k/ Y1 C6 G
{
+ U- Q+ c! P1 T  int x;
  v0 H, _+ u+ X5 q6 i4 F  x=(RNG->DR) % y;  
6 U/ s7 {* l  K7 i) j! R9 h) H& n  return x;
* B4 I' u9 z5 H, l5 j: c}
- I, E- m. N2 b  U0 ]/ w说明:开启相应时钟,简单的配置几个寄存器,然后再main中初始化:RNG_Init()就OK了,若要在其他外设文件中使用随机数,包含头文件rng.h,然后定义变量接收函数RNG_Generate(int y)的值即可,简单易用。
* U% @7 v. z- E: f  p------------END
4 Q" t9 b( R7 j) |; a对于STM32F429,我还是很期待的,比较自带了LCD,还有SDRAM,更多的应用可以被做出来,更流畅的跑系统和需要大内存的应用了,本想自己画个板子,接LCD,然后插在STM32F407 Discovery板子上的,可是硬件设计又是个难题,万一设计错误就无法使用了,所以STM32F429是个不错的选择,官方的开发板,外设丰富很超值。
8 L$ T, B) _! u4 ^2 O, ]0 z* s以上是本人研究的一些东西,给大家分享,本人也是菜鸟,希望大家多指导,共同进步
& w6 A8 l, A# `6 r4 \& M4 x( [0 P+ i# m
收藏 2 评论4 发布时间:2014-4-19 11:11

举报

4个回答
仙人掌 回答时间:2014-4-24 21:25:40

RE:【MCU实战经验】STM32F407 Discovery开发实例心得分享

最近在研究F4的ADC功能,发现跟F1的寄存器不同,比如:2 q5 p5 c- h2 u* J) L7 p& a
1,选择触发方式为软件触发时,F1的寄存器有对应设置的位,但是F4中我没有找到,也不清楚到底有没有?3 k9 f. }9 W7 [  {# h
2,ADC校准,在F4的寄存器手册中找不到对应的寄存器的位,不校准,岂不是精度很差?
7 u! [, ?+ A; A以上两个问题,请教下大家!希望有人能发表相关意见和经验!
bjybjy 回答时间:2014-6-18 17:12:57

RE:【MCU实战经验】STM32F407 Discovery开发实例心得分享

楼主你好,请教一下,STM32F407 Discovery USART CTS/RTS该怎么用,谢谢
youxiaoxiang 回答时间:2014-11-24 12:44:44
楼主你好。看了你的PWM 输出 做呼吸灯的问题。有一点疑惑。# W' T8 D' W0 f7 O) @
具体是如何调节的?
巅峰残狼 回答时间:2014-11-24 13:01:16
谢谢分享
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版