一.库开发的优势
: U, C- U7 Y6 p% n 开发速度快,便于移植。% G+ [, C, D/ ?0 a# D' G v
8 z( X' [6 l; s j$ E1 m
二.stm32F7xx几个重要文件
" o8 |. C( i' I: d1. HAL库关键文件5 ?$ d) f% y( _
* t2 g& f' A5 B" _/ L! M/ v
8 v A; d) E# H) e9 p/ X# @! D5 T) N% s2 | e# Y
2.stm32f7xx_it.c/h0 v6 W( \) O* l5 R: C
中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。6 ?/ y; _! D& G6 [% \7 j) G) W
* g' E! Q1 O8 a- a4 P$ E
% ~. F9 c# [7 l M4 I9 a& \% g7 }6 c. s3 P2 B5 b* A6 _7 m" g8 ?
3.stm32f7xx.h2 K# p, T7 Z) _4 I }7 Z
所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。
`4 ]+ p+ Z9 e' S! \: j
( u3 m" j: r! @4 |& _- F- #if defined(STM32F756xx)
# P: ~+ W5 P" t" J8 i6 a
5 T7 u. J% I0 U$ Z; f+ J- #include "stm32f756xx.h"
z3 K7 K* @. Y6 c! G. d, }+ y9 V - $ b2 u' C! w1 F4 c) E
- #elif defined(STM32F746xx)
! ?: O( V! E3 p/ D
# X3 o+ J+ I" o8 O6 v% ^$ h$ k7 u. K- #include "stm32f746xx.h"
4 N- X: c7 m7 h" p, L# t7 a9 y - 3 _9 I% K" e9 D1 i$ Q2 X! } }1 W6 k- C
- #elif defined(STM32F745xx)
$ a2 s; g/ Y: p8 d - : }& ?: B2 u2 U2 @. W
- #include "stm32f745xx.h") d7 T9 u$ ~& N; c0 j2 W: _
: o: s( h. l% k4 l$ D- #elif defined(STM32F765xx)" K* T* F4 R! m& }
/ V- ?, M' J& i6 H! F, e8 O/ R8 G- #include "stm32f765xx.h"
5 L/ D/ p. U- V8 h - . I' H' O" X2 E
- #elif defined(STM32F767xx)2 R( ^% o% P. N" m& f6 u5 x3 U
; M, f6 c: |/ V- #include "stm32f767xx.h"6 z8 T3 N3 f, _
- 4 J/ ?+ p+ B5 `' y3 }
- #elif defined(STM32F769xx)! Q9 c1 a3 G4 J6 J! B4 b
" } `% d' ~% x7 h. f% f' J- #include "stm32f769xx.h"
" y+ k2 m5 G# e2 Z
+ y/ f6 e5 O* t ]) J% q- #elif defined(STM32F777xx); I. @5 l. |! @/ ^4 J; b
" L% c( r" R2 r& E3 Z) Z7 F- #include "stm32f777xx.h"
4 ]( p0 ^# a2 k3 W1 {4 K
- c- V8 ]" l( C3 e0 w- #elif defined(STM32F779xx)
% y4 b' ^- r( S/ G0 p0 d4 d+ a
6 Z$ n I0 L7 @& G- w) w) K( C- #include "stm32f779xx.h"
& z' A( T- `6 w* g0 C9 o2 t" Y& C& g - % ?% z$ R3 Q0 ^1 I# ~' i( h5 [3 d
- #else3 f4 q' V7 G5 P$ J) A6 F8 E( O
- 2 L0 }8 ^( v5 V3 w
- #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"' t- p) ?/ d9 w }# U
' ^# F: R0 ~1 p- #endif" U( D% l& w' x
复制代码 5 D! s x, S# X5 X o G. n
4.stm32f767xx.h2 W1 j. Y P4 q- a Z4 h
主要就是寄存器的声明(一堆结构体和宏定义)。
) y7 w) X; m, q: h& ?7 ?7 K
+ m# B' ~# L& r4 N Q5.system_stm32f7xx.c/h$ N* ?" g. ^* K! Q3 Y
主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
' p1 O% A! z0 ^1 z) M6 s3 n" \6 w+ W3 v3 Z r$ n
6.stm32f7xx_hal_msp.c7 I4 ]5 u% W+ g' V/ J( R
带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。4 h' p+ ]+ b, ~
. |7 z/ H. q+ a+ F% L- x- \7.startup_stm32f767xx.s: u% Z1 w- N1 m% ~/ v7 ~
启动文件,上电先运行SystemInit,再运行到main。
, g! w' X! v, O0 f
7 [6 v: p9 i8 c2 b1 I H" \- ; Reset handler* U. T! ]6 C8 ~: D0 a
" {5 [8 w: b" T9 J( W: _- Reset_Handler PROC& ]( b8 b, o& J. B2 F
- / J; O; l. U; v! H& h
- EXPORT Reset_Handler [WEAK]% p( h- w/ Y- r8 W4 G" ?1 c
0 ^; v( {1 P1 s, r- IMPORT SystemInit0 K f6 k+ t9 i& H/ g! V. j0 [
- / N2 j5 _1 @5 }+ e4 p/ ]# e0 w' R
- IMPORT __main6 e/ g% Y5 s6 M: }, |' w
+ k. I0 `( t4 E6 s5 d
* S: f0 R' t, H2 L- 2 ~6 `% M9 ^- |3 n
- LDR R0, =SystemInit1 E6 G& `- ]6 @) t/ h
- * r* w6 Q# b( o2 }0 r; I/ X
- BLX R0+ k% ^$ ~4 O" t6 X, g
- : U, g' p6 @; C U5 p- h% \5 q
- LDR R0, =__main/ ]. Z5 l" m3 E* T; x, |( s
' [6 q# y/ ?& W1 f% \4 {- BX R0
! ^ J: I0 U P' }1 n: b: n
1 o+ J Q; x# }- ENDP
' G j+ |( G$ |$ j r' C. ~9 C! h
复制代码 $ e- g/ U& N) L( z0 q. U
/ c t1 g( b6 H' h6 s7 [三.HAL库中__weak修饰符
7 k/ S# @% A$ F8 N weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
- I3 Q; X/ f1 D( ~/ |2 _
: Z8 F6 S7 i4 M; e6 P( A$ R# A四.程序的执行过程7 j* W4 O' M' s7 Y; A% Y9 S2 q" h
Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)
1 Y* @) v/ |) Q# _8 x+ z2 }4 u+ O& Q/ w
五.启动文件
# z/ ? X& ]; k' C# ^主要指令:
5 S- i; D4 ]/ y$ |7 j; l ?0 ~/ E1 E- Q8 a# x
I7 t: `. F* R. X) m( E- B0 m
n4 P7 q, z9 Y' w S* Z' {1 \! y) o
) I. r# g9 m0 ]
% ?; o7 c) G# ~0 K: C' ^Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。 P C* Z. r& ]/ A7 p9 x
9 R7 }4 M g b* w9 F) s, P+ r% yHeap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
6 B5 O* P( a; o
. p1 u+ E9 B0 z9 w/ B9 {- H/ K向量表——中断向量服务函数
6 V' R- s; A/ I- X$ s/ V7 p9 h- `* N9 `, @6 Q5 `$ r
复位程序——先进入SystemInit——main0 P) S: p! K# y$ n
' p$ `3 }4 s& W% I& A$ ~& Q3 k关于启动文件详细描述请参考:STM32启动文件详细说明1 y% q8 W9 y* S8 j
' q% l7 `9 N+ C
六.时钟设置(设置系统时钟)" M* ?3 Q2 _. D: Q5 t8 I
- /************************* PLL Parameters *************************************/
1 t( E8 G/ R" Z& W: h% u% W - //时钟设置函数
8 V3 Y" K; ]( J+ o7 p! j' ^' @+ H - //Fvco=Fs*(plln/pllm);( V! o0 H9 \2 i/ L$ w7 m- [5 ~/ Y# w; D
- //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));' D8 z' N5 u6 }$ u; S& }5 v
- //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
* f# E7 K6 O z( H/ w! I* V0 R4 L: b1 q
9 x }" T" Z% q# q- //Fvco:VCO频率/ |& d9 _# J* Q* G( [1 g9 n
- //Fsys:系统时钟频率
/ }5 Z( [8 I0 w1 V4 i F ]$ L - //Fusb:USB,SDIO,RNG等的时钟频率4 ]- S1 t5 r' ~; F+ b% |5 E" U# c: K
- //Fs:PLL输入时钟频率,可以是HSI,HSE等.- H5 r) w4 U5 P3 @: R
- //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.& `' y5 Z1 r2 y' ? R' k
- //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.) V! {7 J B- ?+ \& G3 B
- //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)3 S8 e! D0 J7 O
- //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15./ a' }$ y5 F8 r: a$ m( h, M5 r
- ! c8 M0 p1 U$ n; ]8 n m
- //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
G5 Q! h1 a& |" x( L: } - //得到:Fvco=25*(432/25)=432Mhz- F K/ m* s9 i2 c$ j0 T
- // Fsys=432/2=216Mhz
; R, s& g3 n# i; c& A - // Fusb=432/9=48Mhz q# w5 @9 y5 i4 k! f9 ?, v6 X8 a7 U
- #define PLL_M 25
/ t5 ?2 W. P! q - #define PLL_Q 9* { ]8 M2 l( b0 g9 n9 n$ Q% M
- #define PLL_N 432
6 L6 m7 z1 o; a; [& k" b0 o8 V3 Z - #define PLL_P 20 a. F. v/ m! N s, S, @6 k
- 9 F* M0 v6 g; g" a, k
- void SetSysClock(void)8 \# U. \+ K7 f
- {/ Y4 i7 P; d8 I
- HAL_StatusTypeDef ret = HAL_OK;
, s5 O+ W1 z$ X, A - RCC_OscInitTypeDef RCC_OscInitStructure;0 e1 t8 z1 @% h- }& F
- RCC_ClkInitTypeDef RCC_ClkInitStructure;: ?/ u* \( `% `+ U* O+ w& {
- $ k: v& \) D9 a8 i* q
- // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
& J6 i1 N" g/ n1 y/ ~/ b8 A( J - * p; ]$ U* {6 Q( e6 ^
- RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE; //时钟源为HSE
5 ~& j8 o( L! j- K$ i: R/ i - RCC_OscInitStructure.HSEState = RCC_HSE_ON; //打开HSE
! i" {+ ?- A+ e! t0 @. U8 V+ D( R0 Z - RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON; //打开PLL
$ K6 L- k; R6 Q2 ~: @ - RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE; //PLL时钟源选择HSE
1 A# F( L, V% k - RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)8 K; `5 x9 G$ j! n5 x- i; v& H+ b
- RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
" C" Q$ D8 i, b+ q# _$ p0 w - RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
) N `& p: o" n - RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)) k1 Q/ H. I c) `) K& @
- ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
* j7 ^5 K7 E$ \0 a9 r - if(ret != HAL_OK) while(1);: d# y; Q/ [! v* G0 U) @3 O
, {4 u. \1 b1 {2 C0 t- ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能 ^' f, V' c9 f
- if(ret != HAL_OK) while(1);
! i0 Z) Z9 O$ U' G, ^8 V' Z! _ - - G3 G, h4 m. L( x6 i
- //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
4 ~, T, p V% x6 F' b - RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);4 M0 ]( a8 o/ X. p. m: m$ h
- RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
) f3 A1 W! n" y: N% B& g+ }' O8 `3 w - RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为14 {7 n2 X6 X5 Y/ k T" p
- RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为44 {3 b. X" j: D9 i! ?% e
- RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为29 c, x( ^4 V6 A" G
- 3 ?! ~" @. v \- Z' W$ ]; Q
- ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。
; e0 t; {( T+ i9 R' b; w! B - if(ret != HAL_OK) while(1);
! d! }4 n+ ]7 o# B# U' [ - }$ @: F* K& P; E9 Y# J+ H6 w
复制代码
$ O' i# g" o* e( J0 s4 ?' m" _( ^, B$ C) C. s( H
9 @4 c6 Q: d% r/ L
9 I C9 a& D2 A* z4 Y- D1 p H- o$ b
|