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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
' P7 U1 c4 @4 Z- K7 G. ]/ R! P# v    开发速度快,便于移植。+ r* j" W+ W$ B. H( t8 H
+ {1 |8 W! |) c8 ?+ v
二.stm32F7xx几个重要文件( P- g' l; d6 u7 H" R; x
1. HAL库关键文件( k; o( x; ]# k$ b; G) q

4 j! _( c# t9 t; D) O
B3RQ`@IJHBU@LHI4O{4C]NE.png

% `" c: e3 g' m* V! K
& n0 N8 S% i8 [" J- {2.stm32f7xx_it.c/h
+ [3 }  C9 K) H; x. p& L% m6 @' U         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。% s% g+ M  n- j( x7 y% y

. z' O- B" ^6 w3 o5 U+ _0 t9 V; R: V3 P* ^
$ c8 B6 D7 {7 m: Z5 E
3.stm32f7xx.h9 }  `0 B2 K4 X/ Z1 B
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。0 m* U: U  {6 F# c) \8 m
" k8 U& F* N; o! l
  1. #if defined(STM32F756xx)
    * g# z5 ]: O9 x0 K
  2. 9 w1 e8 ~$ n# D
  3.   #include "stm32f756xx.h"# ?2 }2 o/ W8 C* I
  4. 9 B8 n4 f. t/ Z- k) y# x- _) M
  5. #elif defined(STM32F746xx)
    4 z3 v/ R( I) @$ N% t& }8 |

  6. ! R, X3 S' _/ \; K- |+ Z: _
  7.   #include "stm32f746xx.h"$ ?. C! u" l2 x# N+ T! T- l+ H6 V

  8. 8 Y1 h" Z9 {- G6 h$ A* P( _5 |
  9. #elif defined(STM32F745xx)
    ( v7 N/ d! f* z
  10. ' h! i! i6 d/ P# Q
  11.   #include "stm32f745xx.h"; t* y4 h: q, i( l

  12. 9 [- B; s9 B5 h8 ?( y
  13. #elif defined(STM32F765xx)
    - O6 l7 H$ i3 }) F: X% Y( u' Y
  14. 7 i) u( T! z9 H) h  R3 O
  15.   #include "stm32f765xx.h"( E8 Q2 y% Y9 J% ?  ]; j0 K8 w

  16. . P8 b  Q7 x4 C' z: U
  17. #elif defined(STM32F767xx)- U6 v; e4 x: q& i

  18. * F! o+ h5 r8 t! ?$ a! U. t
  19.   #include "stm32f767xx.h"
    $ P$ u. f9 _9 R" T, n

  20. 4 a6 A0 C$ }% a( f8 h
  21. #elif defined(STM32F769xx)0 H/ Q4 e* t. ~" V, J, R
  22.   |9 E, C. y7 C( X$ c5 o- h8 x
  23.   #include "stm32f769xx.h"; }/ G. P2 s( Z8 \8 q# N; B7 e

  24. & ?2 g& P7 ~3 e! {6 a
  25. #elif defined(STM32F777xx)
      p% D* h) u) M9 O5 w
  26. 2 {/ r3 U2 w. j/ I( i
  27.   #include "stm32f777xx.h"
    . H& ^7 {$ |4 I0 k
  28. 2 v& w" u( _$ b& ]: B* ^0 q# \
  29. #elif defined(STM32F779xx)
    $ S" G0 B# Z3 |4 e# G3 T
  30. 2 E, C7 @' r6 @
  31.   #include "stm32f779xx.h" : v5 d9 z* f8 |+ q
  32. $ k/ @3 v1 \9 b1 p' s2 Z
  33. #else) y! h9 l8 q# @8 y# Z8 M+ X
  34. / Y0 ?  W7 L7 F
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
    9 W: p& n5 ?! q% Z& w# x7 D" n- l! ~

  36. 2 l' O9 b: ]) t' t5 h: u
  37. #endif; ~/ A" K4 _6 R
复制代码
3 L9 J( P/ I" K% G! A* D
4.stm32f767xx.h9 c4 U" M* c+ a' X+ P9 N3 e8 n8 z; N
         主要就是寄存器的声明(一堆结构体和宏定义)。5 y  ^/ d$ {0 D: F1 }

" X0 `: u% L2 c5 L( T( D; {, v; _5.system_stm32f7xx.c/h
3 Y3 H. O& F5 A7 f' @. C         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
# w( A5 ]0 k! |" q# L
! ?" U% B$ N! [7 D5 x& t6.stm32f7xx_hal_msp.c
3 j+ t) U3 i" V0 k3 A  B         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。
" r4 _0 F; V. Z; D* p% {3 m9 N' v  I& N" L2 \; F5 j4 b
7.startup_stm32f767xx.s
- k& J, G) t# Z启动文件,上电先运行SystemInit,再运行到main。
2 N; D9 j; N: p# Z) J% e5 d3 w! _# l0 X3 ^. ~
  1. ; Reset handler: P0 m! ~8 f# r5 r# Y6 z

  2. ( {) c; `; L! d. [( h
  3. Reset_Handler    PROC3 D5 U+ e) I+ K' g: K) o
  4. 7 J. F/ C/ {! P
  5.                  EXPORT  Reset_Handler             [WEAK]% d0 A4 n( N( k0 O. f

  6. 1 S7 M  ~% ~, I# R. S
  7.         IMPORT  SystemInit
    ' }4 N% j6 L, v5 R! z$ x6 o* r
  8.   T* d- V+ E) V$ b( j1 x
  9.         IMPORT  __main/ r5 B" u, f3 Z0 Y1 }- w

  10. : k0 @8 ], r4 l& x0 U' T

  11. 1 f: X/ a- z+ P: v2 J3 E5 j

  12. , Q$ ^+ {# e2 e8 n- E0 _; P
  13.                  LDR     R0, =SystemInit( b# z$ Y! d3 @2 w+ D4 q

  14. 8 P. Z1 e2 J! [5 E' {" v+ \
  15.                  BLX     R0% T: L0 W7 e0 I  V3 Q) M
  16. 9 R: I  q" i3 d" X
  17.                  LDR     R0, =__main5 V, P: }& b3 X% l

  18. 7 X# ]" O& D# j( S/ t0 t
  19.                  BX      R03 y. l8 a7 \# s0 n$ T" S! x& y
  20. / h  |" C, v6 m6 m4 y1 T: R% ^
  21.                  ENDP
    ) Z9 w: S/ P, `' F
复制代码

& p2 l1 ^# B9 _8 ^0 Y2 _7 A
& T) x, ^5 o2 b* M7 K三.HAL库中__weak修饰符2 X6 |/ ]( |: M9 d
         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。0 c8 g  k) z6 u. m) L. ?7 j% X
5 U2 J& t' }( [+ p1 K; y+ b7 P: t4 a
四.程序的执行过程1 Q$ @, I# J0 [6 M
         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)+ P8 y4 p& |- j4 y
+ l0 R2 P& X! u4 j! v# h
五.启动文件

6 m% Z: k& _" d9 _主要指令:
5 M, P4 F+ ~( L2 d; o; J9 ]/ f& W. G  B- s
N@)4NS$@S08L](`A7P41OFB.png
5 A/ i( a' Q4 C4 b% B4 R
`)LQ`K7K2(MYBG[7WDTIZFA.png

% d6 M9 h  J9 B, S1 {8 v) V0 C6 B# K) w' K; j: b, ?

5 l) `8 @& I0 S( {
  d7 F$ s+ v7 s5 V& R/ E; T, @. H3 v" tStack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。
( N" s# j, ^- c! f- [/ H
* i$ T2 o, n8 m8 o! F9 gHeap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free), X0 b5 M: R$ Y! _

4 Q- J, j' w$ ]# z  `- H0 n# N向量表——中断向量服务函数
" g7 E7 ^, M" a  b2 H/ p+ |% C6 @( @% k0 [3 q
复位程序——先进入SystemInit——main
% U# A& \3 |% U: b) r: D! p8 b  Z$ S3 I( u, V9 F) ~" V1 h! K  ]
关于启动文件详细描述请参考:STM32启动文件详细说明
9 `" W+ a$ b1 p7 V" @& ]6 T  `3 I; Q% U: X$ F: f8 B
六.时钟设置(设置系统时钟)
1 T: t+ R$ L% l( N; ^, ], r: F
  1. /************************* PLL Parameters *************************************/
    * p% S" z( n% `" I7 D" H: l9 w
  2. //时钟设置函数# X8 R- q6 R! @$ v" |
  3. //Fvco=Fs*(plln/pllm);& W" [9 v' W9 ]+ o8 G. [
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));7 Y7 {& E: ]( H4 s
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));: B7 _* [2 B& B) c5 @! f; o

  6. . {( \2 h! X* r
  7. //Fvco:VCO频率) N% b) _# E4 V1 W
  8. //Fsys:系统时钟频率
    ; i% Z; y! {) C) ~3 l( P2 r
  9. //Fusb:USB,SDIO,RNG等的时钟频率
    ; N7 y' B: d  _1 x
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等." l! E8 Z4 c) e# M% H/ J
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.( _* J$ K/ Z; k( W- i0 f
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    * J& I! }- E0 O2 [% n. b
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
    4 y% E' S& e! y9 `" O7 ^4 [  g
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
    ' ~: V7 G2 L% W2 q
  15. 5 z9 _: d* P1 k/ p" K6 M8 K
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    ' ^% g7 Q! H% ]5 _; F7 H3 \
  17. //得到:Fvco=25*(432/25)=432Mhz& W) Z0 b7 B/ ^4 n7 X
  18. //     Fsys=432/2=216Mhz
    + g4 d: ~8 i& V( c, ~
  19. //     Fusb=432/9=48Mhz+ J0 x- L8 ^. [! ^
  20. #define PLL_M            25: W+ F4 b  A# Y0 `) i! E  r$ @# a
  21. #define PLL_Q            9! B: s# R$ H) M- \1 K! o4 A- ~$ Y
  22. #define PLL_N            432
    8 \! N. i' d4 i% \
  23. #define PLL_P            2
    . Q& H& J# R! y( T6 h2 b

  24. ! O( X& J- r/ y4 b" H4 H3 i% l
  25. void SetSysClock(void)
    ' w, n/ l* u0 V5 k
  26. {" x) L2 D' @' f; d4 M& u
  27.   HAL_StatusTypeDef ret = HAL_OK;; H4 E0 [$ R$ _
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;9 w  Y2 O* Z6 {/ X5 G! s, y
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    " J  r) r/ D7 f1 M

  30. $ |, E8 t7 L* v; H
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    / I  e* t5 q, s7 p' M
  32. 1 p) H/ S* H7 n3 }9 `) o" U& A
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE  B1 z4 Y5 k' O  N' G' ?. M, L
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE0 x+ D, [; v. J
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL- L7 {( d, z  {9 }  O% S- h3 G8 U
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE
    . d+ J8 Y9 }' _2 _- L: z$ e" B
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频); M2 q1 }, S0 V' o
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)8 `3 c; r4 ~1 w( w! U+ o; G
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    ! b/ t3 e: c: c( ~
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    8 ^1 T7 R; q$ p* i  v- \( O
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
    6 P/ l6 m$ P6 Q
  42.   if(ret != HAL_OK) while(1);
    ( B) U7 _& I0 l, _( L$ Z; ]5 V

  43. # H3 G" c( A5 d, y/ Q
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能6 H. n6 n" P0 j
  45.   if(ret != HAL_OK) while(1);
    6 V$ i  _+ _9 ~1 K- l; j

  46. 6 X5 }' d  a- J6 C4 ?
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
    7 `: }+ g" j8 N
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);6 v: V( g# L1 ~, I" o4 G+ K7 E3 o
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
    " q5 D) ?$ V1 z8 r
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为18 O& D6 E+ Z: [' W# U
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4
    , P7 U. I, k- @0 x$ w
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    3 z3 ^. u' c+ o/ D) F6 W) e3 w
  53. , R6 m% b1 f9 V. I# V; ^5 o: A
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。
    4 m- f5 ^+ Z! }4 I  h; o
  55.   if(ret != HAL_OK) while(1);' S6 L+ `& A0 q: t3 k
  56. }
      {9 N0 m' d3 ~0 W6 t+ f$ `
复制代码

: ^& ~, Q3 j3 t5 x# T
( [: y6 e$ u2 X# g6 ^6 b
$ S5 V, F0 c& j. _. ^/ E' e9 X# B. |& y
$ F$ q6 ?$ q* u
5 A6 O% d& M1 m
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版