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

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

[复制链接]
仙人掌 发布时间:2014-4-19 11:11
      本人一直以来都在接触STM32方面的软硬件开发工作,最初的是做基于STM32F1的汽车电子相关的软件研发工作,有用到F1的一些基本功能,例如USART串口通信,IIC存储EEPROM芯片,SPI读写FLASH等等,内核的SYSTICKNVIC,中断,强大的定时器功能也总是用到,尤其是CAN总线,其稳定的工作机制和强大的纠错,适应能力,最适合汽车电子等工作环境不稳定的场合。最开始的这些研发工作使我对STM32情有独钟,其强大的外设资源,能满足绝大部分的应用需求,丰富的系列产品,能满足预算和功能的协调统一。
: K# K" y( @& q' r/ N: A1 H7 \. S      有了一些基础之后,我在网上看到了STM32F4 Discovery的出现,高达168MHz的主频,1M的片内FLASH192KSRAM,内置RNGFPU等等,并且包含了F1系列的几乎所有功能,尤其支持USB OTG,强化了音视频解码,能做出更多的功能和有意思的探索。接下来就STM32F4 Discovery官方开发板,本人自己研究的一些过程经验和体会,分享给大家,限于本人能力有限,仅代表个人观点,还请大家多多指教。
* R! H$ ]) M7 m; B   首先,对于开发方式,本人采用“MDK4.72 + 寄存器”进行开发,首先,此版本的MDK(keil)有在线纠错功能,让你能时刻看到自己写的语句是否有问题,虽然有时候的软件提示有少许BUG,但是瑕不掩瑜,还是很不错的功能,其次,新版本的MDK支持的芯片更多,可以方便你移植代码到其他平台上去。再就是用寄存器方式开发,这个纯属个人兴趣,我的方法是:比如我要写某个功能,我会先看官方或者网上一些高手写的库函数的代码,慢慢去分析他们的思路,和一些初始化或者配置的过程,最后总结出一个规律或者套路,再去看芯片的手册,找到相关寄存器,分析用到的每个位的作用,写出寄存器配置的代码,这个过程虽然枯燥无味,却能真正然你理解其中含义,非常清晰的看到一步步配置的过程,不会在云里雾里,所以我采用寄存器方式开发。这个适合时间充裕,想真正了解和学习内核的人。当然,萝卜白菜各有所爱。相关寄存器配置资料:
  m* z# d+ O: J) u0 K# z3 sSTM32F4_DISCOVERY    --   官方开发板的说明手册,外设介绍等等
