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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
, g$ z) l+ U- }% S; r+ A9 H    开发速度快,便于移植。" r& z* F! K0 x( P% i" i- j
- L6 ?' B9 y5 N- _) p. ]; L
二.stm32F7xx几个重要文件5 P" U8 `. }4 ^! @9 S
1. HAL库关键文件
/ L1 G; {' Q" J9 M; X5 P6 r% m8 l. E7 a5 `7 f7 W
B3RQ`@IJHBU@LHI4O{4C]NE.png
3 v5 Z5 W( E) m& f4 E7 p1 t

' b: b" o$ K+ j9 \0 y9 n2.stm32f7xx_it.c/h
/ Q" `( \6 ^% E( w         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
/ t5 _: K- C9 K% L. l
2 B( j& `8 \' H2 x% g
5 p( c$ [: i3 A& I3 V5 _8 b, Q* W7 _: N7 \) v
3.stm32f7xx.h* p6 n6 I5 G$ Q" ~) _
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。& f% C/ t' k, z& r
- t: j$ K* X8 L" Y, I. ~5 ^
  1. #if defined(STM32F756xx), q% W" @# |# B; }. v% `. F
  2. 2 q" Z5 H" }2 u* G
  3.   #include "stm32f756xx.h": S: s$ e( F& X1 |
  4. ! E9 h9 t9 f9 h1 T* h
  5. #elif defined(STM32F746xx)4 P) i8 t* g7 S8 h/ @

  6. * Q- Z6 u  ^# B
  7.   #include "stm32f746xx.h"
    6 P- I* u' O' X5 Y8 C
  8. 8 c4 C1 x; c) S- B
  9. #elif defined(STM32F745xx)3 n6 [4 |3 ~4 i2 O* X
  10. * ]2 a* w) j" ^+ N2 f& H$ E
  11.   #include "stm32f745xx.h"
    # _# a5 k4 b+ k$ i
  12. . g' B: ^1 H( Q
  13. #elif defined(STM32F765xx)
    ' r' u. C. s) u$ N
  14. ) X/ g3 R2 S1 U7 W
  15.   #include "stm32f765xx.h"
    * g9 C9 r" P! X0 K1 [% f

  16. ! A! r% v9 F3 M' _1 A
  17. #elif defined(STM32F767xx)
    . o" z0 E' z8 z& T

  18. $ H: v. O9 M) J4 C8 k* f9 s
  19.   #include "stm32f767xx.h"
    4 l1 ?" I7 e  F" i0 Z: ?
  20. 8 e' ~. v( U, l) T& S" y2 c$ I* x; V, ^, v
  21. #elif defined(STM32F769xx)
    ! Z* u" o) I; [1 t

  22. 2 S0 r. |! N8 u: R! P5 R0 _
  23.   #include "stm32f769xx.h"2 D" s, @) H9 k% `
  24.   i+ |& _  Z' ?, P. i
  25. #elif defined(STM32F777xx)
    1 E* A3 }  M" \" j: V, M

  26. # O% ^, k7 v, O. }
  27.   #include "stm32f777xx.h"
    - q. f5 I; e  E: ?: d

  28. 9 s# @* O8 T/ N8 ?( A9 z
  29. #elif defined(STM32F779xx)* Q2 S/ M( O4 r6 ^0 e+ L# T8 s
  30. ' O# c6 a; s' f2 h
  31.   #include "stm32f779xx.h"
    # a9 k5 f# k' i2 Q
  32. 8 Q4 {! f4 V$ l. {' k- L& I
  33. #else
    # J  i( ]2 N; {! f, a5 R
  34. $ ~& a1 L8 S/ u+ L/ a% m( {; u
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"' x5 R( C" Q, d$ t! y

  36. 0 l' d/ S. Y  x9 z1 W( V+ e
  37. #endif6 e+ T. L; ~8 u2 n9 ]$ A% b% h  [
复制代码
7 k+ a1 b8 f. \3 I) _. x# Z+ {
4.stm32f767xx.h
2 }3 m* D$ c9 R- Z         主要就是寄存器的声明(一堆结构体和宏定义)。
6 w2 f) [7 Z9 W& M% Y
! G" v4 Y9 I" P, o+ X5.system_stm32f7xx.c/h5 B$ y( M: _! W/ R
         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。4 r/ ^+ ]1 n9 L3 V! ~
+ @5 {; A8 D; [, ^/ Q. J
6.stm32f7xx_hal_msp.c
, t) t" _2 C( D  W& W         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。7 A+ Y$ {1 l  e5 b( a' @4 t* b% l2 e

/ y  }) L  V+ T" u2 @! S1 U7.startup_stm32f767xx.s
. L3 ^0 O+ r: R4 N: j& ]启动文件,上电先运行SystemInit,再运行到main。5 Z- O& U0 P6 O5 r1 x3 ]; y* A) Y
2 `; y) e2 I6 N* f
  1. ; Reset handler
    # v" l' ^3 g$ N3 K' f" U% }- q2 M4 p
  2. 9 |2 {( l8 A1 q# @. k9 n+ ^2 }2 L8 D
  3. Reset_Handler    PROC9 P  y- ^) c" n; f& \! X

  4. # w; ^2 D2 b& l( p( O
  5.                  EXPORT  Reset_Handler             [WEAK]8 C5 r. b. j( i+ S- E$ j6 T  K
  6. 7 f: K0 @) N! H" X( X3 ?% ?4 D
  7.         IMPORT  SystemInit- Z  X  I( r9 s: o: r, J( g
  8. . T, \4 c  x# p& u
  9.         IMPORT  __main
    ' u1 o+ Z/ A0 J
  10. $ H+ E, n+ N/ _- i% s
  11. 1 M3 R* g% B* \5 p

  12. 6 S, O% c. A! J; r$ P" A0 |
  13.                  LDR     R0, =SystemInit
    6 D6 y3 V/ S9 |7 W' t8 `
  14. * g5 l0 a0 T' v4 q2 m
  15.                  BLX     R0
    % j7 I6 P$ D  V& p* v# S

  16. / ?( z4 Q" P3 R# _
  17.                  LDR     R0, =__main% I4 P8 i6 h; I+ ?8 w4 N* \7 Z

  18. : k: N; ~+ x! b; t9 ]+ @
  19.                  BX      R0
    + p9 g9 L8 n0 ]8 ]

  20. " E! y, F; }: w% i+ h- W3 J
  21.                  ENDP7 ~$ T  j& n$ e& [- p5 E" u
复制代码
% F1 `4 Q1 [/ q: z4 p

/ q3 P( d  k* z8 Q2 U! A0 g9 s三.HAL库中__weak修饰符
  W+ `4 {' Y% r/ p1 j, |         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
" l8 r* _; u! t0 L. \" K& j/ E8 y* Z7 y
四.程序的执行过程
' l! g5 w$ B; _/ E5 x  A         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate), ^1 p" \+ I4 ]- f
& x* {8 o: R7 P
五.启动文件
2 z% \6 j- [  u# [! ?0 M" x& P
主要指令:
; \+ M/ h. c' O3 x! |8 d& w7 Q
- B/ `& c( }- m* y* R3 V: x" O
N@)4NS$@S08L](`A7P41OFB.png

9 x" f5 L3 n; l& K% y0 G
`)LQ`K7K2(MYBG[7WDTIZFA.png

/ Q" G! o9 |& O5 A/ v4 B
3 q# r8 |2 X# v" V  ]; H5 U5 Q! b9 U8 Y0 @9 l
+ S; P; H  j$ i
Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。$ C5 |# H8 B2 y8 |$ I
9 f8 }4 g- V3 Q. ?* K
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
/ Q% Z, X  E% Z0 V7 X% ]. a5 m( z$ g
向量表——中断向量服务函数0 J5 t6 x5 L: o$ `9 \* n0 m8 s
3 M5 c# A/ i2 {( t$ |0 X% C2 L2 Q9 e1 G
复位程序——先进入SystemInit——main
2 `1 ^$ O! U/ w! N+ p- C: j) B' V5 C7 E# g$ H$ Q( H& c" k
关于启动文件详细描述请参考:STM32启动文件详细说明
4 y" |: V5 \7 W" ^* f5 }* i% X) q) g1 k. Y# x0 S3 b/ G$ y6 S1 t7 d
六.时钟设置(设置系统时钟)

* x# n% |3 c. }: e" Y5 f4 a3 R
  1. /************************* PLL Parameters *************************************/" O( n+ \- ^/ r  O6 J
  2. //时钟设置函数
    ; M( n5 D" A: {" s! x! w
  3. //Fvco=Fs*(plln/pllm);' F  r& h* i; V- Z  v- [$ X
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));- Q1 f) [" W6 e* f) c
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    9 K% d* _4 |4 q

  6. ! t) C( L: T7 H4 w, c: }
  7. //Fvco:VCO频率+ X0 o3 ]. Q, x' A4 S2 Q# A" Z
  8. //Fsys:系统时钟频率
    . J5 h, l% \9 n: M8 x
  9. //Fusb:USB,SDIO,RNG等的时钟频率# ^& ]* t# k5 v9 J# m
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.0 y- k9 _3 {1 ^1 F
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.  T  \$ `+ i% L/ L9 u8 D/ E  L
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    + q2 O, d2 T+ L2 n- c5 T( A  y, q
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)0 p* A3 m) P; S( L  Y
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.3 X* k+ z3 L* b0 R3 f" x3 D

  15. - S7 I# b; F# ~8 F
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    ) w# b; r" R: w6 p2 u0 [# X
  17. //得到:Fvco=25*(432/25)=432Mhz
    2 z' _* t- l7 [6 o6 B
  18. //     Fsys=432/2=216Mhz; u1 [8 _  N; X0 {
  19. //     Fusb=432/9=48Mhz; |) i1 o& x& X/ B
  20. #define PLL_M            25+ p8 ]& O5 {' w6 o7 ]
  21. #define PLL_Q            9  g, L% G8 n7 ]3 H9 \) d
  22. #define PLL_N            432/ @# Y: t- K7 p
  23. #define PLL_P            2
    ! V1 @% e% N' T# M) N" Z  B
  24. $ p" Q# ^$ k" m! J4 K8 p7 ~8 L7 n
  25. void SetSysClock(void)/ X; Z) \# W4 g! V) b+ s& ?
  26. {% g+ s! y5 Q; O3 r; @1 o
  27.   HAL_StatusTypeDef ret = HAL_OK;
    / z7 f" k6 Z( |+ g% H, g0 |
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;
    & J3 |- s. w" A9 k& {8 h
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    " o4 M2 j2 O4 E: J$ v- I# ?" X

  30. 5 z0 ]; j* S" d1 F( E
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    5 j  [' s3 ^3 [" l5 f
  32. & j' Z+ }4 V( C  g2 L4 ]
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE
    * G; z) |( Z# e! W
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE
    + k! b/ Y5 b, _8 {' Q
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL
    2 q( L/ ]: H% O5 \( U( O
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE
    6 R$ q  H. g, i# y/ z7 D. O2 e2 y
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)  n( O$ G% [8 T1 C# O5 u
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    / ~1 D; m+ A* ?  `4 \1 ]
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    . ?! C# N( C7 J9 U! K5 e
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    , [7 M& m* [2 p% K* d! q0 R
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
    8 B2 }% f# ^9 h6 y
  42.   if(ret != HAL_OK) while(1);
    2 A, B( z( h" j/ A! n- \) ]
  43. 0 q% X. l" Y7 Q2 N
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能; d% I  T' T$ P6 }& ?9 `' [
  45.   if(ret != HAL_OK) while(1);  g- `  o6 q9 v, w% W# A

  46. 9 w3 H$ j  N) h& l
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2) C4 X7 k% t0 g  H, z
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);9 F" H" ^3 `3 |) K# p3 B. M& F, @
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL7 _$ P* e. }9 ~- `- A
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为11 k: b4 w4 g! J9 ~) f' t
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4+ i- |+ S$ p* p/ o3 t- f' V6 Y. o5 `8 Y
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    ! w* r6 l4 k. ]9 ]0 ^, u
  53. 1 ?7 P! b1 Q. N$ c, X6 w4 O
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。' g$ N# Y, p3 \, X
  55.   if(ret != HAL_OK) while(1);  X! S/ A/ ^# i$ v$ [' u
  56. }
    5 _6 p: Y; @8 a
复制代码
! f& k; v8 L/ X- T3 u7 o; I7 i; N6 K

! j, ~* R+ Z8 d* ^1 E. E: J: N6 J( x+ w- E
+ s4 F" L# G% p  J
- \) ^3 a( i- f! Y
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版