一.库开发的优势
7 b) k: Z' d$ I9 p) E+ C; e 开发速度快,便于移植。
9 X% o" f1 c* F4 O# X
1 G) C7 N0 H; N% z }/ i二.stm32F7xx几个重要文件
, B }, T3 E: w! @9 G. c% P, W1. HAL库关键文件5 L2 ~9 v B, _; ~/ N) u
9 }; e/ ]2 ~. a/ G, G
6 m8 l7 j8 v" b! S ?) k% [
' _$ @0 h# n- Z8 h1 C2.stm32f7xx_it.c/h
1 M9 [! W9 ~6 @) {' h 中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。# [- u$ |6 S' T1 M4 p
H4 a) R% b# v" E' F+ I" t1 O/ L- {( R: K1 k
; Z; a @. s1 v5 B. ^ g3.stm32f7xx.h: ~) K% _4 M4 T
所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。3 {* U; D9 X' k
! K8 ^' T4 v" @8 c8 g/ [; ~. ]
- #if defined(STM32F756xx); e9 z2 N# ^5 e
& A/ F; L+ k# p" G- #include "stm32f756xx.h"
' ?6 ] k$ ?& _' h - - J! W* \! ^6 P/ q8 N3 z5 s
- #elif defined(STM32F746xx) d5 e, u- u/ A" H& d
# K, ?! y& Y7 h. O& i( g5 ?4 b/ K- #include "stm32f746xx.h"
8 j1 ~, i% L ^6 T, ^, |- C, E1 h- B9 K - ! J6 v# x4 Y% n/ M9 i0 I& ^: ~) Q
- #elif defined(STM32F745xx)
; G9 n$ a% ]1 Y# h2 `1 h - $ @# ^% p. G( p: h. Q6 x
- #include "stm32f745xx.h"
4 f: A4 w2 U. ~6 g- E- G8 t) @ - % J7 ?6 _* O- \, P
- #elif defined(STM32F765xx): B( M# }- c _' b
* Q& s. H/ ^1 E% }9 [ S- #include "stm32f765xx.h"& {, E3 V4 t9 k
- 3 [6 y/ a$ [7 t* q* X2 C
- #elif defined(STM32F767xx)
- \6 j) f4 n' G) }, Q. r - . k% d. ?8 L' \
- #include "stm32f767xx.h"
8 `: A% b1 | N/ n5 j - % J5 ~0 f L5 O# z+ o
- #elif defined(STM32F769xx)2 x' l. l' v) R, x: ?* T _
6 u& b+ t& c2 L5 a# w! x. M A- #include "stm32f769xx.h"( g/ |+ l4 o+ _+ H5 M
: V+ c% j' e) E0 a. d. B- #elif defined(STM32F777xx)
! w. y2 l' B8 m
, ]( S9 X: c6 Z* g9 F7 @2 F- #include "stm32f777xx.h"
5 I& b' p% L3 k& g7 N* \/ g6 U) V - ) Y7 X1 t: N8 r N; T
- #elif defined(STM32F779xx)
8 i2 s) K. k0 _! y* r
) t [3 e/ y0 k, a Y; u6 O" R* F" R3 `- #include "stm32f779xx.h" , E8 ?+ F1 _$ Z7 X
- 6 ?* s* _+ o7 A
- #else: M7 b1 u. r3 T; I. f
+ y" i, v8 E9 ~: V$ @6 S- #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
. L1 Z' }' E$ H. V, q5 \
0 r/ s0 i& o" o" m' ?* U3 q4 ~$ T2 i- #endif
, b% v, N% B% K+ [
复制代码 2 L R5 L* U% g! s" U. n0 C% I: I% Q
4.stm32f767xx.h% i7 I3 T3 k9 E* e; v4 q/ T
主要就是寄存器的声明(一堆结构体和宏定义)。* @) c4 q" v! i
' B* u1 I+ j a! T
5.system_stm32f7xx.c/h" W$ Z' }9 N/ `9 m, q8 M: |9 s
主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。2 U# |( U, K1 d( R+ i/ z; `
2 [- M2 f6 v) E, ?6.stm32f7xx_hal_msp.c0 I0 b% Q( |. [. `, q8 e g
带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。! W; M2 L3 j; b4 C* M' H0 w
4 V& Z0 e/ ]/ d" q1 J1 H( G7.startup_stm32f767xx.s, k3 q0 R6 e2 p; h9 i a
启动文件,上电先运行SystemInit,再运行到main。
3 [& t/ \- f) X5 y' L/ g0 s) R7 W- t* Z5 K$ z K" E
- ; Reset handler( p7 w4 G' ~( y; m: v3 ~+ Z
- ) i5 p9 M8 X( j. P" ^. X' I
- Reset_Handler PROC
; [* Q. a. {4 s% d
/ z: [6 O- X4 G; @& F$ W- EXPORT Reset_Handler [WEAK]* j9 ~, n a' [& a% r
u8 T" J; `9 S6 q) P: E! F& k- IMPORT SystemInit
& e+ M- @4 d1 {. ~- y1 z/ V - ) a$ d( M/ Z0 s
- IMPORT __main
; g9 s9 g; e2 v* s; D; z+ P5 f - ) V4 u7 B0 W2 g5 w {1 r, ~( K/ v
- 0 D2 L, y2 \$ H& t1 R$ `
8 }: q( [6 K* I0 S- LDR R0, =SystemInit
0 t8 q# f6 U" G1 q( X9 f. P( [/ } - . y! b. E+ s7 V& Z& _
- BLX R0
6 N* @" j* v( e* H - - s6 r x$ P$ U |' c1 }& G. j
- LDR R0, =__main
: |! l* \4 e d" \% R - ( C+ s" p; E. r9 P- k+ N
- BX R0
- S( _7 d3 t. D9 g- K) I: S - 0 d4 h' @4 u3 E* @4 [
- ENDP
2 c- L1 }% X0 P* h* K5 B7 x- R
复制代码 1 T: z2 Z2 m3 ?5 U* M( I3 X) F% ^6 t
2 `" A8 }0 k( k$ j" \6 M$ C三.HAL库中__weak修饰符
. T8 t8 A: A: `7 Y weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
9 [- D+ p: |% s5 J6 E( j. J: k/ y" i# G) b
四.程序的执行过程
6 B5 U* V3 Z7 W4 r Y8 R! w Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)* Z2 m- q# i* Y# R5 }
$ t, F6 l# {! i! G) t3 d五.启动文件
( U! e: D& A; _* G( M主要指令:& c+ D4 L2 K7 K, A
4 v* l. H6 W+ I+ R9 q3 L
. ?9 b; X9 Z8 g4 j. L6 ^3 n/ k* @8 M- E' R0 @ C2 [& E7 P
9 N1 e" V( f7 k, g
) c4 g$ @" g e: C6 S* p
9 s+ J6 }& ?/ b) Q5 i9 Z1 qStack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。
1 n6 J# I8 K0 g3 e, L( R; F6 l0 R' S6 k5 j; p% Z" m. A+ G
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
# P; m; y0 S- Z$ N& ^. f" G+ I" [! a9 m
向量表——中断向量服务函数
$ w; M$ A" m3 ]
1 X5 A, ^& ^5 ]7 N复位程序——先进入SystemInit——main
. V; M% O9 T8 G0 S0 ?1 |0 S" h
6 _+ s9 x5 u7 U; N% h关于启动文件详细描述请参考:STM32启动文件详细说明
& A9 \+ }% f) u! N/ b' ]
8 {& g1 O# e% G* S. L; i六.时钟设置(设置系统时钟), X( j; T/ r6 `5 J
- /************************* PLL Parameters *************************************/7 Y# ^( L) J6 t6 B u" Y4 g
- //时钟设置函数
- i. A/ d: X- a; B - //Fvco=Fs*(plln/pllm);
) ~; G- {0 U- w* m3 x1 ?. |" @$ E& w- J - //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));6 Y+ ~( j/ A' g
- //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
6 [! m5 f2 \) S+ [8 I$ {
8 Z! Y# l. s3 |: a; H! |2 \- //Fvco:VCO频率
5 X2 J/ X0 A: x/ f# Q b4 ~. f8 n - //Fsys:系统时钟频率/ I( q" M% `* z' e& }1 C z" J
- //Fusb:USB,SDIO,RNG等的时钟频率7 w E" ^0 Z; P `. W- C, n
- //Fs:PLL输入时钟频率,可以是HSI,HSE等.
2 z2 a0 W+ X+ G% O+ }/ T& w - //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.5 ~% b9 s% m/ m
- //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
' Y. Q8 }+ Z1 D - //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
% b/ v0 D5 t7 k8 A" F0 w - //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.$ p0 Y# b6 j$ i/ D- m D
- W4 L# M1 t2 n7 ~0 M5 [
- //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
. ~6 r1 D% I2 u. q) @% }& ? - //得到:Fvco=25*(432/25)=432Mhz7 T8 P" o% H. E$ s; k5 F# E+ G
- // Fsys=432/2=216Mhz( [# r& c- _6 Q
- // Fusb=432/9=48Mhz
4 h# i3 t: A! O1 O6 G - #define PLL_M 252 `8 C4 |& T, A& @0 O; o$ w
- #define PLL_Q 9& ~9 @9 S% x- C1 ` R
- #define PLL_N 432
3 C# O$ y) R/ o/ j - #define PLL_P 2
5 p" d) p9 x! r4 M1 w( o2 v2 I - , P* p9 {$ N0 P* }0 L! Z' k2 O
- void SetSysClock(void)
/ B. B0 x/ R; f - {
6 s: \( H, P" }7 X, A1 J7 h - HAL_StatusTypeDef ret = HAL_OK;( Z/ ^4 J; L) U0 n) I) Q
- RCC_OscInitTypeDef RCC_OscInitStructure;
' M% f" x) B) _9 W' z& Y# A - RCC_ClkInitTypeDef RCC_ClkInitStructure;
' R6 u$ C' d0 [) e
( Q9 i# i- a! k7 s1 l2 S2 Q- // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟4 n. N$ T$ V, p! j
4 x% h8 x$ }! c0 j* L: W- RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE; //时钟源为HSE
! p) X% L7 @0 k; T { - RCC_OscInitStructure.HSEState = RCC_HSE_ON; //打开HSE
" @2 }6 T3 P7 h5 {% F( o$ G9 l - RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON; //打开PLL) E* a( W; v' d7 I2 k0 C; D/ z# j
- RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE; //PLL时钟源选择HSE9 i2 m: P( I# C }8 T. I# C- u
- RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)+ r2 ^% x+ }. l; T# t
- RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
7 u& `3 `, y3 P U& m7 Y5 J. s% u - RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频) g9 \. B# |/ X" C$ i
- RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频); x1 K, n, ?& H" o' F
- ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化9 @9 C' o. c% q: L i# [
- if(ret != HAL_OK) while(1);$ T" {1 S, r6 }; p0 X
- 4 D1 n- s# W2 X, t$ T
- ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能& x0 z% ` g8 K6 [1 K4 T& ]7 P
- if(ret != HAL_OK) while(1);
2 t2 p2 ?5 S/ w7 ` D( S1 s/ X - " I p! a9 T6 N1 v& ^, \7 P4 {
- //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
. u' o8 e: ^- g/ w" }. {2 M! t F - RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);( a$ g. P: ?% p6 V; o% ]
- RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL/ m! m+ E" t* v' J0 b ~2 R
- RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为11 D( o; F3 c, i2 L' x2 q/ j, V
- RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4" L- |/ Q% O" i2 P$ u2 Z9 C9 F$ I
- RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为21 r- t n. U$ U: G$ n1 P- l, o( ~
% l1 c% I/ G F; Q1 W( t' i5 M9 R- ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。2 Z/ W; y- T; F7 H4 D4 ?2 D9 w
- if(ret != HAL_OK) while(1);
6 M8 s* m1 ~0 R3 S7 i, m# ^ - }% N7 O% `9 P7 K$ P) f
复制代码 Q U7 Y6 V" a, V7 I
: s* p5 }4 _, x
. a* ]( X3 g+ \* u# }3 N4 e0 m b0 h; H
! |# k, r% Z3 f8 E4 n
8 l9 w Z# n9 q0 {4 J! ? |