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

【经验分享】STM32F7xx —— 启动文件和HAL库

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
: U, C- U7 Y6 p% n    开发速度快,便于移植。% G+ [, C, D/ ?0 a# D' G  v
8 z( X' [6 l; s  j$ E1 m
二.stm32F7xx几个重要文件
" o8 |. C( i' I: d1. HAL库关键文件5 ?$ d) f% y( _
* t2 g& f' A5 B" _/ L! M/ v
B3RQ`@IJHBU@LHI4O{4C]NE.png

8 v  A; d) E# H) e9 p/ X# @! D5 T) N% s2 |  e# Y
2.stm32f7xx_it.c/h0 v6 W( \) O* l5 R: C
         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。6 ?/ y; _! D& G6 [% \7 j) G) W

* g' E! Q1 O8 a- a4 P$ E
% ~. F9 c# [7 l  M4 I9 a& \% g7 }6 c. s3 P2 B5 b* A6 _7 m" g8 ?
3.stm32f7xx.h2 K# p, T7 Z) _4 I  }7 Z
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。
  `4 ]+ p+ Z9 e' S! \: j
( u3 m" j: r! @4 |& _- F
  1. #if defined(STM32F756xx)
    # P: ~+ W5 P" t" J8 i6 a

  2. 5 T7 u. J% I0 U$ Z; f+ J
  3.   #include "stm32f756xx.h"
      z3 K7 K* @. Y6 c! G. d, }+ y9 V
  4. $ b2 u' C! w1 F4 c) E
  5. #elif defined(STM32F746xx)
    ! ?: O( V! E3 p/ D

  6. # X3 o+ J+ I" o8 O6 v% ^$ h$ k7 u. K
  7.   #include "stm32f746xx.h"
    4 N- X: c7 m7 h" p, L# t7 a9 y
  8. 3 _9 I% K" e9 D1 i$ Q2 X! }  }1 W6 k- C
  9. #elif defined(STM32F745xx)
    $ a2 s; g/ Y: p8 d
  10. : }& ?: B2 u2 U2 @. W
  11.   #include "stm32f745xx.h") d7 T9 u$ ~& N; c0 j2 W: _

  12. : o: s( h. l% k4 l$ D
  13. #elif defined(STM32F765xx)" K* T* F4 R! m& }

  14. / V- ?, M' J& i6 H! F, e8 O/ R8 G
  15.   #include "stm32f765xx.h"
    5 L/ D/ p. U- V8 h
  16. . I' H' O" X2 E
  17. #elif defined(STM32F767xx)2 R( ^% o% P. N" m& f6 u5 x3 U

  18. ; M, f6 c: |/ V
  19.   #include "stm32f767xx.h"6 z8 T3 N3 f, _
  20. 4 J/ ?+ p+ B5 `' y3 }
  21. #elif defined(STM32F769xx)! Q9 c1 a3 G4 J6 J! B4 b

  22. " }  `% d' ~% x7 h. f% f' J
  23.   #include "stm32f769xx.h"
    " y+ k2 m5 G# e2 Z

  24. + y/ f6 e5 O* t  ]) J% q
  25. #elif defined(STM32F777xx); I. @5 l. |! @/ ^4 J; b

  26. " L% c( r" R2 r& E3 Z) Z7 F
  27.   #include "stm32f777xx.h"
    4 ]( p0 ^# a2 k3 W1 {4 K

  28. - c- V8 ]" l( C3 e0 w
  29. #elif defined(STM32F779xx)
    % y4 b' ^- r( S/ G0 p0 d4 d+ a

  30. 6 Z$ n  I0 L7 @& G- w) w) K( C
  31.   #include "stm32f779xx.h"
    & z' A( T- `6 w* g0 C9 o2 t" Y& C& g
  32. % ?% z$ R3 Q0 ^1 I# ~' i( h5 [3 d
  33. #else3 f4 q' V7 G5 P$ J) A6 F8 E( O
  34. 2 L0 }8 ^( v5 V3 w
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"' t- p) ?/ d9 w  }# U

  36. ' ^# F: R0 ~1 p
  37. #endif" U( D% l& w' x
复制代码
5 D! s  x, S# X5 X  o  G. n
4.stm32f767xx.h2 W1 j. Y  P4 q- a  Z4 h
         主要就是寄存器的声明(一堆结构体和宏定义)。
) y7 w) X; m, q: h& ?7 ?7 K
+ m# B' ~# L& r4 N  Q5.system_stm32f7xx.c/h$ N* ?" g. ^* K! Q3 Y
         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
