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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
* M1 b9 t8 C# F4 K7 ~. m    开发速度快,便于移植。
' ~7 Z: A# Q: a7 R, \
- S9 \/ \9 Y+ G0 N+ p6 }二.stm32F7xx几个重要文件/ g( U% a7 h" A
1. HAL库关键文件, {* s8 ?( N8 K. z2 Z
3 x) [6 C' a' ?2 D) M! R
B3RQ`@IJHBU@LHI4O{4C]NE.png

2 ~3 l4 a9 K2 c: h' u: \" u
8 }6 q/ N* H* W. D2.stm32f7xx_it.c/h
" @' C/ Q0 D! e         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
" Z0 |6 |) U6 T7 d9 g
9 Y1 j% M) p7 X0 @7 ?. ?8 _6 x" q7 ]2 c! w

* B1 J4 x: d/ G6 r: h# ]& Z3.stm32f7xx.h2 N6 I0 ^) ~* R) D
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。+ ?& N7 w. {) Z8 n  h/ M

& ?6 `* V  h8 W6 M4 R1 W
  1. #if defined(STM32F756xx), W7 i8 `1 X; B4 y7 p
  2. ( W- G! o; q: v& l% F" w0 J0 l
  3.   #include "stm32f756xx.h"! O& k7 d% o! b$ \
  4. 4 Y: w/ X  c6 C
  5. #elif defined(STM32F746xx)- M+ E% H9 m/ ^$ `* ^# t2 N

  6. 3 |& E* Z# B9 m4 A
  7.   #include "stm32f746xx.h"+ e! `0 P( X- K5 x1 R' k; j

  8. 0 w) d. M& V9 |' t/ G
  9. #elif defined(STM32F745xx)
    ; c6 N9 s2 g! B$ M' z  e
  10.   ]8 c: M) n; r3 K
  11.   #include "stm32f745xx.h". ^* A4 C0 n  x" R+ c' U1 Z( {3 G

  12. , ^9 }( J6 F& V! ?# I) I/ e
  13. #elif defined(STM32F765xx)/ a/ ^- ?) t' _- w

  14. " \: t$ [4 @* T
  15.   #include "stm32f765xx.h"
    % V$ v5 b0 H9 Z9 ^# @. v( _8 Z

  16. ) n' \. @9 Z1 C6 G9 W
  17. #elif defined(STM32F767xx)
    & U3 i- b0 @7 Y' H7 g# j
  18.   J( i3 ^( I  p6 y7 w% H  p! C
  19.   #include "stm32f767xx.h"! ~4 k, m6 y; }  ?6 e1 r5 h: _

  20. # f* \* J  ?  c' j+ D
  21. #elif defined(STM32F769xx)& R: P, u9 w7 z4 ]& M" }9 k# M

  22. % P! z, |" w4 J
  23.   #include "stm32f769xx.h"8 h  k9 h1 Y/ }1 D0 Z0 J) a( m

  24. : ?6 o8 ~% j( i1 j- k6 B; o" h5 C
  25. #elif defined(STM32F777xx)
    ) i* n# J  I2 }# o

  26. 2 E% I4 o9 A- K
  27.   #include "stm32f777xx.h"
    + F! t6 N/ H; K* f3 _5 P

  28. # V* C. ?% d0 I  B, V
  29. #elif defined(STM32F779xx)
    * L- _& I! s' y( [, a! T8 L

  30. ' a2 L9 i6 }  U" ]) m  d0 v
  31.   #include "stm32f779xx.h" 3 p0 Z7 E7 h: Y: n5 L8 m
  32. ; P5 j" c; ?: k( r  R  T# d+ Z3 Y* D
  33. #else2 H) a" b; b" j4 v; u: ]- h! _# o

  34. 0 F" }& M6 c( ?% p) a. ~( Q5 y
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"% V# ]% s9 Q6 p2 K$ I. ~4 n( J& Q+ }/ \( G

  36. ( ]' J3 t, g" Z" ~1 i
  37. #endif
    $ h9 z0 |1 r3 n9 ^' m/ S
复制代码

9 F  Q- H% Z' ^5 K7 [4.stm32f767xx.h2 l, C: T( [- Y
         主要就是寄存器的声明(一堆结构体和宏定义)。+ [7 _# x2 |: r/ q

% F5 }- b$ w2 f% S1 b  N5.system_stm32f7xx.c/h
& D9 G2 K* S% J# ~         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
, `1 ^+ U- Z0 o0 U/ \9 \7 j/ [9 H( ^4 k
6.stm32f7xx_hal_msp.c
0 T# G) ^) ~+ S1 ^% i5 Y0 X7 e         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。* n: O$ \0 t: ?6 o, n! l

! c$ ?+ J! Y8 _7.startup_stm32f767xx.s2 j" k5 `+ C% {( w
启动文件,上电先运行SystemInit,再运行到main。' \( t) L) n5 t) M+ }3 @+ J
5 ]$ s& m, k" I) V
  1. ; Reset handler3 f9 V* B2 F& ~
  2. * H# z& l7 E# u5 d
  3. Reset_Handler    PROC
    . B3 v! u7 x1 N' `4 t) {# I
  4. ) F. [4 Z* Z( |5 _1 [6 C9 ?, z! R$ D$ ~
  5.                  EXPORT  Reset_Handler             [WEAK]  {* A( P8 Y  j( z' q* q) l

  6. ! O! x  o' k, Z
  7.         IMPORT  SystemInit" O' Y; d  p+ q7 m0 Z0 k
  8. " T5 x& E* j; c" w% }
  9.         IMPORT  __main, U, \9 X2 E6 r0 |+ R$ i' l' A$ L9 [
  10. : H! ~+ e/ ]$ s% i1 V

  11. . J: Y3 }+ W  R2 s* t6 I

  12. 9 v! D3 l4 H5 g7 P2 `2 x6 @7 L
  13.                  LDR     R0, =SystemInit  {3 b; t" z) x% N4 H& z5 Y2 a9 Y- w
  14. * F% |6 t! E! t( S- P& g! ]6 u
  15.                  BLX     R0
    9 o5 l: J4 s0 f! P' U) P
  16. ' e  Z9 K# d) ~) }, q, A! L$ o
  17.                  LDR     R0, =__main
    ( }. D0 v8 x3 c, b# @: W6 n
  18. 6 [  E; _/ u. T0 A/ W7 P0 M" m2 Q
  19.                  BX      R0
    . a/ o7 w" k9 y$ q' j; J; B/ X. m
  20. & z" M) S# F& `0 l
  21.                  ENDP
      R8 [. X: Y# H6 I. E( c! a
复制代码

4 ]# r- l/ ~0 t1 ~7 O) Q" k, a2 E  ~8 [: t% v* j5 h
三.HAL库中__weak修饰符
1 r- i8 @0 f: H. f/ O         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。. l9 o& v  z; p0 g  ]1 N
3 @9 `# f  o' v' l! U" w
四.程序的执行过程, t# n4 M* g' ^! O
         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)
% I7 `/ d- G( _+ X9 }9 v0 a6 E: P
/ J: p: N7 h+ s) ?" `. d; K五.启动文件

7 P9 T0 k  m: @" @主要指令:; Q) R, A$ _- O8 Z

1 b) W( |2 ]: E/ y
N@)4NS$@S08L](`A7P41OFB.png

: e4 n9 J; ^) M1 P2 \
`)LQ`K7K2(MYBG[7WDTIZFA.png
1 T2 {: o/ }" U3 v% {3 |

8 ]* y2 F# d$ y1 Q/ x) ^1 H" ?5 n* H0 G9 p
. a; V1 O/ ^& a  J9 z4 N
Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。3 O- w( N7 J5 S4 n' [! Z

( T4 k3 B( r' }9 w+ @Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free). H* O( S4 e5 K

* H7 e! V5 Q- T' [1 ]& x向量表——中断向量服务函数, z' w$ b6 U( U4 W

0 b/ u; m( V' g9 [% Q* I% l2 X复位程序——先进入SystemInit——main
4 M6 n* `( V# }" o, L; r/ J1 e; I
! s3 k$ \* K, m) q2 C+ J: Z关于启动文件详细描述请参考:STM32启动文件详细说明) {/ H. Q, r& Y' K2 {! `" R8 J
/ l6 i& w- h# S5 A/ l
六.时钟设置(设置系统时钟)
! J2 o% Y' \8 W; L
  1. /************************* PLL Parameters *************************************/
    4 `0 i$ ^6 j& l; K
  2. //时钟设置函数, @# h6 t9 E8 y/ ~
  3. //Fvco=Fs*(plln/pllm);
    ( q3 q3 b: p+ }" W* t
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
    ! b& B5 ?8 T% a# j
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    1 C2 A# K1 @& i, w; p/ ~! y

  6. 7 p. V* B0 n9 \1 {
  7. //Fvco:VCO频率  D+ c. }" [# Y2 w$ ]  e* `5 y
  8. //Fsys:系统时钟频率3 j% u! X! t; E) d# d5 \
  9. //Fusb:USB,SDIO,RNG等的时钟频率
    : H. A; y- F2 Q# S
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.+ w9 f0 b+ L3 h$ e% K
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
    6 E2 \1 r! |) S$ j- s/ |+ O
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    ( H; N8 u" [/ p! N$ Y
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
    & z+ w# n$ F5 a3 Q
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.0 s' `4 |1 `- `+ G7 z1 {

  15. " i1 c3 C. q4 h% F: Z0 k6 ?
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    6 f, P5 x0 v. q! N- p
  17. //得到:Fvco=25*(432/25)=432Mhz
    5 L' |) p6 Z* [. K) k) q! _
  18. //     Fsys=432/2=216Mhz8 x7 f4 ?/ l; d3 F
  19. //     Fusb=432/9=48Mhz' `% M" W1 E$ r( Z9 j
  20. #define PLL_M            25/ t( m" |8 l& ~3 S+ H
  21. #define PLL_Q            9
    ' m  A; r1 _  `* t& ~; _
  22. #define PLL_N            432: Q" ?# O# s! w' A( Q! Q. q5 [
  23. #define PLL_P            2
    1 Z) p1 }1 e. @

  24. . ?/ c+ O9 P4 U
  25. void SetSysClock(void)
    / E4 O2 d/ ^  |) k7 Y) g, F: P
  26. {
    * m0 H8 g. E( W2 n
  27.   HAL_StatusTypeDef ret = HAL_OK;
    # h0 B8 a, G& k
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;
    ( Y0 p6 q5 F7 g: |% x0 m. {
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;' a# w8 U& D) T

  30. 0 i6 M' q1 U" g* o3 l9 k
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    : O4 h/ I: v) h: B% P2 v5 A4 ~

  32. , L3 k$ |, [+ p- D8 Y; w; f
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE& ^3 p& T& v' y0 p# g* e5 s* \
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE
    " e. l; v3 Q2 }4 @5 Y2 F
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL1 U8 H$ j4 t; K4 p) h4 Z
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE7 y# M3 q( V4 F
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)
    5 t( J2 V+ [. {2 d
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)7 z4 |" X9 ~% |! {
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    - E6 {& _( ]- N, b$ B" \
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    + H2 A1 N( ?  D, g' {' F
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化2 N! N9 w; ~& m+ q# j
  42.   if(ret != HAL_OK) while(1);- [" v3 C: |6 a- f, o1 p

  43. 5 _( Q# ~7 I: L* U# A/ y
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能
    ' G/ |& C; v* y
  45.   if(ret != HAL_OK) while(1);
    / _7 k4 F% q4 ], R* W

  46. 4 ~" _1 V0 W& U+ J
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2% d" B8 w9 i1 I; C& {# C. f; p
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);. B2 c" Z( @4 p2 K
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
    : P% B4 t# {" Q( T3 d
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1$ U$ R% s' x/ e3 W( x
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4' P2 z& P% B+ L" r$ e9 _
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    + u/ ~9 `6 ?- i; o8 e
  53. - F0 r! v- y' S' ^! |
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。* ?0 j+ \* v- G1 ~8 Y5 g: e- S
  55.   if(ret != HAL_OK) while(1);; g8 s+ ]5 @7 E% g
  56. }2 c5 z* ]3 c) A0 S2 S0 E
复制代码
* g. B8 ~3 i% M. x$ j. v5 ?9 n
* a* y4 K, U' B0 @6 `
8 D1 E$ R* x' Q  z

4 {* A* z+ n; v4 Z+ k+ M3 H/ Y
" N6 v6 `4 W/ W# s7 `; ?4 c- X
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答

所属标签

相似技术帖

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