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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势; [0 Z2 K7 {7 P$ t
    开发速度快,便于移植。
' o; N$ t7 |% [, F. i
1 @, a& X  {/ l8 @% l8 K' L2 F, i二.stm32F7xx几个重要文件
7 r9 r6 M1 `+ @( \& h6 J! {8 P1. HAL库关键文件
4 h& O, Z. g/ _7 n1 d- w6 X% g$ [  C2 F+ W/ n( ~
B3RQ`@IJHBU@LHI4O{4C]NE.png
) t" j# w! y( N2 I

) }/ N% {. j; V2.stm32f7xx_it.c/h; v. z. s3 h% O7 U( q& h3 Z
         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
  d7 s3 t5 c% k: {9 j( K! u* F! h6 P) J

- f" C( d5 T) f% M0 X3 K$ S8 t/ _9 A. A; i  i1 B* I
3.stm32f7xx.h/ B0 }8 n( V+ R2 h
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。9 C/ x1 G, {" s7 l
) `: |& i7 E9 t
  1. #if defined(STM32F756xx)
    5 {! `7 `  r2 F$ v: G

  2. ( f: K8 e9 T/ g, V3 r4 S
  3.   #include "stm32f756xx.h"# c, ~5 D7 j$ q. ?, ^
  4. 6 \, a7 N  P4 t
  5. #elif defined(STM32F746xx)& H, `. l: k  H
  6. 0 v! u, l+ E' K* M/ X3 R4 {0 r  r
  7.   #include "stm32f746xx.h"
    ' |1 K' v3 r8 n" ]) w4 `
  8. 5 i" B6 k, n0 b7 i2 ~7 @: _
  9. #elif defined(STM32F745xx); |7 B( ]$ L/ ?7 C
  10. + q* j2 S1 c- X+ y8 q7 j
  11.   #include "stm32f745xx.h"
    4 B# b6 N$ q; ^, x3 q! u2 C; \

  12. & l) |) u3 g% A) K0 x
  13. #elif defined(STM32F765xx)
    : K; o% {' y$ ?9 Y  B

  14. 4 q( O* V9 ?8 D7 Z& w9 ?
  15.   #include "stm32f765xx.h"
    2 }7 b+ N  f0 i/ Q' _

  16. 5 E9 H2 O( p. [8 e( b+ M
  17. #elif defined(STM32F767xx)
    : N' a, ~; t( \! N! h$ g

  18. . `# l' x1 e6 P5 R" o% _' d
  19.   #include "stm32f767xx.h"
    8 Q- S, y, n3 O3 u, v! r& }0 o- E

  20. ' r( d2 |* J( z% P8 A$ c
  21. #elif defined(STM32F769xx). |- V5 W" s$ |" W4 V0 c
  22. , H7 H: w# P# [$ [+ L
  23.   #include "stm32f769xx.h"
    " F9 ^9 Z$ w- X3 g; w: Y
  24. 8 v6 `* I8 {% ~- u( ^1 F% R, y
  25. #elif defined(STM32F777xx)
    2 u* r8 n" C( a( a0 A8 |

  26. # A9 n7 S& N1 v) X/ V  R
  27.   #include "stm32f777xx.h") f; o3 i3 s; N3 ^7 Q9 ?

  28. ; v& u, N1 e, B+ A
  29. #elif defined(STM32F779xx)
    9 I) V& ?5 W  {0 Q, n

  30. 6 V5 D9 [- W  s1 ?3 O; o
  31.   #include "stm32f779xx.h"
    8 w, L1 n  I5 W2 P* ~
  32. . A6 o- T9 a  F/ X
  33. #else6 |) y0 D( z7 W% X- q5 U
  34. # ^; L8 i) e% }; ?3 v; |# Q5 B5 l- @
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
    5 E' s/ t: o" }& j

  36. 4 K& I5 N# g) M6 U
  37. #endif0 v* L  A8 @. D  s  V; e7 }
复制代码
; e7 i; i1 ]' v% k
4.stm32f767xx.h
! ^* P; a) P8 A- D         主要就是寄存器的声明(一堆结构体和宏定义)。; ~, c+ b( Z; m- t

! l; v# j3 i7 ?5 L5.system_stm32f7xx.c/h
3 `& J, \, H% j+ |6 h& I4 q) m( \' {9 C         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
. N/ g$ e; W/ d: l3 R# }. @. F, y" Y/ \4 D6 P% X) p1 H
6.stm32f7xx_hal_msp.c
; O6 h# B! R% ^5 t5 F" ?         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。- p+ O+ d" c( ?
4 h: H  B. |( Q0 `9 }8 Y; ]3 p
7.startup_stm32f767xx.s
) s5 n* `2 K6 |0 |* X; U启动文件,上电先运行SystemInit,再运行到main。
+ u# g9 l* p  L# j
, C: K- N/ a5 S4 J
  1. ; Reset handler+ j' g) {+ W2 |& k9 f$ \2 s; n& d
  2. - K& g$ F; G3 g/ o
  3. Reset_Handler    PROC
    0 n0 ]/ ^7 L8 y2 w$ ^1 k7 ~  C* d

  4. ! D3 Z2 W7 \4 |# o2 h8 b
  5.                  EXPORT  Reset_Handler             [WEAK]. b3 i- m4 r: z: M
  6. - l9 p$ H$ ?& @( J: w
  7.         IMPORT  SystemInit
    * P+ W. B, I( C- i
  8. . G* ]: u6 Y% S+ ^. `" I
  9.         IMPORT  __main
    ' r& F6 k( z5 _$ R& G3 _
  10. 2 J# W, D; u7 \: p! p

  11. # U/ S( M' i6 P* b6 f
  12. ; \* q. t7 q6 @1 O+ }( z
  13.                  LDR     R0, =SystemInit. n! K1 C# q7 y

  14. , Q. c8 ^4 A9 q) e
  15.                  BLX     R01 p1 O1 }( n% `- B! ~

  16. ) T3 Y8 D  i& `$ U
  17.                  LDR     R0, =__main8 j- c* n$ x# z
  18. , B% T2 y7 T0 U+ \5 O
  19.                  BX      R0( l; ^" X0 u- R$ C
  20. / [. [/ {. f# o5 U
  21.                  ENDP* ~9 m5 M7 B8 r1 o/ a( Z
复制代码
( g$ `" g# @$ f7 A2 Q

' k  @! L+ x$ G三.HAL库中__weak修饰符
1 P; k7 O2 S2 l         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。# S1 L, i, g( n. S/ }' M

7 M7 B2 \' m, q6 n5 u四.程序的执行过程; f0 B6 k% t5 g5 P  G7 c( o& m
         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate); b! z$ i* m: \" X' x' o8 @

0 z: M+ i6 B+ Q5 F" z( [/ e五.启动文件
' h. t+ u. r/ t" C6 F/ n
主要指令:1 W5 a" x: h+ O- _/ L3 F. O
' A% k7 W4 _# L* ~
N@)4NS$@S08L](`A7P41OFB.png
& [, \4 }; R# \$ s% T; T
`)LQ`K7K2(MYBG[7WDTIZFA.png
; ]5 a- y7 w1 Z5 G5 O! X

6 U) W0 c3 a* f% X! G  r% U( h% a
- \! }' n4 a7 K
+ l- `3 C& w* f2 ~, B- _" Z+ ^Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。
' V+ Z+ @8 W1 ]4 w1 `7 P: A) o1 J& O% `7 @
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)1 J& V3 w. m, j7 x  [

% U3 N' c1 t1 P/ f& k- ^# U' j! {向量表——中断向量服务函数
% k; F, D1 l$ G+ d9 w4 r% p) h  T4 J) e2 K  F$ t* f
复位程序——先进入SystemInit——main
2 c. \- y4 N+ A* h
8 h" x* i/ R8 F9 K' i7 X关于启动文件详细描述请参考:STM32启动文件详细说明& E5 r1 j5 H% d
7 W( \" L4 |5 \4 _0 {* F) F4 a
六.时钟设置(设置系统时钟)
5 Q; H8 a2 H: J$ Q7 t9 c4 p
  1. /************************* PLL Parameters *************************************/
    ) g" N3 t6 `' L0 S& y& a
  2. //时钟设置函数3 ]" R/ `( {' G; {) y
  3. //Fvco=Fs*(plln/pllm);
    # S( f- w5 _" p. j
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));8 w7 w: q. }5 I0 B( U( L) o# }# d
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    ) m7 E! k3 T8 z+ {3 d  Z0 G' o
  6. 3 V  D7 I5 Q' N: I- E( d& y
  7. //Fvco:VCO频率
    ! F8 h) M  @2 `0 n* A, ?# f
  8. //Fsys:系统时钟频率* @4 Q7 d: x: h- [! c
  9. //Fusb:USB,SDIO,RNG等的时钟频率
    , g& ^& j/ w. F1 y: I+ Z5 u
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.7 `, ^- F1 B2 {7 X2 e
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
    . X, q2 A1 A; e! e6 e
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.; y" O7 i) O" x
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)% S- P6 K. u  A. A# _: R+ T
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
    $ }6 Z  e1 b! ^" ?
  15. ! L+ Q! F2 h+ y* B3 L4 S; k/ M! E
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.3 O% S4 T* j" X8 T+ g# p) j5 S
  17. //得到:Fvco=25*(432/25)=432Mhz' a. ]8 M# g% ~8 m; Y) Y
  18. //     Fsys=432/2=216Mhz
    6 F4 g6 U! B' n* k
  19. //     Fusb=432/9=48Mhz% k! k1 X1 y: x$ q; m
  20. #define PLL_M            25
    7 P6 P$ \4 f  F! _, a
  21. #define PLL_Q            9
    . b1 [7 _5 Z' ~4 O2 D, F+ |
  22. #define PLL_N            4320 H1 f  t8 n3 B" t% S/ g
  23. #define PLL_P            2
    6 X8 y' Q: J1 x5 n
  24. ) z9 z+ S3 N  \8 Q9 ?1 c
  25. void SetSysClock(void)1 z+ w! H1 ^. |3 B+ I
  26. {
    . n. Q% ?- [: N4 g! x2 M
  27.   HAL_StatusTypeDef ret = HAL_OK;1 u/ w" z3 R. x# }2 h
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;4 x. G: r0 z+ F; c/ C- B4 c# X
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    ; ]) P9 e0 l8 r* R- R; g

  30. 0 m3 k7 u5 L4 h& o: Z5 e) B
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟, x0 R1 \  B& p( r$ M3 o

  32. 0 m4 N& T* h: g2 ^
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE+ N6 T* M& H- Z
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE2 E7 |3 B; p6 c
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL& P+ ~9 c0 r  J4 v! V! @
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE
    5 h' s/ k* E9 L5 k. g5 E7 g
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)
    * E) ]% P2 X7 E7 ~0 l
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    " \, i0 M; V( N
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)8 ~' @  n8 o# _/ l- q  h- ]
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    $ l( G  Z& _( D3 k. i0 R' |
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
    * O  g- H% ]9 {( t
  42.   if(ret != HAL_OK) while(1);
    - Y6 D% l, B$ j5 F3 C
  43. % @( E3 L% U* i
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能, X! V4 }6 d) ^- Q+ Z
  45.   if(ret != HAL_OK) while(1);
    2 M4 X6 [! X7 k6 S: v: w0 x3 t
  46. # s8 |9 w+ |, B' q6 E* R) `5 L
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2- F7 w& U1 a0 N% X
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    ; L$ `; ]8 G6 S
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
    * p, `0 P  M! m, U% h  d0 W3 Y. D. H
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1
    / H6 U2 Z1 W% ~- R2 \$ B4 o
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4
    , Z1 W4 B: v9 n. q" h
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    * E2 v1 h4 z( h2 ^8 U* }" I
  53. ! m7 V1 S  O# ~0 }
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。" @/ L7 l% b8 G! M( v
  55.   if(ret != HAL_OK) while(1);
    1 z" v8 ~: C! f
  56. }
    ' A9 w4 h+ D7 T
复制代码

1 v  p% Z2 [! V" T& X" D( A" p, `
$ ^2 j( S5 Q" o* x3 K* I' @" T' Z0 l" R* T4 k- ?/ E
. X; B2 o$ [! R: m' D
- C, s  F" w1 |. i6 ]5 e  H
收藏 评论0 发布时间:2021-12-11 11:00

举报

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