" h5 s! W8 Q" |! E/ M* [, RRM0090 Reference Manual  --  寄存器手册,也是寄存器方式开发重点要看的0 l, `! }  C& y3 E. M$ A
STM32F407数据手册        --   主芯片STM32F407VGT6的手册,主要看管脚对应功能,外设配置简介等
% K/ ]. {2 i: L) E% d: ACortex-M4 Devices Generic User Guide  --  Cortex-M4内核手册,包含NVIC,SYSTICK等等内核的详细说明
8 o3 E. K7 K3 k8 J# X! o/ b还可以去ST官网下载3.5的库函数,以及STM32F4 Discovery板的例程,经常看一看,借鉴学习下,非常有好处。# R- u  i: Z( f
F4系列和F1系列的寄存器有少许差别,大家使用时可参考F1的相关例程,对照修改即可。. `; x+ A4 }. ]# w, `3 k9 n
2 g1 u+ }" i. c* p. N
以下发表一些自己研究过程中的心得体会:若有错误,还请指正(以下代码均对应官方的STM32F4 Discovery板子,部分代码仅贴出最关键部分)
; A4 F" |# p# {, I! W+ P一,IO
: |8 |# H1 S) h& c. ?$ X最开始莫过于控制IO口的电平高低了,从这里开始,F4的寄存器就不同于F1,例如初始化LED的代码:
9 B- [9 \8 O; Z" y6 U6 ^//PD12:绿灯,PD13:橙灯,PD14:红灯,PD15:蓝灯
- |  f8 s# t1 M' ~1 @void LED_Init(void)
. M" F2 f( Z4 i- H1 E4 C9 V{
0 I7 l2 l9 F# J& \   RCC->AHB1ENR |= 1OTYPER &= 0xFFFF0FFF;//设置PD12,13,14,15推挽输出
( E9 K' @, k9 p6 o$ j  GPIOD->OSPEEDR &= 0x00FFFFFF;//PD12,13,14,15速度100M1 p7 n8 |' l/ A7 Y+ v  E6 X9 ]0 A, P
  GPIOD->OSPEEDR |= 0xFF000000;' M" H& H. U. y9 c( e! @
  SYSCFG->CMPCR = 0x00000001;//GPIO速度超过50M的时候,使用IO补偿单元   4 ^1 k& g$ @$ |
  GPIOD->UPDR &= 0x00FFFFFF;//PD12,13,14,15无上拉无下拉
* A% n5 p& K1 g  GPIOD->BSRRH = 0xF000;//配置完成后使所有等保持熄灭状态
0 E* N3 \9 ]& a8 |& I  @2 w}
6 T4 o6 j% N. p3 ]% \配置过程:2 v/ u9 W7 A  J
1,开启GPIOD时钟 2,配置IO为通用输出模式  3,配置IO为推挽输出  4,配置IO输出速度  5,配置上下拉模式  (其中,使用IO补偿单元不是必须,只是官方历程中写到,实测不加此句也可以)                                                                                                                                 2,相关寄存器为:GPIOD->MODER      GPIOD->OTYPER       GPIOD->OSPEEDR       GPIOD->UPDR3 t, }' @: e; I, f
二,USART
3 {  Z6 a' C1 T  g6 k+ `3 [2 eUSART串口也是调试过程中,或者以后产品运行时与上位机软件通信的手段之一,十分重要,可以官方的开发板只有micro USB接到了USB OTG,虽说也可以配置通信,但是太复杂了,本人还没调通,暂时用把排针引线接到其他板子的USB转串口的芯片,再连接到电脑。+ @$ _, k  g0 ?: W
注意:一开始我连接到的是USART1,也就是PA9,PA10,但是怎么也调试不通,一直在串口调试软件中显示乱码,一开始以为是波特率有问题,可是怎么也调不成功。后来我看官方开发板的原理图,才发现PA9,PA10已经连接到了板载的一个芯片上,可能是做USB设备的驱动芯片吧。所以我换成了USART3,对应发送接收引脚PD8,PD9,检查无冲突之后,仅更改引脚,使用之前的相同配置,调试通过。代码如下:
: f; i, c$ T4 z+ V7 fUSART初始化部分:1 l, L1 Z8 g- }3 ^* Y# Z
//初始化串口3
. r7 P9 a- v# n" U0 Q//USART1,6 84MHz  USART2,3,4,5 42MHz
/ E* o2 N! r3 o% Q: Y" e, U4 M4 \//波特率不通过参数传入,直接通过计算得到,并写入USART_BRR
- s& @: V5 @! v/ O: Svoid MYUSART_Init(void)0 ^6 o& H2 P" A9 r
{
5 V- g# W9 @- e0 w" \. k         //使能PORTDUSART3时钟8 ~- N0 a/ |0 u/ R4 K% F) t; n
         RCC->AHB1ENR |= 1OTYPER &= ~(1PUPDR |= 0x00040000;  //PD9 上拉
8 d* [: N; o  ~8 \: Z, M         //复位USART3
: p% l6 ?$ V, s% I2 q         RCC->APB1RSTR |= 1CFGR = 0x00000000;
% m2 n8 ?2 Z# K2 c* S  u  /* Reset HSEON, CSSON and PLLON bits */
, O$ M7 D# H  {5 F# s+ M5 g- l; }$ D9 B  RCC->CR &= (uint32_t)0xFEF6FFFF;
: ?, g$ d* r5 s) ~+ Z; p! M- w) s  F  /* Reset PLLCFGR register *// r- H2 C" U5 Q; M
  RCC->LLCFGR = 0x24003010;5 B0 `( `$ c0 x3 v
  /* Reset HSEBYP bit *// A* _& Q. P4 x+ B2 r4 |% a: d5 ~: V
  RCC->CR &= (uint32_t)0xFFFBFFFF;! M/ c+ N, d, s1 W3 d
  /* Disable all interrupts */
7 b; D2 l  v0 s7 m  n: [# Z- E  RCC->CIR = 0x00000000;& l9 U1 t' h7 _) }
}5 o- g. _2 b6 R- b2 b! f6 A
* Y+ `( ~$ p) _# E! F* Q- `  y/ U
//STM32F4时钟配置
4 k/ m% j! S/ e3 N//关键是粗体部分的参数配置,此四个参数决定了配置后的MCU的主频,进而决定了整个系统的时基' X; H" y/ A3 U! L/ I' l, S5 r1 b" `
//配置完成后系统主频为168MHz,注意,板载是8MHz晶振,所以要在MDK的设置里写为8
. @, L- F6 O6 M' g* u5 J. K//还需要在文件stm32f4xx.h中第92中把25000000改为8000000  ]$ }4 t' Q& @+ ^( r+ }0 z
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
& Q3 u% I0 y" x7 e#define PLL_M      8
2 _( i) l% e7 u9 s4 d  Z4 ?3 H#define PLL_N      336
  g1 L( G1 Q5 l6 C' e3 w9 t/* SYSCLK = PLL_VCO / PLL_P */4 M  h. h: \7 r: K
#define PLL_P      2
6 K. V; B/ s# X# v* q1 D6 \$ u/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
- z  c# _2 c/ `0 Y: \. i) f#define PLL_Q      7* T" D  k* q( ~
void F4_Clock_Init(void)/ W6 f4 f' o' g9 k9 i
{  L! X+ x# f0 b( {% ]! Y; }
         /* PLL (clocked by HSE) used as System clock source */9 a/ l5 J4 {0 F9 @" J( o
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;6 e% `; Z# A4 D6 F8 \. @
         * a; V, z3 b. ]4 K% v9 W1 ?7 ~
         F4_Clock_DeInit();
% e% \3 a6 [$ j3 v7 G3 t         1 I- {1 m$ r% ?5 x) N! s2 K
         /* Enable HSE */
* ^9 j" [* u, D" o, j  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
0 C/ n* _" U+ p* ~: a- V         ( D/ ~9 f' S/ A1 `2 \
         /* Wait till HSE is ready and if Time out is reached exit */0 Y" M/ l+ @) U: U" I
  do
4 o6 q) g, R8 G3 R' w8 n  {# h! g) e" b8 F. t
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
% l$ N. l6 h& N: p* ], A! W    StartUpCounter++;. \" b( |4 m) e6 S7 O- t7 j
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));! ~* N# Z; v8 t& K: [+ p' M% o, ^5 p
         