' p1 O% A! z0 ^1 z) M6 s3 n" \6 w+ W3 v3 Z  r$ n
6.stm32f7xx_hal_msp.c7 I4 ]5 u% W+ g' V/ J( R
         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。4 h' p+ ]+ b, ~

. |7 z/ H. q+ a+ F% L- x- \7.startup_stm32f767xx.s: u% Z1 w- N1 m% ~/ v7 ~
启动文件,上电先运行SystemInit,再运行到main。
, g! w' X! v, O0 f
7 [6 v: p9 i8 c2 b1 I  H" \
  1. ; Reset handler* U. T! ]6 C8 ~: D0 a

  2. " {5 [8 w: b" T9 J( W: _
  3. Reset_Handler    PROC& ]( b8 b, o& J. B2 F
  4. / J; O; l. U; v! H& h
  5.                  EXPORT  Reset_Handler             [WEAK]% p( h- w/ Y- r8 W4 G" ?1 c

  6. 0 ^; v( {1 P1 s, r
  7.         IMPORT  SystemInit0 K  f6 k+ t9 i& H/ g! V. j0 [
  8. / N2 j5 _1 @5 }+ e4 p/ ]# e0 w' R
  9.         IMPORT  __main6 e/ g% Y5 s6 M: }, |' w

  10. + k. I0 `( t4 E6 s5 d

  11. * S: f0 R' t, H2 L
  12. 2 ~6 `% M9 ^- |3 n
  13.                  LDR     R0, =SystemInit1 E6 G& `- ]6 @) t/ h
  14. * r* w6 Q# b( o2 }0 r; I/ X
  15.                  BLX     R0+ k% ^$ ~4 O" t6 X, g
  16. : U, g' p6 @; C  U5 p- h% \5 q
  17.                  LDR     R0, =__main/ ]. Z5 l" m3 E* T; x, |( s

  18. ' [6 q# y/ ?& W1 f% \4 {
  19.                  BX      R0
    ! ^  J: I0 U  P' }1 n: b: n

  20. 1 o+ J  Q; x# }
  21.                  ENDP
    ' G  j+ |( G$ |$ j  r' C. ~9 C! h
复制代码
$ e- g/ U& N) L( z0 q. U

/ c  t1 g( b6 H' h6 s7 [三.HAL库中__weak修饰符
7 k/ S# @% A$ F8 N         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
- I3 Q; X/ f1 D( ~/ |2 _
: Z8 F6 S7 i4 M; e6 P( A$ R# A四.程序的执行过程7 j* W4 O' M' s7 Y; A% Y9 S2 q" h
         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)
1 Y* @) v/ |) Q# _8 x+ z2 }4 u+ O& Q/ w
五.启动文件

# z/ ?  X& ]; k' C# ^主要指令:
5 S- i; D4 ]/ y$ |7 j; l  ?0 ~/ E1 E- Q8 a# x
N@)4NS$@S08L](`A7P41OFB.png
  I7 t: `. F* R. X) m( E- B0 m
`)LQ`K7K2(MYBG[7WDTIZFA.png

  n4 P7 q, z9 Y' w  S* Z' {1 \! y) o

) I. r# g9 m0 ]
% ?; o7 c) G# ~0 K: C' ^Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。  P  C* Z. r& ]/ A7 p9 x

9 R7 }4 M  g  b* w9 F) s, P+ r% yHeap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
6 B5 O* P( a; o
. p1 u+ E9 B0 z9 w/ B9 {- H/ K向量表——中断向量服务函数
6 V' R- s; A/ I- X$ s/ V7 p9 h- `* N9 `, @6 Q5 `$ r
复位程序——先进入SystemInit——main0 P) S: p! K# y$ n

' p$ `3 }4 s& W% I& A$ ~& Q3 k关于启动文件详细描述请参考:STM32启动文件详细说明1 y% q8 W9 y* S8 j
' q% l7 `9 N+ C
六.时钟设置(设置系统时钟)
" M* ?3 Q2 _. D: Q5 t8 I
  1. /************************* PLL Parameters *************************************/
    1 t( E8 G/ R" Z& W: h% u% W
  2. //时钟设置函数
    8 V3 Y" K; ]( J+ o7 p! j' ^' @+ H
  3. //Fvco=Fs*(plln/pllm);( V! o0 H9 \2 i/ L$ w7 m- [5 ~/ Y# w; D
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));' D8 z' N5 u6 }$ u; S& }5 v
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    * f# E7 K6 O  z( H/ w! I* V0 R4 L: b1 q

  6. 9 x  }" T" Z% q# q
  7. //Fvco:VCO频率/ |& d9 _# J* Q* G( [1 g9 n
  8. //Fsys:系统时钟频率
    / }5 Z( [8 I0 w1 V4 i  F  ]$ L
  9. //Fusb:USB,SDIO,RNG等的时钟频率4 ]- S1 t5 r' ~; F+ b% |5 E" U# c: K
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.- H5 r) w4 U5 P3 @: R
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.& `' y5 Z1 r2 y' ?  R' k
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.) V! {7 J  B- ?+ \& G3 B
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)3 S8 e! D0 J7 O
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15./ a' }$ y5 F8 r: a$ m( h, M5 r
  15. ! c8 M0 p1 U$ n; ]8 n  m
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
      G5 Q! h1 a& |" x( L: }
  17. //得到:Fvco=25*(432/25)=432Mhz- F  K/ m* s9 i2 c$ j0 T
  18. //     Fsys=432/2=216Mhz
    ; R, s& g3 n# i; c& A
  19. //     Fusb=432/9=48Mhz  q# w5 @9 y5 i4 k! f9 ?, v6 X8 a7 U
  20. #define PLL_M            25
    / t5 ?2 W. P! q
  21. #define PLL_Q            9* {  ]8 M2 l( b0 g9 n9 n$ Q% M
  22. #define PLL_N            432
    6 L6 m7 z1 o; a; [& k" b0 o8 V3 Z
  23. #define PLL_P            20 a. F. v/ m! N  s, S, @6 k
  24. 9 F* M0 v6 g; g" a, k
  25. void SetSysClock(void)8 \# U. \+ K7 f
  26. {/ Y4 i7 P; d8 I
  27.   HAL_StatusTypeDef ret = HAL_OK;
    , s5 O+ W1 z$ X, A
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;0 e1 t8 z1 @% h- }& F
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;: ?/ u* \( `% `+ U* O+ w& {
  30. $ k: v& \) D9 a8 i* q
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    & J6 i1 N" g/ n1 y/ ~/ b8 A( J
  32. * p; ]$ U* {6 Q( e6 ^
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE
    5 ~& j8 o( L! j- K$ i: R/ i
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE
    ! i" {+ ?- A+ e! t0 @. U8 V+ D( R0 Z
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL
    $ K6 L- k; R6 Q2 ~: @
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE
    1 A# F( L, V% k
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)8 K; `5 x9 G$ j! n5 x- i; v& H+ b
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    " C" Q$ D8 i, b+ q# _$ p0 w
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    ) N  `& p: o" n
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)) k1 Q/ H. I  c) `) K& @
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
    * j7 ^5 K7 E$ \0 a9 r
  42.   if(ret != HAL_OK) while(1);: d# y; Q/ [! v* G0 U) @3 O

  43. , {4 u. \1 b1 {2 C0 t
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能  ^' f, V' c9 f
  45.   if(ret != HAL_OK) while(1);
    ! i0 Z) Z9 O$ U' G, ^8 V' Z! _
  46. - G3 G, h4 m. L( x6 i
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
    4 ~, T, p  V% x6 F' b
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);4 M0 ]( a8 o/ X. p. m: m$ h
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
    ) f3 A1 W! n" y: N% B& g+ }' O8 `3 w
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为14 {7 n2 X6 X5 Y/ k  T" p
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为44 {3 b. X" j: D9 i! ?% e
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为29 c, x( ^4 V6 A" G
  53. 3 ?! ~" @. v  \- Z' W$ ]; Q
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。
    ; e0 t; {( T+ i9 R' b; w! B
  55.   if(ret != HAL_OK) while(1);
    ! d! }4 n+ ]7 o# B# U' [
  56. }$ @: F* K& P; E9 Y# J+ H6 w
复制代码

$ O' i# g" o* e( J0 s4 ?' m" _( ^, B$ C) C. s( H
9 @4 c6 Q: d% r/ L

9 I  C9 a& D2 A* z4 Y- D1 p  H- o$ b
赞 收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版