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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 11:00
一.库开发的优势% l# h; p% n. ~0 ~/ l
    开发速度快,便于移植。
; w1 q8 x+ S. L' ^
) B! n$ I0 _+ z# s7 q" t$ B二.stm32F7xx几个重要文件
  w; `: t" I& z! t1. HAL库关键文件5 L3 r0 g0 V0 R( ?9 q
5 z# w1 i+ _: l; L
B3RQ`@IJHBU@LHI4O{4C]NE.png
! h) Y6 x9 y$ I4 z/ e8 k0 c: t
2 Y" V, D" B/ c, t; U
2.stm32f7xx_it.c/h
! U% k( m' M7 ?3 |) [4 t! l6 g3 l         中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。- J  A# n+ J! h2 w+ B+ v1 ~& C
+ I* [& Y- j! W+ v. k8 X' t

# K& E/ H& A2 [
+ t7 [( @" ]6 v- `6 @+ E3.stm32f7xx.h& r/ J# ^& t/ y6 d) g' |
         所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。3 _2 D2 ~7 s3 ~1 e8 r& s
  e2 o) P4 S. ~2 e
  1. #if defined(STM32F756xx)* V! r4 i! q/ o4 e8 K) {

  2. 8 ?% U: F) i0 d" l
  3.   #include "stm32f756xx.h"  y0 i8 b6 z$ I: o
  4. % _- O% V7 C' J7 ~7 z
  5. #elif defined(STM32F746xx)* R9 X+ @' B' Q+ M) q2 d

  6. ) J5 S2 N3 F) E7 _7 z
  7.   #include "stm32f746xx.h"3 A. B! {$ }: q  V" Q

  8. : r) x5 M, V6 @
  9. #elif defined(STM32F745xx)$ y; T* ]/ i! c

  10. ) A! V6 Y( f2 c. F% J6 U
  11.   #include "stm32f745xx.h"  l& @9 w, p0 q5 [

  12. 7 x0 a9 }- j7 _
  13. #elif defined(STM32F765xx)
    . g$ |$ R! F6 n8 \

  14. 4 l$ e3 R5 A& @& v# B* _
  15.   #include "stm32f765xx.h"
    ) K- j. M$ U$ z' i! a4 n

  16. , N* i3 H5 Z+ U
  17. #elif defined(STM32F767xx)0 J5 F; c* a- q
  18. " M) h) l$ F- T$ ?, s
  19.   #include "stm32f767xx.h"
    ; g0 O+ h2 y! g* G8 R

  20. / c8 C6 Y# B# ]  A3 K0 l
  21. #elif defined(STM32F769xx)" ?; F# K2 s# [# d5 ]; f4 d
  22. & k2 A- B1 H4 s- h
  23.   #include "stm32f769xx.h"
    ( ?$ I% N# d4 \. |& q: b

  24. % J7 v% [2 Z/ t/ G$ s! e
  25. #elif defined(STM32F777xx)* s8 _. t7 A3 F0 }2 F  y& ~

  26. 9 @: Q' B0 r* t" \* W
  27.   #include "stm32f777xx.h"
    5 p9 D8 A- A4 h: u; q0 ?; W
  28. 4 o5 ~8 r/ T. T  a  `3 ~+ q, K
  29. #elif defined(STM32F779xx)
    & K" }; u' f2 R7 M( Q4 K8 E

  30. * ~* e/ y3 ?/ ?4 K# n8 m
  31.   #include "stm32f779xx.h"
      ~, C4 q1 S3 J3 J. V

  32. 3 C8 c: r# |7 N" g& e! @
  33. #else' v/ T. r8 s7 j% F

  34. - c, a6 q) H, ~9 s$ B3 s
  35. #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
    & s/ H, P* ~% y* A

  36. ; x1 Z7 d% t! n1 s( N7 r, h
  37. #endif* t7 k! T) M, W, O& l
复制代码

3 }* d; v$ p6 ~3 H2 e9 ^4.stm32f767xx.h, a/ W- ]2 T/ E5 s/ Q5 T/ j
         主要就是寄存器的声明(一堆结构体和宏定义)。
, f# X% y, `' @0 c6 E2 i9 _' a
. {6 v( s7 |4 }5.system_stm32f7xx.c/h
2 c! _* F! Y  ]         主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。& q# g2 N& Q' p6 V6 ~, P8 Z5 C
, _* L9 _, Y! y; f3 q
6.stm32f7xx_hal_msp.c  M  r# ^" [; G. r
         带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。) q' ?' ^  W/ B5 l: ?9 Q$ O

! a+ V, [) ^- `$ ^' Y7.startup_stm32f767xx.s- Y# C  m# D+ u) }6 T+ M
启动文件,上电先运行SystemInit,再运行到main。
, j8 `9 U/ N& e! ^
- r/ ~5 ~1 O4 x! [
  1. ; Reset handler( p& x8 Y4 n. S& |# O% l
  2. ) f3 A  T/ s. j- `, d; }
  3. Reset_Handler    PROC
    5 k+ `# Q& A& d! `8 R  G$ r! m& ?

  4. 0 y  v6 E8 y# u' O/ N
  5.                  EXPORT  Reset_Handler             [WEAK]6 ]1 h% }. u( \

  6. / ?) `1 G9 A" @2 p7 B5 M
  7.         IMPORT  SystemInit( Y6 Z9 Z0 r3 V8 y
  8. ; i% z# z/ M+ ]/ U4 r& v
  9.         IMPORT  __main
    ! y2 J1 r& C% b/ B+ \/ G  ^5 [

  10. ( [2 c. X: n5 b+ @

  11. : g5 n% J; \5 M' M& X+ S. ^/ @! ]

  12. 6 I9 {3 Y- s5 Q4 b+ J: N
  13.                  LDR     R0, =SystemInit
    . r8 @0 ?5 N( a* Y- b. f: M1 E
  14. ! Z0 k- e7 b" U$ {9 {2 a7 t# b0 Q4 w
  15.                  BLX     R0
    2 ]4 }0 y( W) m5 S* D9 u
  16. ) G  y( S( g8 b. |; {. ]; O) D
  17.                  LDR     R0, =__main% @' j+ d) f% Z3 ~4 q

  18.   D* C3 c. V" D
  19.                  BX      R01 }$ F% v* P& ?2 G; P

  20. - G: Y4 O. p+ h
  21.                  ENDP* h, p: j% c/ Y. |; X! b
复制代码

2 j* S) F5 O! ~- ]) F) Q# C- C, y4 n
三.HAL库中__weak修饰符
- {# b# J  {3 q; z! @3 f. s2 _         weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。/ v% {  N0 j4 V+ k" ?& i0 f
# T3 @' _( Y. m6 D% k- s* ^
四.程序的执行过程
5 I8 A  h% X( D4 f3 s         Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)# V7 j7 ?2 _  v( U0 F
3 s" [$ M# B, f: o
五.启动文件

/ Y' e  Q0 G' c0 @# e主要指令:
/ r/ F# f! f0 I6 H/ d- W6 Y& G* X
5 ~; n1 d2 `& \) y4 q2 w/ U0 `$ v
N@)4NS$@S08L](`A7P41OFB.png
# b, C6 a: C3 L+ \
`)LQ`K7K2(MYBG[7WDTIZFA.png

9 C5 g+ b5 H$ t
# Z; j5 @1 f7 f6 j( r
  z& C, X  c/ o, j: v
* A* W( E; g& x) Z, X9 \Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。% u0 H4 E" q0 w2 Z. ~" c# `( f1 o
( o! K% D" B' J: M5 G
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)# T" W2 J9 D) g

$ T6 ~3 c0 X6 J# ?向量表——中断向量服务函数
. Z* C1 `- F/ o& u5 y4 G6 g( l. ^. M# {' \5 `/ M
复位程序——先进入SystemInit——main- i) z; O& ~6 A1 z7 o

$ ]) ?( X( t0 u, I5 E8 G5 N+ K关于启动文件详细描述请参考:STM32启动文件详细说明- J7 B' z5 [( h) G

9 R% P* z0 H: G1 q0 V六.时钟设置(设置系统时钟)

) D7 d4 m# g- F/ ]0 v" k/ {
  1. /************************* PLL Parameters *************************************/1 l, ]% e( {0 H9 n7 }9 A( R, F* ?
  2. //时钟设置函数
    8 P- @/ ~2 L1 Q- {& `  L& j
  3. //Fvco=Fs*(plln/pllm);
    # G# l$ S8 p( Y
  4. //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
    1 N6 G% K; t7 e- {! f
  5. //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));7 D4 L$ S% Y% j) P7 d3 W

  6. , m/ N. `4 _& v; K# U: e& ~$ t) @
  7. //Fvco:VCO频率
    1 u' B% J" _% D* {+ {7 b) h
  8. //Fsys:系统时钟频率
    2 @& p. n5 T1 d; T
  9. //Fusb:USB,SDIO,RNG等的时钟频率# l% x4 B; m6 D+ \4 @: e
  10. //Fs:PLL输入时钟频率,可以是HSI,HSE等.
    & o. _2 h# N2 P! a8 {& i) |
  11. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.8 R# X3 J' j0 S. ]# w0 d* X6 D
  12. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.! p% @3 `/ _7 Q6 [9 M% I' O' y; s
  13. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)0 c  v" x8 G+ k5 T
  14. //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
    " v' R+ r# P7 l* k6 O3 @5 M
  15. 5 d* T  x# n5 ]8 V
  16. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
    $ H. W7 T2 D- g8 W4 D
  17. //得到:Fvco=25*(432/25)=432Mhz( x' h. r, v" x2 e
  18. //     Fsys=432/2=216Mhz$ ], \9 h! k  I" R8 {& c/ g
  19. //     Fusb=432/9=48Mhz
    - c0 G! W1 I4 l% ?/ Q. t1 i
  20. #define PLL_M            25& A: T" m5 b" {8 O8 t. W4 W
  21. #define PLL_Q            9
    : r1 I: w" r# m3 s- K- d. h' o
  22. #define PLL_N            432
    , s" \' V* @* a5 d( L+ i
  23. #define PLL_P            2* S" ]& E0 s6 _( z% R, b

  24. ; }/ O; {. k' c# f* Q
  25. void SetSysClock(void)
    + `* y8 y; M! I0 s; K" P
  26. {
    $ ?  k2 X* L: b+ D. [9 z) t
  27.   HAL_StatusTypeDef ret = HAL_OK;
    + e' [" x* M( B. `) K3 B
  28.   RCC_OscInitTypeDef RCC_OscInitStructure;% L1 I& a% _* b' p! R1 u. _
  29.   RCC_ClkInitTypeDef RCC_ClkInitStructure;
    : T" f" ]2 A, \+ }) `
  30. / U; F- D& |# q3 R1 n: [; ^* I
  31. // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
    , ?& y5 f  y; g
  32. 1 V6 h3 ^% G! T. s$ V6 M3 _" U& |+ B
  33.   RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;  //时钟源为HSE" Q' {3 P9 y8 u/ z
  34.   RCC_OscInitStructure.HSEState = RCC_HSE_ON;                    //打开HSE7 N6 ^; G) Q9 \2 g7 }4 T5 d7 Q
  35.   RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;        //打开PLL
    ) s( F0 |/ Q& }' y( k- v1 y0 L. x3 U
  36.   RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;        //PLL时钟源选择HSE
    # W# ]0 s7 {! M
  37.   RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)
    & t+ e0 n1 w3 l; w  {& `# ?  A
  38.   RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
    2 q! ~2 o3 y+ T, T0 X/ O
  39.   RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
    ; u/ q; k  H! ]. F" ]6 w
  40.   RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)8 A8 v) M# g7 S8 n
  41.   ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化" N& h# r1 _5 V1 z, x
  42.   if(ret != HAL_OK) while(1);. f4 _! K/ n% C+ a3 ^
  43. 0 V) G* D" P, x+ H9 _2 w" O
  44.   ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能& U$ H4 D( Z% V# H' W
  45.   if(ret != HAL_OK) while(1);
    2 c8 w; x) p, k2 t
  46. : w! X- |: n. N: o7 ^2 F
  47.   //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
    ) q. x; L5 I6 F- f
  48.   RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);5 q) D7 R0 n+ P
  49.   RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL1 q+ V, R5 A9 j* o' f
  50.   RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1% W# ~7 @" F( S' @: Y4 y+ ]4 d
  51.   RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4- o0 |3 d. r* s
  52.   RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2. \$ G5 M, o( u+ P' n( U. h

  53.   a5 C& ]; Q" e9 q
  54.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。! g8 W( X/ _* K$ R2 N* Z
  55.   if(ret != HAL_OK) while(1);3 D3 m$ W. @. ^+ ~9 W& G$ s
  56. }
    % X$ A5 ^6 j# R
复制代码

3 G/ w$ ?% ~4 \9 _8 N/ J8 `1 i& I6 l2 |

2 c# L, `+ }( M3 v6 C  ?. n& ?

8 N7 U0 L/ p; s# f
收藏 评论0 发布时间:2021-12-11 11:00

举报

0个回答

所属标签

相似技术帖

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