/ e4 X, l" V+ o- b7 o         if ((RCC->CR & RCC_CR_HSERDY) != RESET). l, W7 Z: M- `6 o' s1 \) z" Q
  {9 _- t8 W/ `. y8 `
    HSEStatus = (uint32_t)0x01;. q$ t6 z( ^  b& k+ }
  }
( `+ G- M- k$ y$ i1 {# x% L' W  else
. w$ Y! `9 B  q, f  {
7 O) U! W: T1 J6 o    HSEStatus = (uint32_t)0x00;6 b, L, [7 u2 k' W! i1 q$ w5 `
  }1 u6 d' v0 Y2 Y' e8 [

  F( u. d' v: o, N  if (HSEStatus == (uint32_t)0x01)4 v0 N# Q9 ^/ m& o1 Z$ o
  {1 g; c, K0 m; i; _9 T$ G
    /* Enable high performance mode, System frequency up to 168 MHz */) c8 S/ n# N! d) ^$ \$ `  Q
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
, r; B  U8 ~5 b( y- f    PWR->CR |= PWR_CR_PMODE;  
) v% M& l. d' F5 a, N% ] ) S" {$ c; ^  ^& f# O
    /* HCLK = SYSCLK / 1*// r  }: J  L: r) y5 j
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;* R- `) M. ~" l# U8 v: b) D
      # [5 F2 H7 Q' z/ n. n+ C3 V
    /* PCLK2 = HCLK / 2*/
2 B* f6 e3 Q" T9 n0 A. A    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
  B6 y; |+ P: X    # u! q( _9 J+ C9 O. i9 @
    /* PCLK1 = HCLK / 4*/
# Q3 U- \5 v& i" e    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;: ?8 w' y0 _3 [% P; b

5 q  `- F" I+ _4 g    /* Configure the main PLL */9 @2 Q" `! d- A7 \7 }% n& U7 M8 w
<strong>    RCC->LLCFGR = PLL_M | (PLL_N > 1) -1) CR & RCC_CR_PLLRDY) == 0)
+ D; Z/ Y' A; {9 k    {
  @0 T( R# O) C8 f    }
) e* W; F- T8 ]' x* R  g                   4 H! ?" j" n0 N9 i+ j
                   /* Configure Flash prefetch, Instruction cache, Data cache and wait state */% e7 ]3 v# u+ B# B* z: z& i- m6 t9 }- }
    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
7 \# o6 T5 I7 R6 W7 X# A : ~  {/ w2 r. T: r
    /* Select the main PLL as system clock source */
9 S3 C6 m% }, K3 L" R6 |  K. G    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
6 v6 h3 W5 o, g0 [    RCC->CFGR |= RCC_CFGR_SW_PLL;
: G0 e: H, |; P6 O7 i4 _! J
1 c+ j- J& ]# U    /* Wait till the main PLL is used as system clock source */
/ X* @4 u  v- o2 O# s" E    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
. h) Q: |% N0 I7 v: n/ n: Y    {+ O5 x1 Q% |/ C2 w/ Y" Z
    }/ A( L3 L% T- c6 `
  }: D  z( C5 J7 }  S7 v5 e9 P
         else& J0 V3 B4 Y7 M! s
  { /* If HSE fails to start-up, the application will have wrong clock
# Y% {: `, y' U" b         configuration. User can add here some code to deal with this error */8 L: b* v5 O# _! u/ W5 r! `
  }: o! J. y) v* Z6 V/ J! l. b$ H& V
