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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势0 x/ w; T; |1 T+ c  \, D# u3 V7 Q# E
    开发速度快,便于移植。
* g" s4 S1 a" [0 C( I1 H
! C5 V9 y/ |+ A% q4 @1 b# Q二.stm32F7xx几个重要文件: N/ i7 s- z+ N; y8 r
1. HAL库关键文件8 r/ ~7 ]8 j1 w' c

4 P) w3 a3 M( X; |3 x# C0 ]
B3RQ`@IJHBU@LHI4O{4C]NE.png

/ j; p' h( Q) ^# c9 r
2 m9 x1 Q* a- p2.stm32f7xx_it.c/h
: W" C2 s* y# Q         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
. x: O. a+ I! V8 @
: [& [1 \3 B6 W% n! y* y- O$ \8 r. F( R4 V$ l# G5 Z

4 ?; P4 u, ~8 l( R$ I3.stm32f7xx.h6 n8 S) e  s: I; V$ @; q$ f
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。
# Z' `9 y: x! T; ?& b* d5 r; P
! k2 ^9 G5 V0 w
  1. #if defined(STM32F756xx)
      p, `0 j9 s6 ^9 f% l

  2. 2 T0 e+ b2 w( L8 A! S
  3.   #include "stm32f756xx.h"
    # b# ]- f5 [1 U* Z( W6 R

  4. " ?# O% Z2 X  ?. n- v  D3 B% e
  5. #elif defined(STM32F746xx)1 v8 Z& s- X! t8 X5 {
  6. 3 m) u+ R8 Z7 _/ M. E
  7.   #include "stm32f746xx.h", d' i6 ~' h! d/ Y& H# D
  8. ! g9 o" n8 L; X3 e  Z$ B( B+ d
  9. #elif defined(STM32F745xx)
    + G) F! R' p* Q2 w

  10. 8 V6 P) I9 D6 x- a% s+ m- I: D
  11.   #include "stm32f745xx.h"
    % e6 @8 h) q! ^! N0 P' O
  12. 4 O* b- r/ m0 c" S; @
  13. #elif defined(STM32F765xx)0 N$ [; e2 R& a3 m4 ^' t5 A5 z2 J

  14. $ h# B" \5 `5 i1 p+ j
  15.   #include "stm32f765xx.h"
    ! C/ f8 o% `7 M9 u' t
  16. 1 Y' q8 ?  `- o
  17. #elif defined(STM32F767xx)
    2 x- w! W( s2 }  q2 Z( S

  18. 5 x- B1 F8 H5 e8 x; R
  19.   #include "stm32f767xx.h"3 ^8 V8 _6 J& L% u% h3 ?# n) A
  20. * j9 W' q; [  O
  21. #elif defined(STM32F769xx)1 u8 h5 L+ h" L' I3 g, l- B( m

  22. ' v, J6 ~: Y& c& F, {
  23.   #include "stm32f769xx.h"
    / S7 R( H2 O" j- C% D% O

  24. . K4 q& F' N! {3 _" v, f; K
  25. #elif defined(STM32F777xx)
    * ]! \' y" ^# `) Z
  26. 2 j4 n4 J8 i6 H& o1 I
  27.   #include "stm32f777xx.h"2 \0 K0 O, h3 X- z7 T
  28. - o/ w! H6 w  x0 ~
  29. #elif defined(STM32F779xx), U+ b7 H; n# D

  30. , V6 F* g$ U) ~
  31.   #include "stm32f779xx.h"
    + x, f' G) R4 X- K0 E% b7 I& A3 z

  32. ; S& H1 n' p' r. A1 e4 W
  33. #else
    / _' }1 q" c$ F

  34. ! a8 E4 t3 }8 b; v* B
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"0 _) P- \% a, C% E7 g
  36. 5 x& C2 X: ]9 r; b2 j3 u$ R
  37. #endif
    2 X4 J) ~( r  m: u) {0 D' @9 F
复制代码
( S$ F, a2 `" Y! d/ Y
4.stm32f767xx.h
  j8 F! d' k4 G2 Z- p: M  a2 j7 h         主要就是寄存器的声明(一堆结构体和宏定义)。# H9 g% z8 W& l
) M; v7 u6 r- G+ L! }; G
5.system_stm32f7xx.c/h
& f5 @3 I% }. k, }         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。  G7 q" q7 R/ K2 ?

' I& C1 q! z6 l8 Y6.stm32f7xx_hal_msp.c& Z3 T* ~1 y/ U$ e$ c4 }0 B( h
         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。
' ^' T) d, D7 d+ O2 p9 r
8 k' W, B* u1 N$ Q6 r7.startup_stm32f767xx.s
- `! `, Q& f3 p, F* w4 l+ q" _5 M' [启动文件,上电先运行SystemInit,再运行到main。
! j# @0 U, S& s) X# w* p
# G9 V' O7 l8 F6 `
  1. ; Reset handler9 _3 \7 J" Q& z
  2. ( W/ L. l4 B' Q) G' }
  3. Reset_Handler    PROC
    * k" W$ D2 j$ |/ _" U2 R

  4. ! Z- C# ~8 J1 v3 r+ D1 a
  5.                  EXPORT  Reset_Handler             [WEAK]0 w" m9 ]: D& w8 T/ g
  6. 4 r# h" i1 n" a. T9 z. S$ ^
  7.         IMPORT  SystemInit
    : h. b. K$ ?1 R( \. c! S

  8. / t) ?0 N/ G5 a8 ~' m0 g
  9.         IMPORT  __main
    4 R- A' V1 \4 l
  10. ' a' [- N3 ]6 a, T/ p
  11. 6 T4 M- Q6 b! W& r7 k

  12. 7 |. b5 C. Q) A% |% A3 {
  13.                  LDR     R0, =SystemInit6 E0 E+ I" \3 A5 o6 ?. W9 U

  14. 4 ]" i7 x' |8 e: ?% w7 x; G
  15.                  BLX     R0
    4 s2 ^4 `- e4 e# k9 E. P6 R5 x
  16. 2 {3 R: ?; e& F8 K0 {
  17.                  LDR     R0, =__main: m' o3 p/ ]4 @; `% T
  18. ' Y1 q( [% F3 @0 F! M: K) J5 e: y
  19.                  BX      R0' P4 e# H) C9 }/ S* E, N/ P: t- _
  20. 4 N$ T5 W. _6 e4 F% t2 A
  21.                  ENDP# j5 T% g4 M" S" B8 }! M" E+ [, N
复制代码

$ D: A4 f# d/ O5 U$ `  `: Z; Q! X9 {1 V$ }
三.HAL库中__weak修饰符. O) `# g: G1 q* }' Y
         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。. A/ I- I- o, ^- K/ O

1 }4 g& b3 A% K. O# @. z四.程序的执行过程
. E9 B2 J* n. N" p; W  D9 W         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)
$ `, h  `& i0 e5 c  [3 @! _9 Z, X/ @
五.启动文件
' @$ E; X- ^& m% o! v8 D
主要指令:2 D: |$ p9 B6 T
! a" g  ~/ K- L) M6 V2 ?. z
N@)4NS$@S08L](`A7P41OFB.png
- y' O* l) g7 k' }% H
`)LQ`K7K2(MYBG[7WDTIZFA.png
- d. R* j. E# i+ t3 h! x/ @; K" q
, U" F: F# m; y$ w) M9 X6 ~
8 Y" k/ ^) k) K. y- w* ~1 |1 d
4 q! r2 O1 ?5 Z5 y$ p" U
Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。( }  h8 l! q/ t# r; g
; K) i$ `5 E* k" v: P7 H, {4 x0 M
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
3 N: x3 |- m2 n: A
6 Y+ f" A. K0 I0 ~向量表——中断向量服务函数6 M- s: l3 N. e) }2 p

- e" f7 ?+ H7 e9 e" {复位程序——先进入SystemInit——main. l( @6 F0 n$ a& _2 R/ Q3 d

9 D1 |9 f7 _0 J" O" T/ Q关于启动文件详细描述请参考:STM32启动文件详细说明
7 n% _. Q  }! D  Y: c
3 P5 `" J# t9 n; w六.时钟设置(设置系统时钟)
5 L6 d( B# e. [6 b( c# p
  1. /************************* PLL Parameters *************************************/
    2 H: \- F5 V1 _) F. N7 Y( |# l
  2. //时钟设置函数  N) C0 D1 q* T" \+ K2 R
  3. //Fvco=Fs*(plln/pllm);: d2 ], q( j, U7 U; J& I! ~
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));" z5 |. b  G; \
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));$ w4 L) z$ k$ q. p" l2 L; S$ e

  6. & P0 W; ?5 g" f1 t( t
  7. //Fvco:VCO频率$ q6 E4 f; G" j9 }! m; I+ z! b
  8. //Fsys:系统时钟频率
    2 g/ t' _8 V3 L. C4 u* L
  9. //Fusb:USB,SDIO,RNG等的时钟频率
    2 P9 ^) D4 Q: e: U7 N. Z7 J: z
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.  K$ E7 [( O6 J" D
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.# d. K* j; S( T; T0 p
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    2 E* D: `- R/ ]2 ]
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
    : M1 ~/ l  S0 g7 k5 w% `" l: ]
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
    4 I1 [! W5 @; l+ g0 E7 o1 \

  15.   H0 L0 M9 l5 O# a1 B
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    4 E+ I+ O. }  a! B0 h) S& x: u
  17. //得到:Fvco=25*(432/25)=432Mhz4 j( v5 f3 W6 z$ X& E6 X
  18. //     Fsys=432/2=216Mhz! @, P$ B% J9 q0 Q0 w: m1 k: y. T
  19. //     Fusb=432/9=48Mhz0 Z# v% R2 V& P! C. |) i
  20. #define PLL_M            25
    * Q6 P3 x0 f1 O
  21. #define PLL_Q            95 {3 L; B  s- ]
  22. #define PLL_N            432
    0 e6 B' c8 M! x) l: J) b4 }
  23. #define PLL_P            2. n% i; v! ^% w) u- ]
  24. : P, J2 ^; f1 ]# }+ ?/ R6 R
  25. void SetSysClock(void)
    8 {& _# j% k' l" B( B
  26. {6 F4 ?7 j* t& k+ @2 H% r  q0 y. ]
  27.   HAL_StatusTypeDef ret = HAL_OK;4 E& I9 }8 F5 M- a
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;
    3 H; w6 c. c4 N, `- L: _! O
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    # }* W, k% o4 D) I* j5 B  @7 }

  30. % b+ x& e7 I# m2 I6 e
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟: @0 v  @! A2 R0 b1 H

  32. , k( X5 }* l- A( ~/ O9 b8 E
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE
    / p  ]% Y0 v/ a, m
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE, x, J1 M8 o! F7 z7 w3 j
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL
    0 Z1 h( D! E9 q
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE& `$ f5 J8 F+ G6 Q" U
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)! u' W* b. }7 R0 D' ]/ s
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    ) R3 ?0 h0 w! K; O
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    % v9 Z' ?# V, H; g
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    + W0 z4 n* j1 z
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
    / t" z2 C+ y1 F1 e* L! t& w  ^3 z& E
  42.   if(ret != HAL_OK) while(1);
    . C+ s9 e2 x( T' r% @- j. \
  43. ; M1 f- Y' x2 ]
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能# g$ o/ p* t  T% k; ?, u: j* t* v
  45.   if(ret != HAL_OK) while(1);, E; E/ f$ w3 U) s) Q
  46. " x, }, H9 }& j8 m& M
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
      @1 h# o/ O) [' A
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);/ w' e" ^; t4 H0 P: D
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL: v8 R7 l5 r* ?
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1
    5 E, A$ X+ `  k) X
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为47 M' i7 |/ m( h) K6 i+ c/ z
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    5 Y1 t4 \) l6 p# U3 `9 K* s

  53.   L1 G9 K2 t. n% C: Y1 r" G
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。
    ( d& w* ~2 i! p& B* q0 [- b
  55.   if(ret != HAL_OK) while(1);+ S* L% c: ]$ B7 s: l8 i
  56. }. w. c0 f* N7 h( B& m
复制代码
2 f! ]5 K2 r, B/ m4 K  g

, M& \- e3 ^& s0 b
9 o5 I+ \. {: _5 c4 E7 c5 G; _$ j3 L, _3 A' k; J9 `4 F

4 f% ^/ t* i( s' F% c3 ~: Z
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版