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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
7 b) k: Z' d$ I9 p) E+ C; e    开发速度快,便于移植。
9 X% o" f1 c* F4 O# X
1 G) C7 N0 H; N% z  }/ i二.stm32F7xx几个重要文件
, B  }, T3 E: w! @9 G. c% P, W1. HAL库关键文件5 L2 ~9 v  B, _; ~/ N) u

9 }; e/ ]2 ~. a/ G, G
B3RQ`@IJHBU@LHI4O{4C]NE.png

6 m8 l7 j8 v" b! S  ?) k% [
' _$ @0 h# n- Z8 h1 C2.stm32f7xx_it.c/h
1 M9 [! W9 ~6 @) {' h         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。# [- u$ |6 S' T1 M4 p

  H4 a) R% b# v" E' F+ I" t1 O/ L- {( R: K1 k

; Z; a  @. s1 v5 B. ^  g3.stm32f7xx.h: ~) K% _4 M4 T
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。3 {* U; D9 X' k
! K8 ^' T4 v" @8 c8 g/ [; ~. ]
  1. #if defined(STM32F756xx); e9 z2 N# ^5 e

  2. & A/ F; L+ k# p" G
  3.   #include "stm32f756xx.h"
    ' ?6 ]  k$ ?& _' h
  4. - J! W* \! ^6 P/ q8 N3 z5 s
  5. #elif defined(STM32F746xx)  d5 e, u- u/ A" H& d

  6. # K, ?! y& Y7 h. O& i( g5 ?4 b/ K
  7.   #include "stm32f746xx.h"
    8 j1 ~, i% L  ^6 T, ^, |- C, E1 h- B9 K
  8. ! J6 v# x4 Y% n/ M9 i0 I& ^: ~) Q
  9. #elif defined(STM32F745xx)
    ; G9 n$ a% ]1 Y# h2 `1 h
  10. $ @# ^% p. G( p: h. Q6 x
  11.   #include "stm32f745xx.h"
    4 f: A4 w2 U. ~6 g- E- G8 t) @
  12. % J7 ?6 _* O- \, P
  13. #elif defined(STM32F765xx): B( M# }- c  _' b

  14. * Q& s. H/ ^1 E% }9 [  S
  15.   #include "stm32f765xx.h"& {, E3 V4 t9 k
  16. 3 [6 y/ a$ [7 t* q* X2 C
  17. #elif defined(STM32F767xx)
    - \6 j) f4 n' G) }, Q. r
  18. . k% d. ?8 L' \
  19.   #include "stm32f767xx.h"
    8 `: A% b1 |  N/ n5 j
  20. % J5 ~0 f  L5 O# z+ o
  21. #elif defined(STM32F769xx)2 x' l. l' v) R, x: ?* T  _

  22. 6 u& b+ t& c2 L5 a# w! x. M  A
  23.   #include "stm32f769xx.h"( g/ |+ l4 o+ _+ H5 M

  24. : V+ c% j' e) E0 a. d. B
  25. #elif defined(STM32F777xx)
    ! w. y2 l' B8 m

  26. , ]( S9 X: c6 Z* g9 F7 @2 F
  27.   #include "stm32f777xx.h"
    5 I& b' p% L3 k& g7 N* \/ g6 U) V
  28. ) Y7 X1 t: N8 r  N; T
  29. #elif defined(STM32F779xx)
    8 i2 s) K. k0 _! y* r

  30. ) t  [3 e/ y0 k, a  Y; u6 O" R* F" R3 `
  31.   #include "stm32f779xx.h" , E8 ?+ F1 _$ Z7 X
  32. 6 ?* s* _+ o7 A
  33. #else: M7 b1 u. r3 T; I. f

  34. + y" i, v8 E9 ~: V$ @6 S
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
    . L1 Z' }' E$ H. V, q5 \

  36. 0 r/ s0 i& o" o" m' ?* U3 q4 ~$ T2 i
  37. #endif
    , b% v, N% B% K+ [
复制代码
2 L  R5 L* U% g! s" U. n0 C% I: I% Q
4.stm32f767xx.h% i7 I3 T3 k9 E* e; v4 q/ T
         主要就是寄存器的声明(一堆结构体和宏定义)。* @) c4 q" v! i
' B* u1 I+ j  a! T
5.system_stm32f7xx.c/h" W$ Z' }9 N/ `9 m, q8 M: |9 s
         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。2 U# |( U, K1 d( R+ i/ z; `

2 [- M2 f6 v) E, ?6.stm32f7xx_hal_msp.c0 I0 b% Q( |. [. `, q8 e  g
         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。! W; M2 L3 j; b4 C* M' H0 w

4 V& Z0 e/ ]/ d" q1 J1 H( G7.startup_stm32f767xx.s, k3 q0 R6 e2 p; h9 i  a
启动文件,上电先运行SystemInit,再运行到main。
3 [& t/ \- f) X5 y' L/ g0 s) R7 W- t* Z5 K$ z  K" E
  1. ; Reset handler( p7 w4 G' ~( y; m: v3 ~+ Z
  2. ) i5 p9 M8 X( j. P" ^. X' I
  3. Reset_Handler    PROC
    ; [* Q. a. {4 s% d

  4. / z: [6 O- X4 G; @& F$ W
  5.                  EXPORT  Reset_Handler             [WEAK]* j9 ~, n  a' [& a% r

  6.   u8 T" J; `9 S6 q) P: E! F& k
  7.         IMPORT  SystemInit
    & e+ M- @4 d1 {. ~- y1 z/ V
  8. ) a$ d( M/ Z0 s
  9.         IMPORT  __main
    ; g9 s9 g; e2 v* s; D; z+ P5 f
  10. ) V4 u7 B0 W2 g5 w  {1 r, ~( K/ v
  11. 0 D2 L, y2 \$ H& t1 R$ `

  12. 8 }: q( [6 K* I0 S
  13.                  LDR     R0, =SystemInit
    0 t8 q# f6 U" G1 q( X9 f. P( [/ }
  14. . y! b. E+ s7 V& Z& _
  15.                  BLX     R0
    6 N* @" j* v( e* H
  16. - s6 r  x$ P$ U  |' c1 }& G. j
  17.                  LDR     R0, =__main
    : |! l* \4 e  d" \% R
  18. ( C+ s" p; E. r9 P- k+ N
  19.                  BX      R0
    - S( _7 d3 t. D9 g- K) I: S
  20. 0 d4 h' @4 u3 E* @4 [
  21.                  ENDP
    2 c- L1 }% X0 P* h* K5 B7 x- R
复制代码
1 T: z2 Z2 m3 ?5 U* M( I3 X) F% ^6 t

2 `" A8 }0 k( k$ j" \6 M$ C三.HAL库中__weak修饰符
. T8 t8 A: A: `7 Y         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
9 [- D+ p: |% s5 J6 E( j. J: k/ y" i# G) b
四.程序的执行过程
6 B5 U* V3 Z7 W4 r  Y8 R! w         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)* Z2 m- q# i* Y# R5 }

$ t, F6 l# {! i! G) t3 d五.启动文件

( U! e: D& A; _* G( M主要指令:& c+ D4 L2 K7 K, A
4 v* l. H6 W+ I+ R9 q3 L
N@)4NS$@S08L](`A7P41OFB.png

. ?9 b; X9 Z8 g4 j. L6 ^3 n
`)LQ`K7K2(MYBG[7WDTIZFA.png
/ k* @8 M- E' R0 @  C2 [& E7 P
9 N1 e" V( f7 k, g
) c4 g$ @" g  e: C6 S* p

9 s+ J6 }& ?/ b) Q5 i9 Z1 qStack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。
1 n6 J# I8 K0 g3 e, L( R; F6 l0 R' S6 k5 j; p% Z" m. A+ G
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
# P; m; y0 S- Z$ N& ^. f" G+ I" [! a9 m
向量表——中断向量服务函数
$ w; M$ A" m3 ]
1 X5 A, ^& ^5 ]7 N复位程序——先进入SystemInit——main
. V; M% O9 T8 G0 S0 ?1 |0 S" h
6 _+ s9 x5 u7 U; N% h关于启动文件详细描述请参考:STM32启动文件详细说明
& A9 \+ }% f) u! N/ b' ]
8 {& g1 O# e% G* S. L; i六.时钟设置(设置系统时钟)
, X( j; T/ r6 `5 J
  1. /************************* PLL Parameters *************************************/7 Y# ^( L) J6 t6 B  u" Y4 g
  2. //时钟设置函数
    - i. A/ d: X- a; B
  3. //Fvco=Fs*(plln/pllm);
    ) ~; G- {0 U- w* m3 x1 ?. |" @$ E& w- J
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));6 Y+ ~( j/ A' g
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    6 [! m5 f2 \) S+ [8 I$ {

  6. 8 Z! Y# l. s3 |: a; H! |2 \
  7. //Fvco:VCO频率
    5 X2 J/ X0 A: x/ f# Q  b4 ~. f8 n
  8. //Fsys:系统时钟频率/ I( q" M% `* z' e& }1 C  z" J
  9. //Fusb:USB,SDIO,RNG等的时钟频率7 w  E" ^0 Z; P  `. W- C, n
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.
    2 z2 a0 W+ X+ G% O+ }/ T& w
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.5 ~% b9 s% m/ m
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    ' Y. Q8 }+ Z1 D
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
    % b/ v0 D5 t7 k8 A" F0 w
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.$ p0 Y# b6 j$ i/ D- m  D
  15.   W4 L# M1 t2 n7 ~0 M5 [
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    . ~6 r1 D% I2 u. q) @% }& ?
  17. //得到:Fvco=25*(432/25)=432Mhz7 T8 P" o% H. E$ s; k5 F# E+ G
  18. //     Fsys=432/2=216Mhz( [# r& c- _6 Q
  19. //     Fusb=432/9=48Mhz
    4 h# i3 t: A! O1 O6 G
  20. #define PLL_M            252 `8 C4 |& T, A& @0 O; o$ w
  21. #define PLL_Q            9& ~9 @9 S% x- C1 `  R
  22. #define PLL_N            432
    3 C# O$ y) R/ o/ j
  23. #define PLL_P            2
    5 p" d) p9 x! r4 M1 w( o2 v2 I
  24. , P* p9 {$ N0 P* }0 L! Z' k2 O
  25. void SetSysClock(void)
    / B. B0 x/ R; f
  26. {
    6 s: \( H, P" }7 X, A1 J7 h
  27.   HAL_StatusTypeDef ret = HAL_OK;( Z/ ^4 J; L) U0 n) I) Q
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;
    ' M% f" x) B) _9 W' z& Y# A
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    ' R6 u$ C' d0 [) e

  30. ( Q9 i# i- a! k7 s1 l2 S2 Q
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟4 n. N$ T$ V, p! j

  32. 4 x% h8 x$ }! c0 j* L: W
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE
    ! p) X% L7 @0 k; T  {
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE
    " @2 }6 T3 P7 h5 {% F( o$ G9 l
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL) E* a( W; v' d7 I2 k0 C; D/ z# j
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE9 i2 m: P( I# C  }8 T. I# C- u
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)+ r2 ^% x+ }. l; T# t
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    7 u& `3 `, y3 P  U& m7 Y5 J. s% u
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)  g9 \. B# |/ X" C$ i
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频); x1 K, n, ?& H" o' F
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化9 @9 C' o. c% q: L  i# [
  42.   if(ret != HAL_OK) while(1);$ T" {1 S, r6 }; p0 X
  43. 4 D1 n- s# W2 X, t$ T
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能& x0 z% `  g8 K6 [1 K4 T& ]7 P
  45.   if(ret != HAL_OK) while(1);
    2 t2 p2 ?5 S/ w7 `  D( S1 s/ X
  46. " I  p! a9 T6 N1 v& ^, \7 P4 {
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
    . u' o8 e: ^- g/ w" }. {2 M! t  F
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);( a$ g. P: ?% p6 V; o% ]
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL/ m! m+ E" t* v' J0 b  ~2 R
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为11 D( o; F3 c, i2 L' x2 q/ j, V
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4" L- |/ Q% O" i2 P$ u2 Z9 C9 F$ I
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为21 r- t  n. U$ U: G$ n1 P- l, o( ~

  53. % l1 c% I/ G  F; Q1 W( t' i5 M9 R
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。2 Z/ W; y- T; F7 H4 D4 ?2 D9 w
  55.   if(ret != HAL_OK) while(1);
    6 M8 s* m1 ~0 R3 S7 i, m# ^
  56. }% N7 O% `9 P7 K$ P) f
复制代码
  Q  U7 Y6 V" a, V7 I
: s* p5 }4 _, x
. a* ]( X3 g+ \* u# }3 N4 e0 m  b0 h; H

! |# k, r% Z3 f8 E4 n
8 l9 w  Z# n9 q0 {4 J! ?
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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