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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势
: C; Y$ H; O6 `' z    开发速度快,便于移植。
% n$ v6 W. j* Y5 q2 R# u* G3 [3 s2 [
二.stm32F7xx几个重要文件, j  h0 ]6 S: z) b' M
1. HAL库关键文件0 i6 a2 d$ O* Z9 b' Z2 O

) J* S! @8 n! ~
B3RQ`@IJHBU@LHI4O{4C]NE.png

7 d0 j* n7 F. p& T
+ x$ r" G5 Y' y$ P- p2.stm32f7xx_it.c/h
* W- N' u! `0 @: [0 G- i         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
( M; U$ `( w' l5 [! R3 e( D/ E# q/ A2 F2 g3 I5 q% ]
5 x: C# y9 ^# ^
* Q* z& {% i7 f3 e9 z
3.stm32f7xx.h
7 [& p5 h9 t9 I, t+ h5 |0 Q3 Q; {         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。
1 d  R4 h2 B7 g
+ G- f  _2 P" a/ |. E% C
  1. #if defined(STM32F756xx)' A- ^, j2 K7 B6 B8 \, E& H6 L0 Z+ `

  2. # ?9 Y* X9 W6 i/ x/ c
  3.   #include "stm32f756xx.h"5 r5 h3 l& W8 l2 ^; F& k

  4. 8 p# C" S4 ~. l- b* i
  5. #elif defined(STM32F746xx)2 h4 @/ N2 ?) \3 G) ~" I, b+ g
  6. : y3 w; ~9 r; b1 A0 S( u6 q5 v
  7.   #include "stm32f746xx.h"
    : g3 s7 F: j6 H' ]3 m- S/ C

  8. 4 n7 X+ W! M  M3 m0 z" m, x! U
  9. #elif defined(STM32F745xx)
    ; ^+ a! p# l3 s! }

  10. 4 O' d- {: }( M: @6 w( m, ]
  11.   #include "stm32f745xx.h"! w/ T" X2 y- B+ e
  12. ! X1 y) Q8 |3 d, n7 ^6 `
  13. #elif defined(STM32F765xx)$ _' |2 O3 c+ S

  14. . f) E, r% W' ~' \- @
  15.   #include "stm32f765xx.h"6 P1 O3 h( o8 c1 x& A0 B. }
  16. ; T& [3 u3 t% \" W
  17. #elif defined(STM32F767xx)! y: }6 x1 Y6 B  _

  18. 1 L$ p. n, U6 |. C
  19.   #include "stm32f767xx.h"
    & j7 g. n/ p! y4 d5 r

  20.   _+ ]0 ^, n7 C# P/ M
  21. #elif defined(STM32F769xx)
    & d$ E  F7 j# M. d% f

  22. / ~' ~+ ^4 X/ c; Z& E
  23.   #include "stm32f769xx.h"
    # y- w) S" U1 D0 W
  24. . A2 h' f( T- b0 d; X, r
  25. #elif defined(STM32F777xx)
    " Q; O" k$ y2 {; ]* ^

  26. 0 E" z7 U1 c0 v3 w( i: ]
  27.   #include "stm32f777xx.h"
    8 ]: F& M6 b9 @& t6 g2 t1 Z

  28. - e' s$ w- ?) o
  29. #elif defined(STM32F779xx)% N0 ^' o" M, k) s  t- z

  30. ' r+ D9 o0 {4 v* b8 t: @% s% h
  31.   #include "stm32f779xx.h"
    4 ^: v/ i9 u: S

  32.   [* U! ?  K1 m( {4 j+ b. l8 l7 v" Q
  33. #else6 K  \' n4 h- }: I

  34. " y7 `$ q3 p6 d+ {
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
    - M/ j9 _: ^7 m' u, d$ d" |
  36. ; P. N) u6 Y/ }4 t4 u( h3 \
  37. #endif7 |8 N1 d) R, l1 B' r* W0 ~7 f1 z' o
复制代码

# b+ z+ I/ T7 U+ X& e$ y4.stm32f767xx.h
+ I# K6 L/ l- Z9 |         主要就是寄存器的声明(一堆结构体和宏定义)。( H6 z3 h3 d) m7 m/ G; \  e

* J. b0 B+ i2 X0 _5.system_stm32f7xx.c/h1 j2 y7 {: ^, T
         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。/ q+ ?3 ~2 X' V: _/ e4 L
% |" W& k' q% [  U4 e5 T
6.stm32f7xx_hal_msp.c0 Q2 B& I& O; K
         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。
2 |9 P/ I6 x% g( o& }9 m5 U* o7 N/ X7 V
7.startup_stm32f767xx.s
* h% h) ~& `( `: p启动文件,上电先运行SystemInit,再运行到main。* v" f. q0 c: d  d" R* L

- h* [: M) K. @
  1. ; Reset handler: ^9 _# x# H, U  {# z

  2. 7 R/ r: k7 T# m: p- L4 A8 q' w
  3. Reset_Handler    PROC
    2 \( w' H3 R* l
  4. 5 _* u7 n( F* L/ C: u2 }
  5.                  EXPORT  Reset_Handler             [WEAK]
    0 G/ C* u# ^/ M8 {! U2 g9 ^1 [

  6. , I, H& ~: s/ E. S3 z
  7.         IMPORT  SystemInit+ @+ _6 I+ G' u; G% ^- b
  8. + o+ v" h7 t3 u  g+ b% O
  9.         IMPORT  __main
    + B( u* P% R* j% q! L7 {4 j
  10. & c# C* R% p( C7 ~1 c- \5 E

  11. . v! h' B/ Z+ i. s9 b3 D. g
  12. 0 v; L  r1 I' i# O9 q- s" h* N
  13.                  LDR     R0, =SystemInit& R! _% _! z$ x1 G, A( L) n

  14. 2 x+ J5 T6 x0 w9 q
  15.                  BLX     R01 B" e7 r& g! Z$ t  H- h/ {
  16. 4 D- `1 `' J6 Z+ j. r
  17.                  LDR     R0, =__main0 t) _- U. ^9 s8 ]9 `

  18. # Y! v  n: ?: p8 x9 A' P
  19.                  BX      R08 {7 n6 ?' X. p" Z

  20. 8 P0 Y/ F0 U% {" F
  21.                  ENDP" s+ z/ v. s/ \2 P: I9 M
复制代码
" F/ c9 z! o, I& D

9 A* j$ a* `" n4 G+ P三.HAL库中__weak修饰符
( j3 ]. T- C5 y/ s2 H0 L         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
$ o0 l1 P  ?7 o' [5 e/ h* `3 o- Z
7 o3 q+ x9 S5 ]8 J: f5 N# _四.程序的执行过程
2 J, _$ ]9 v. H- D& T         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)! J$ U6 W( [4 G; \, f. R

3 K( `! E. ?4 }6 r$ s五.启动文件

# k9 @3 Z- q1 }9 P8 s主要指令:; c  ~$ a' ]6 y+ T, `
% M" a( j, k) G) F* t
N@)4NS$@S08L](`A7P41OFB.png
/ S3 ]4 A. J- Y5 j0 p" Z( k. L3 E: ~
`)LQ`K7K2(MYBG[7WDTIZFA.png
: l! _" q3 f8 ?- a
) F8 J! H6 ]* H  T$ I

0 t9 i* K- s. E* }0 M
3 S: d( [/ z; Q3 B& xStack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。% C# j9 ^- i* V8 D* A
! @# D/ O* E: {. }& U& g6 g: v
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
" [0 x7 j7 \5 ]- H9 x) e
# J/ F. e) y. U向量表——中断向量服务函数
" `2 `1 O9 m! [* O
$ ~6 p& v* `$ h) f4 n1 t7 l8 q复位程序——先进入SystemInit——main; Z( a! D( n- M8 b$ S2 |& T
3 x9 B0 q- Z; u& h$ f  m* ]
关于启动文件详细描述请参考:STM32启动文件详细说明6 d) K3 \+ k+ `& H
- `) D# \8 |5 z
六.时钟设置(设置系统时钟)