/ T3 I+ y, @8 o3 c8 _0 P( g

9 d" I7 s( X+ u2 ^# p! V% g说明:以上是初始化的关键部分,SYSTICK频率默认为系统时钟的8分频,配置好了时钟,自然就可以轻松设置SYSTICK了。
: v$ p- `1 L1 }5 c& M; T9 K$ x5 w5 X) x四,定时器 PWM 输出
4 Y6 p0 j4 c0 T  gSTM32的定时器很复杂功能也很多,此处仅说说TIM4作为PWM输出时的配置,效果是控制LED产生呼吸灯的效果。                                  此处仅配置TIM4-CH4的输出,其余几路输出同理:# l2 U6 b9 w2 j/ {: g
//PD15 BLUE   TIM4-CH4, v7 d8 @+ ^5 e6 `. j+ [8 m0 h0 h
u16 TIM4_CCR4_Val = 0;8 k6 p7 e; B7 u& }( h
u16 PrescalerValue = 0;//预分频器值
0 {/ `! @- |! F% [u16 pwm_tempvalue=1;
! H# c! g, ~6 [. ^//TIM4-CH4 PWM输出初始化
) T( _, d. g, U# r- B//必须对PD15的IO口进行重新配置
5 R8 c: X3 b, |8 F2 c* jvoid TIM4_CH4_PWM_Init(u16 arr)0 T  F$ O6 g; u# S; R( P, V6 i
{9 `; V8 \/ w2 G4 J. H$ Q
        //TIM4时钟使能
- K" S9 i" _! k9 t        RCC->APB1ENR |= 1OSPEEDR |= 0xC0000000;
! c0 |! j3 ~% i, y        //当速度超过50MHz时使用IO补偿单元" {# U: \: ?5 b& ]/ k7 G
        SYSCFG->CMPCR = 0x00000001;) v% P/ l+ d& X# T- Z1 b9 d
        //PD15上拉,PUPDR15[1:0]即31,30位  01ull-up9 J* C) n" B2 O5 [- s' Y) G' G
        GPIOD->UPDR |= 0x40000000;. Y8 y6 b: n% L4 S, I9 F
        //配置第二功能寄存器(必须开启),PD15对应GPIOD->AFRH: d* I" O& P$ V: L9 S8 `- X
        //31,30,29,28位 AF2:0010
9 Z' E- c3 @0 L4 X: [) s3 a# e        GPIOD->AFR[1] |= 0x20000000;7 w/ o5 O" b+ `% C: s' ^- u
% c, f" V5 C2 j) p4 S4 Y% y
        //计算预分频器值5 t% _+ ]" X% h! Z5 u
        PrescalerValue = (u16)((SystemCoreClock/2)/28000000)-1;        
9 `( X6 m0 z, E        //设置计数器自动重装载值1 t3 O1 _$ R! {7 {
        TIM4->ARR = arr;% I3 ?. M! u% E- Z! ^( A. Q( N) u( i
        //设置预分频器分频值* M; K2 m$ W# r' v% t' v7 O
        TIM4->SC = PrescalerValue;
2 c4 `& a/ x) o& p; I' K+ N        //时基配置:Bits 9:8 00:t(DTS)=t(CK_INT)! j: M/ h# n6 _: U- S  _
        //TIM4->CR1 &= 0xFCFF;+ M7 @6 n+ I' _  i. I: R. Z
        //计数模式配置:Bits 6:5 00
3 g, _6 ?5 `" H+ Z" N8 ]/ ~3 e        //TIM4->CR1 &= 0xFF9F;        , k- o/ d% b  ]  l% R8 o
        //配置TIM4的CH4为WM1模式输出0 z/ D) E3 Z( B8 J( E; ]. V0 ^
        //配置TIM4_CCMR2的OC4M(位14,13,12)为:110
- ^: d! e/ e3 k7 A        TIM4->CCMR2 |= 6CCR4的值来该表占空比,从而控制LED的亮度
) x# o, f( O8 d% ~, f        TIM4->CCR4 = TIM4_CCR4_Val;! o6 @) ?+ r/ ~0 y+ R( B/ U9 |0 x
}
) y6 L6 f2 t- q* { , Y3 E/ C3 I$ f/ N
主函数中:* z) G& d: z& d7 i" k* T* u8 P
TIM4_CH4_PWM_Init(800);//TIM4 CH4 PWM输出初始化
0 B3 L9 e; O4 E循环里调用TIM4_CH4_PWM_OutPut();  即可
- W. ^0 K2 F7 U7 k# L
9 M7 O5 Q  ?9 o说明:1,粗体部分是重点    2,IO要配置成第二功能模式     3,延时控制了呼吸灯的节奏,占空比控制了LED亮和灭的范围,这个可以自己多次设置后调试体会。
2 Q- Z9 H) A1 O - R: O6 `  E) \9 R+ s, \7 V% w0 j
五,RNG 随机数生成器
7 X4 u" Z9 ]9 o+ k5 e0 j9 H" G2 U这个是STM32F4比较有意思的一个功能,可以硬件产生一个随机数,更加方便易用,配置也相对简单:( `0 k9 v2 ?8 u
void RNG_Init(void)//随机数寄存器初始化8 ]- T9 H! j0 m: i. f5 A3 `
{& T) O# h! s3 J9 @
  RCC->AHB2ENR |= 1CR |= 0x00000004;
# l- E5 F5 L& S4 Q! p  RNG->SR &= 0xFFFFFFFE;( t$ Z$ F. u# G# d7 u
  RNG->SR |= 0x00000001;  
1 c# g% T9 M+ R! ]" X% g5 E}1 V' B' N6 U* w7 f( _
: o  v( M) m, g4 z% Q
int RNG_Generate(int y)//生成随机数# a4 G" @3 \; N1 T/ ?- B
{
1 A* ]9 n3 L7 K0 I9 a  int x;  e0 W6 E' T$ F% @2 }
  x=(RNG->DR) % y;  7 r9 N8 ?# u4 L, X+ S+ R
  return x;
# i0 w7 w( l. e* r- ]% {1 e$ m/ b}
6 h" `4 O/ p. g/ |  ^说明:开启相应时钟,简单的配置几个寄存器,然后再main中初始化:RNG_Init()就OK了,若要在其他外设文件中使用随机数,包含头文件rng.h,然后定义变量接收函数RNG_Generate(int y)的值即可,简单易用。: }' L5 `+ \9 ~! C( v
------------END
) B0 d. @2 o( G$ d) m& a# s2 N对于STM32F429,我还是很期待的,比较自带了LCD,还有SDRAM,更多的应用可以被做出来,更流畅的跑系统和需要大内存的应用了,本想自己画个板子,接LCD,然后插在STM32F407 Discovery板子上的,可是硬件设计又是个难题,万一设计错误就无法使用了,所以STM32F429是个不错的选择,官方的开发板,外设丰富很超值。, f9 I8 A$ [2 ]  G- m5 z+ r6 U  v
以上是本人研究的一些东西,给大家分享,本人也是菜鸟,希望大家多指导,共同进步
5 V$ y5 i+ s- E! x6 `, s; G
收藏 2 评论4 发布时间:2014-4-19 11:11

举报

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

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

最近在研究F4的ADC功能,发现跟F1的寄存器不同,比如:# o' k, p9 L) c$ F
1,选择触发方式为软件触发时,F1的寄存器有对应设置的位,但是F4中我没有找到,也不清楚到底有没有?7 T3 q- i% U* s# Y
2,ADC校准,在F4的寄存器手册中找不到对应的寄存器的位,不校准,岂不是精度很差?! j. D' H' Z% ]3 P; A% W
以上两个问题,请教下大家!希望有人能发表相关意见和经验!
bjybjy 回答时间:2014-6-18 17:12:57

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

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