3 i8 f+ M$ @) @" b( W
  1. /************************* PLL Parameters *************************************/
    : B& U7 |6 ?0 F$ k
  2. //时钟设置函数$ E8 A" _* l# z& I
  3. //Fvco=Fs*(plln/pllm);: J4 l0 g. H/ k
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));3 e& B; P. H, j! \; E
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
    ' y9 H5 G) j9 _7 H& O, d2 c

  6. ' n: H" z$ b2 S% _' ^& p
  7. //Fvco:VCO频率
    0 L! m, B6 V/ ~% Q( p) E
  8. //Fsys:系统时钟频率2 p2 n$ M! F  V/ ?
  9. //Fusb:USB,SDIO,RNG等的时钟频率
      I" V& f) h9 c( S
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.
    & s# C: x( d- F1 j. o
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.* m* b8 N6 p5 @) i. @* M
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
    $ v. q& m( X* b$ X
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)6 I& P- C$ g& m8 [  L
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
    * u5 A, E2 E' U" S

  15. 9 Z4 `; ~% Y6 O) G# ?- a/ Z# [
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.! J' P1 X4 y  G2 c: @6 |- t$ z" c1 \
  17. //得到:Fvco=25*(432/25)=432Mhz
    : J" z6 H/ o3 \9 B3 l8 n% D
  18. //     Fsys=432/2=216Mhz
    : J3 K; _" }- F6 E4 p& C* s
  19. //     Fusb=432/9=48Mhz
    * y3 D& m  D. ~& e; \
  20. #define PLL_M            257 V0 W  W- _4 p. S9 G
  21. #define PLL_Q            9
    ; K4 G* o1 e' ~5 z" ~  O
  22. #define PLL_N            432
    8 @% B$ B1 k8 j4 F+ l) A
  23. #define PLL_P            2* L. A; m1 ^+ y$ ?1 `' D

  24. ; x- B( `9 D% T" m; X/ n
  25. void SetSysClock(void)3 ?" L! W% D3 h4 G' a9 k
  26. {
    ' {2 q4 ~# L& q, i% ]
  27.   HAL_StatusTypeDef ret = HAL_OK;* g' E0 X0 C- E7 ~, j
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;; p8 D( S; Q4 P( T7 N: w
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;; G7 N0 m* h9 o

  30. " |3 g: J6 G0 Q1 h9 j
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    0 D4 w# G- z* P' I

  32. 9 p% t% I+ t& l- N& c
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE! p; V  ~/ c0 l, w9 X, v# {: S: Z
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE
    ; X( @1 [& R  G
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL" \' \3 Q$ ?9 T: r4 J+ P# d, u- N8 j
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE/ H1 v5 Z  r& L  Q
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)2 V% y7 J8 ~; g5 m5 ?. ]* E: O2 I
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    9 _1 B; h7 a6 v9 G7 n' I
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    8 K4 k/ A: w  g/ ]  z
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
    - l( G2 f2 D' B( B& Y& F
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化! }! {+ y1 C7 g/ F
  42.   if(ret != HAL_OK) while(1);
    ( O& `/ @: e0 V; B

  43.   {8 Q. C3 I) n- u
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能
    * \- x! a. j8 F( T+ O8 S$ X
  45.   if(ret != HAL_OK) while(1);
    # T1 n: \% B1 [( R% b

  46. # P+ g; T- c: \; U
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
    ; N3 ^- y4 q0 R- K1 w, q8 v3 `7 a8 K
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    & Z) `) `$ C" N7 R
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
    & U7 q3 A3 T0 o  l6 A  R
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1& N4 Q; A" |8 |
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4  Y8 ?% e0 I8 b* @
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
    ' T3 Q! X" t, T  T

  53. 0 f, w8 Z* R3 E, {; ]
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。# @, H& S. W: ~. t3 N% h( E7 P
  55.   if(ret != HAL_OK) while(1);( t3 d7 O8 U# y3 o( M
  56. }4 {: c8 _/ I- J1 X" s
复制代码
& R' c" X' e  g: [

# T2 d' J  q' n1 V# u3 |) }! B  l  Y9 G0 i8 ~) h7 E* y# {( ~

) Q% a0 {0 M  g5 ?9 h- b9 p- w" l! p6 K$ ]2 U  `* U+ U
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版