启动流程5 P4 X: Q$ {5 @& M4 }) F7 b
H7的启动流程我们再说一下:% h' }0 |* q8 x4 j) Q
! M8 H0 }& }6 P/ f6 }* b
系统上电复位,进入启动文件 startup_stm32h743xx.s,在这个文件里面执行复位中断服务程序。
' N) j7 c$ q7 l' J* n; K在复位中断服务程序里面执行函数 SystemInit,此函数在文件 system_stm32h7xx.c 里面。( B, B( M6 F" a- D
之后是调用启动文件__main,最终进入到 main函数
! e# }0 g, V0 G4 b7 j进入到 main 函数就可以开始用户应用程序编程了。在程序运行之前需要:6 N0 `# H5 }4 f- L" O5 N. B
MPU 初始化,需要用到库文件 stm32h7xx_hal_cortex.c 和 stm32h7xx_hal_cortex.h。
* L2 z# i+ B. [0 p+ `) l1 ~Cache 初始化,需要用到 core_cm7.h 文件。 l/ X" k! x4 M+ Y
HAL 库初始化函数 HAL_Init,对Systick滴答定时器初始化,需要用到文件 stm32h7xx_hal.c。
! P/ e, w. v0 T" x! g1 y系统时钟初始化,需要用到库文件 stm32h7xx_hal_rcc.c5 U6 ]; R5 j* S3 z5 A# q
- f) y j, P6 r3 r9 p1 ~ Z2 i
要注意的是,Hal库的SystemInit函数对于时钟只做了:复位 RCC 时钟配置为默认复位值(默认开启 HSI) 并没有做其他的配置,所以时钟初始化还要用户自己配置。
' Z4 Y7 ^ v3 d/ x/ H
; h+ _; H4 m2 V+ y我们今天关心的就是最后一步的系统时钟初始化
- }* X" S) I& Y7 w% \$ b- L& v8 K* n" o4 ], x9 \# @
上面的四步,在执行完HAL_Init之后,系统还在用内部高速时钟 HSI,对于 H7 来说,HSI 主频是 64MHz; ]; p, x6 ?! `4 o% k
) M/ {' A& K9 q; O
修改时钟配置
0 } d+ F* U, X2 ]那么我们来看下如何修改时钟的配置:. r8 D1 L c Y- V$ ]6 Z$ U
/ {1 B! H6 q& _4 Y+ k+ y% }9 [ r第 1 步:在 stm32h7xx_hal_conf.h 文件配置 HSE_VALUE. g+ p: }0 t+ ?+ W; p# C
配置的大小要跟板子的实际晶振大小匹配。; P6 Z8 ~% w7 I+ W& M' |6 d
+ V7 u3 g& N* A" H- G R
我使用的外部晶振是25Mhz的 所以配置为25000000- #if !defined (HSE_VALUE)
# t3 u7 Z1 Q' N/ I9 e# J - #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
: H; o: o' i9 l - #endif /* HSE_VALUE */
复制代码
+ Q4 X8 _2 }2 r0 p7 C, v第 2 步:然后我们初始化时钟,最主要的就是两个结构体参数和两个函数:- RCC_ClkInitTypeDef RCC_ClkInitStruct; // 配置时钟源相关参数8 k% I" n& O. A+ r
- RCC_OscInitTypeDef RCC_OscInitStruct; //配置系统时钟源及各个外设分频系数
复制代码- HAL_RCC_OscConfig() //配置时钟源相关参数
! v* Y5 F# w2 [. `- p - HAL_RCC_ClockConfig() //配置系统时钟源及各个外设分频系数
# x% }! I) n6 V! T) M
复制代码 ' _; K; C4 V ]' ^, |
HAL_RCC_OscConfig()" A6 u: _$ U, j5 Z( `, r: x! {
HAL_RCC_OscConfig() , 该 函 数 在 HAL 库 关 键 头 文 件stm32h7xx_hal_rcc.h 中声明,在文件 stm32h7xx_hal_rcc.c 中定义。首先我们来看看该函数声明:( `' |2 b" x# p U
: K) I. W, A( s
- __weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);
复制代码 % ]/ I: D, p0 x3 R* p% S3 K8 K* Q
只有一个RCC_OscInitTypeDef 结构体参数,我们来看下这个结构体:
8 l9 \% b$ |, R% J
7 `% W- H, Z0 ]0 {. \- typedef struct+ i& ^0 L @9 |5 u1 _( [8 s
- {
! [" I' n, a! ~ r& G7 x - uint32_t OscillatorType; //需要选择配置的振荡器类型
# k# u- w2 g$ a" z - uint32_t HSEState; //HSE 状态
- _" h( v9 }% A& n2 B - uint32_t LSEState; //LSE 状态
+ }+ ~. a$ c4 Z! u - uint32_t HSIState; //HIS 状态
6 Q* i9 G0 b$ l3 _& w. U - uint32_t HSICalibrationValue; //HIS 校准值
# Y( l8 @5 I1 l; y% d% q @ - uint32_t LSIState; //LSI 状态 / _, A. d% l/ V5 w- X* W9 \
- uint32_t HSI48State //HSI48 的状态/ D' z* B7 z- x k9 I( \9 H
- uint32_t CSIState; //CSI 状态
* D) d2 @0 F# e' L2 c. B# O - uint32_t CSICalibrationValue; //CSI 校准值
9 l4 {, N% y7 S$ p4 N% Q - RCC_PLLInitTypeDef PLL; //PLL 配置
4 M/ S. ^2 R0 n% c$ Y - }RCC_OscInitTypeDef;
复制代码
9 V* N! w3 Y) G# b! C7 D第一个就是选择振荡器的类型,比如我们要开启 HSE,那么我们会设置 OscillatorType 的值为 RCC_OSCILLATORTYPE_HSE,然后设置 HSEState 的值为 RCC_HSE_ON 开启 HSE。对于其他时钟源 HSI,LSI 和 LSE,配置方法类似4 ]( \! W! B. X
4 d5 @- }( I7 {9 F# U1 b7 J最后有一个 RCC_PLLInitTypeDef PLL; //PLL 配置
3 U3 c( f0 j2 `: a
2 `: ~; M V+ B6 H' b u这个就是配置锁相环了,结构体参数如下; b8 o; G' t" s& D
3 r Z9 v, A. l& |6 j- a
- typedef struct
6 t3 P/ ~& V% }( f/ u - {
0 v" O6 }; A! ?: K' a - uint32_t PLLState; //PLL 状态 E3 x" B0 p9 [( i- b+ k/ h
- uint32_t PLLSource; //PLL 时钟源
) H* x0 U; P3 s+ F( v' y - uint32_t PLLM; //PLL 分频系数 M1 `9 y) q9 V0 J* ?1 T* e
- uint32_t PLLN; //PLL 倍频系数 N
( ^: C. I- ]8 ` - uint32_t PLLP; //PLL 分频系数 P3 k* _( ?. l h( K4 j: A
- uint32_t PLLQ; //PLL 分频系数 Q! G% O5 K/ {9 }7 \
- uint32_t PLLR; //PLL 分频系数 R7 I6 i3 y9 ?5 j U, G
- uint32_t PLLRGE; //PLL1 时钟输入范围8 L4 D. F" b' v/ n
- uint32_t PLLVCOSEL; //PLL1 时钟输出范围
( k) D) S8 _ F/ V - uint32_t PLLFRACN; //PLL1 VCO 乘数因子的小数部分; @2 ?* E3 Q+ [2 k# C& L4 F3 N
- }RCC_PLLInitTypeDef;
复制代码 ( Y# B- E: G, Q3 S& D7 R, B9 m8 b
这里的分频系数,全部都是PLL锁相环内部控制,我们要做的就是明白具体的公式就行
/ E4 ~$ W. ]* o, ]) Z% `5 r7 GFvco:VCO频率
* o' C7 B+ A" k# `7 u2 E% UFsys:系统时钟频率,也是PLL1的p分频输出时钟频率 pll1_p_ck$ y; l# B8 s2 s1 b
Fpllq LL1的q分频输出时钟频率 pll1_q_ck) J6 i3 w4 [4 s& H
ref1_ck: PLL输入时钟频率,可以是HSI,CSI,HSE等.
6 j* Q; ~) `$ a: w3 ~+ [/ U+ n; H) k1 Z9 m S
plln LL1倍频系数(PLL倍频),取值范围:4~512.
0 {! n5 P$ b$ B# M/ spllm LL1预分频系数(**LL之前的分频),取值范围:2~63.( `2 @! I# g' f$ b9 A+ S! ]
pllp LL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
, m' B) k B5 _# b9 mpllq LL1的q分频系数(PLL之后的分频),取值范围:1~128.: u: N2 Q6 _5 P* N# o+ h. L
+ D7 d! I2 M5 F L% J) S
% u3 o0 M$ A: f/ h
5 J( b+ F0 E, Z0 h a0 c- VCO频率: Fvco= ref1_ck*(plln/pllm);. [1 n" m# @! N, e" f) N' y/ h
- pll1_p_ck频率: Fsys=Fvco/pllp= ref1_ck*(plln/(pllm*pllp));
x3 Y& o: Q- W - pll1_q_ck频率: Fpllq=Fvco/pllq= ref1_ck*(plln/(pllm*pllq));
复制代码
, j8 h; d2 K J+ P
b' Y& x! Z. P, \/ p; |
2 K3 x" H N4 t0 P7 {6 a9 Y. N9 ^具体的公式如下,上一篇也有讲解
* R, J; E- d/ F+ w& u) E
7 Z! o Q. o& W" Y
, T3 L: `4 V, J' ^" ~1 B" b/ ~( [# o
HAL_RCC_ClockConfig()
' G2 u2 @/ p! I2 G. ^接下来我们就要看 HAL_RCC_ClockConfig()函数,声明如下:* {: s. C) K( Y( u$ ]- ]
2 g1 \) H" i1 o+ g1 p# c
- HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct,
& C! A: o5 H- y* ]. ^/ `6 V/ q4 p - uint32_t FLatency);
复制代码
% c" M8 U$ P$ N一共有两个参数:第一个入口参数 RCC_ClkInitStruct 是结构体 RCC_ClkInitTypeDef6 X; I, i% D, g! S5 e, l
指针类型,用来设置 SYSCLK 时钟源以及 SYSCLK、AHB,APB1、APB2、APB3 和 APB4 的分 t4 e7 u* X" N6 |% R
频系数。第二个入口参数 FLatency 用来设置 FLASH 延迟
5 L0 g5 g0 r8 ]/ F% Z9 c2 Q* j2 L- x& u9 ]( A. t+ Q. ^
我们开看下RCC_ClkInitTypeDef 具体位置在stm32h7xx_hal_rcc.h 中声明- g. e4 Z# o0 c* A- o; |( V& N
l& i/ W0 u6 s
- typedef struct _ a. J, C7 M* I8 I i) V
- {
: b+ m Q$ I& B# s - uint32_t ClockType; /*!< 要配置的时钟。
4 u: [% r* p* j* |' j% z/ F$ K - 该参数可以是@ref RCC_System_Clock_Type 的值 */
! M6 w2 y T( E8 l6 i- a* Z
6 R, o9 F M6 B7 r4 y W" J- uint32_t SYSCLKSource; /*!< 用作系统时钟的时钟源(SYSCLKS)*/
8 y% w# U* M5 M - 4 `0 h& ~# o+ c; R, a- P
- uint32_t SYSCLKDivider; /*!< 系统时钟分频 */
- B- h! K2 W, K2 M! n" z) k2 C
- \! L; c. X8 ^' s8 C; d& o- uint32_t AHBCLKDivider; /*!< AHB分频 */* b8 ?5 B. r: A4 b
- 8 }9 W' j' O8 v( V7 A0 g* u
- uint32_t APB3CLKDivider; /*!APB3分频*/# B- d# E$ z# V, P% l/ a
- 4 x, @3 s7 v3 N6 e# ?, g2 y0 N6 k
- uint32_t APB1CLKDivider; /*!APB1分频*/
7 i1 E5 I! g' p/ \0 t) L$ [3 Q! X$ p - uint32_t APB2CLKDivider; /*!APB2分频*/" n- o4 L. F. ^# Z
- uint32_t APB4CLKDivider; /*!APB4分频*/: O$ {: i( {+ I3 a( s: l
- }RCC_ClkInitTypeDef;
V- Y& f; V( g; O$ Z
复制代码
! `# k5 e$ A4 R第一个参数 ClockType 配置说明我们要配置的是 SYSCLK,HCLK、D1PCLK1(PCLK3)、
2 E' [; Q1 `4 A) d& n5 zPCLK1、PCLK2 和 D3PCLK1(PCLK4)六个时钟。
# }( p+ W. i% n K* Q第二个参数 SYSCLKSource 配置选择系统时钟源为 PLL。
8 ?* L) }* V& {第三个参数 SYSCLKDivider 配置 SYSCLK 分频系数
% {$ b+ E& R# i0 x第四个参数 AHBCLKDivider 配置 AHB 分频系数
6 O9 c1 \# d+ _7 d) A第五个参数 APB1CLKDivider 配置 APB1 分频系数# @ D, P1 s" C: P! v
第六个参数 APB2CLKDivider 配置 APB2 分频系数
4 W1 d- s& W* b2 I% q9 I: I第七个参数 APB3CLKDivider 配置 APB3 分频系数) J$ z5 A h7 a9 K
第八个参数 APB4CLKDivider 配置 APB4 分频系数1 w* v& v- J0 [' c# b
* Z r: L, A, i+ J' ]6 S) L这个在下面有详细的介绍
# A% X3 X8 G3 y3 d
& A. e+ |* C: F6 v6 F2 Y然后我们看第二个参数:FLatency 用来设置 FLASH 延迟和调压器VOS9 w3 ?7 _3 m9 c* L
' b! Q. s: C A4 O, @$ D那就需要知道Flash 读操作9 v r$ |% f) W8 H2 G' ]
' A! [, u2 B# a9 S \) K* v7 _8 J
Flash 读操作 是每次读取完Flash数据,需要延时一定时间,确保之后的数据传输正常
! u6 C: M9 Y6 t9 n: C: C r/ v' E
VOS:在STM32H7中,系统Flash的受到调压器输出电压级别选择(VOS)的影响(在电源控制寄存器中)
* Y" |6 U- p, }" N9 O. u4 f6 K0 E& f2 q
为了得到最高的FLASH读取速度,我们需要设置VOS级别为1 然后等待数设置为4 就可以得到最高的Flash读取速度,ST 官方例程使用的就是 4 个 等待状态数
* w" B [- k9 q- G2 K- ~, S- _5 l9 ^6 N+ |' r& ]6 u/ O
- @8 ^: B5 r* a* `( E8 }5 h# [7 S( ?* u' p/ m
STM32H7xx参考手册 112页# {1 k" Z, ?' [% n1 ]' l8 J# B
7 P4 w% H; [* U8 O最终代码如下:
' z7 H: ]1 J* v, w
|( I3 V9 u# c$ U2 r4 g! i都做了注释
! ]; }6 W6 t8 S, g6 ?! v# o
5 `- w' b" ?( b% g) S/ x- / Z1 U( A7 w5 a' H# v
- + ^! q1 |8 z! i$ p3 T9 t" n( i
- /*
: ]% |3 y: z7 X) l - *********************************************************************************************************
0 Y t3 Y$ i5 V8 v8 ^# ~ - * 函 数 名: SystemClock_Config
3 \/ E* l9 @ U3 u3 ]6 I# W - * 功能说明: 初始化系统时钟
- N( M$ Q/ ~ |* f4 F7 x$ K - * System Clock source = PLL (HSE)- @9 b) D6 ] X9 ~
- * SYSCLK(Hz) = 400000000 (CPU Clock)
) ^! e7 W5 g' w - * HCLK(Hz) = 200000000 (AXI and AHBs Clock)
0 @; @/ d: \- d% B- ~6 M - * AHB Prescaler = 2$ T- Z! s) O2 n( V! d+ g" T
- * D1 APB3 Prescaler = 2 (APB3 Clock 100MHz)" K @' ]# y% w* ?$ P: S
- * D2 APB1 Prescaler = 2 (APB1 Clock 100MHz)/ H0 R: F+ K( K3 F; o
- * D2 APB2 Prescaler = 2 (APB2 Clock 100MHz)* ]3 m+ R q4 }) m
- * D3 APB4 Prescaler = 2 (APB4 Clock 100MHz)6 b g" R# r' g/ d8 b9 ]
- * HSE Frequency(Hz) = 25000000; V2 \4 Q" R( E- b
- * VDD(V) = 3.3
) }) ]$ n, [& q: \0 V - * Flash Latency(WS) = 4- f' w, f( J2 D1 m6 P
- * 形 参:
* C2 A) k) ^( c/ p& k3 c - * plln:PLL1倍频系数(PLL倍频),取值范围:4~512.
3 _! Z9 q+ o/ Z5 {( B- ^1 v: l - * pllm:PLL1预分频系数(**LL之前的分频),取值范围:2~63./ `" h' @6 T! H
- * pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
: U) ~. V1 _: c3 ?( W, |( U - * pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.* w. V9 h4 x+ C9 c" \# m' b Q
- *
+ j7 ^% r5 n& Z W: Z" Z7 @ - *0 |2 k: N2 F; H2 M$ g4 ?, W3 X
- * Fvco:VCO频率0 \, ?% {' n) B& s/ l T
- * Fsys:系统时钟频率,也是PLL1的p分频输出时钟频率 pll1_p_ck( K1 b: g, m& ]# s5 e
- * Fpllq:PLL1的q分频输出时钟频率 pll1_q_ck( I( u* [5 v" w. A q0 P" [! i N. h, `
- * ref1_ck: PLL输入时钟频率,可以是HSI,CSI,HSE等.
% l5 U2 a* C) D; p - *
8 ]* u5 p8 w# C8 \ - *0 S- L: X$ w7 w; S7 ?
- * plln:PLL1倍频系数(PLL倍频),取值范围:4~512.+ [- v/ F" e+ n9 o& C, ]; v2 N
- * pllm:PLL1预分频系数(**LL之前的分频),取值范围:2~63.# I$ j2 k; y0 x8 l( H9 R% R
- * pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)2 H7 j9 v u% X0 g; Y" c" H' R% m
- * pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.9 Y6 j/ J: T6 H3 @- z
- *
- V7 U& K% W8 D - *
# w4 D4 G6 J) L$ h' `. {& W - *+ e# E( r8 j7 \
- * VCO频率: Fvco= ref1_ck*(plln/pllm);
7 a7 w# |0 W# N% M9 P+ v - * pll1_p_ck频率: Fsys=Fvco/pllp= ref1_ck*(plln/(pllm*pllp));6 ^$ r* W- i% L+ _' Q+ R, `7 U
- * pll1_q_ck频率: Fpllq=Fvco/pllq= ref1_ck*(plln/(pllm*pllq));
* U5 V8 O6 P- g; {. U - *
' ~( Z4 i2 m3 w8 k" m1 z - * CPU频率(rcc_c_ck)=pll1_p_ck频率=400Mhz ) ~* y& K% e8 F2 w. d. h
- * rcc_aclk=rcc_hclk3=200Mhz
+ ~2 B5 M$ W$ |0 q- j - * AHB1/2/3/4(rcc_hclk1/2/3/4)=200Mhz 5 H# T& ]) F1 k4 g' y1 n F
- * APB1/2/3/4(rcc_pclk1/2/3/4)=100Mhz & `. `2 X% j8 @% Y7 p1 C" Q6 k
- * FMC时钟频率=pll2_r_ck=((25/25)*512/2)=256Mhz
) v8 Q# R& y. y% n' {- m% d' F! l - *& M) b) e: n4 Y9 T- N% Y
- *- E& O5 y, F( y! h/ a. u
- * 外部晶振为25M的时候,推荐值:plln=160,pllm=5,pllp=2,pllq=2.3 {" m9 o8 E2 ~' |6 @
- * 得到:Fvco=25*(160/5)=800Mhz8 n/ D. Q+ o& P) I) x$ Q
- * CPU频率Fsys= pll1_p_ck频率=800/2=400Mhz- I& I# k/ }7 J$ I4 C a. ^" `
- * pll1_q_ck频率=800/2=400Mhz: w4 n* e' w( ?3 @
- * 返 回 值: 无! l# ^7 J( r |8 E0 o
2 Q7 O. O4 L1 {0 P! o: m5 z- *********************************************************************************************************
- p1 `# ~0 s6 s5 G A& { - */
9 }0 @0 ^0 z9 } - void SystemClock_Config(u32 plln,u32 pllm,u32 pllp,u32 pllq)9 S O) ]* w- X; M, C( O3 T- n
- {
6 C* Z/ v0 J4 \: H5 F/ x* m - HAL_StatusTypeDef ret=HAL_OK;
- G* N G, K1 `* s) q - RCC_ClkInitTypeDef RCC_ClkInitStruct;
# q2 \% k1 d+ g - RCC_OscInitTypeDef RCC_OscInitStruct;
/ ~0 v W4 b) d, K9 p$ ~ - /*使能供电配置更新 */
8 n6 `3 z$ b. H# x" C - MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0);
: a( @* l- q* B) \ -
2 P. e3 N% M' Y; Y; s7 M& m0 a - /* 5 Q0 P9 n6 t- C W/ p5 M. x
- 1、芯片内部的LDO稳压器输出的电压范围,可选VOS1,VOS2和VOS3,不同范围对应不同的Flash读速度,! `. ?* H. k$ W0 M0 t
- 详情看参考手册的Table 12的表格。
, i+ K f4 o6 T+ O - 2、这里选择使用VOS1,电压范围1.15V - 1.26V。
1 Q; d: L' y7 ]* r1 w - */0 l' f2 V. A8 N+ b# x
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);% P5 N( j5 `. V* p* }4 e0 Z9 c
/ d% o! Q! C- W1 t+ \! H0 f# ]- while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {}
1 A+ {; c- j* S* `( O - 9 I0 }) u2 j( f9 b/ a+ H
- 7 X' y- b" @! ?) `* @5 z
- /* 使能HSE,并选择HSE作为PLL时钟源 */; _9 T: l+ n( h' v/ K8 u
- RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE;. l8 ? a( p P) E
- RCC_OscInitStruct.HSEState=RCC_HSE_ON;8 K) f5 [4 t- P- Q2 E6 [& g, g
- RCC_OscInitStruct.HSIState=RCC_HSI_OFF;
: e; ^ k" u) H" i3 N3 ~: t - RCC_OscInitStruct.CSIState=RCC_CSI_OFF;
" l' q" v: l/ E& b* J5 A - RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON; ?" Q5 C$ c9 e2 G6 s, |
- RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE;
# ~# p p, Z" b4 s8 W; T - 2 L; {6 K0 o$ p9 {6 ^$ ^$ {
- RCC_OscInitStruct.PLL.PLLN=plln;
. e: s- h' f2 n. [& l, c- z, B - RCC_OscInitStruct.PLL.PLLM=pllm;8 C5 S+ b' S0 \' k: k# w
- RCC_OscInitStruct.PLL.PLLP=pllp;
% h) E) ~$ E. z" \( z - RCC_OscInitStruct.PLL.PLLQ=pllq;" P3 ?. K O& A; H, L
- ( U) i) \5 y/ k8 U- C% r
- RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
' X9 t2 w) N7 k5 f8 L4 N* q F5 ~ - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;, G3 m. C; l# ` f
- ret=HAL_RCC_OscConfig(&RCC_OscInitStruct);
% _) @+ m- P: R) Y, a5 r - if(ret!=HAL_OK) while(1);$ |- C0 _$ Q/ q% V
+ j$ [' N B0 y1 @ V-
4 m S; f( l4 ?# P8 c - : B' O. O4 i7 E5 w3 p
- /* 1 [6 t8 M, A. f1 r. F, R
- 选择PLL的输出作为系统时钟% G& t% q5 K( U, H4 ] N; D9 g
- 配置RCC_CLOCKTYPE_SYSCLK系统时钟
4 N2 J0 `- a6 E3 w+ o - 配置RCC_CLOCKTYPE_HCLK 时钟,对应AHB1,AHB2,AHB3和AHB4总线
1 \% i1 o' c9 r! F/ ^ - 配置RCC_CLOCKTYPE_PCLK1时钟,对应APB1总线. `1 i6 w. `+ l* t
- 配置RCC_CLOCKTYPE_PCLK2时钟,对应APB2总线
2 `" o" ]0 P" x2 o3 L& d! L1 V - 配置RCC_CLOCKTYPE_D1PCLK1时钟,对应APB3总线; G1 Z" Y; C1 I& ?
- 配置RCC_CLOCKTYPE_D3PCLK1时钟,对应APB4总线
" y7 i% Q' A3 \* _- G7 P - AHB 分频系数为 2,故其频率为HCLK=SYSCLK/2=200MHz。2 W: F% Z: g' `" O7 r3 T
- APB1 分频系数为 2,故其频率为 PCLK1=HCLK/2=100MHz。; n$ @1 x' h+ g: \, }/ h
- APB2分频系数为 2,故其频率为 PCLK2=HCLK/2=200/2=100MHz,
# |5 g8 y6 R0 F5 S" K, l& k( n - APB3 分频系数为 2,故其频率PCLK3=HCLK/2=200/2=100MHz,9 E0 \8 y0 T* L5 Z
- APB4 的分频系数为 2,故其频率 PLCK4=HCLK/2=200/2=100MHz
6 u! d! ]' `& c, E - */
: J$ G/ P& r9 U7 {4 ~ -
3 ~/ I8 a: [3 J3 Z+ Q - RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK|\
" y* @' C& K9 u9 U; | ] - RCC_CLOCKTYPE_HCLK |\
( e2 s* C% Q; J2 r! \# \+ ~, K# G - RCC_CLOCKTYPE_D1PCLK1 |\0 r: o0 z* R$ Z& z% x' t
- RCC_CLOCKTYPE_PCLK1 |\' {8 ]# g! H- M9 i3 g
- RCC_CLOCKTYPE_PCLK2 |\
1 A( f0 s$ I" g: c1 M - RCC_CLOCKTYPE_D3PCLK1);' E% a2 z$ A" [: D$ T8 H- B' ^
3 l/ I+ a0 [, Q l$ H- RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
& F) n/ V/ V9 S; I2 y - RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;
+ o3 z/ F- n6 `/ b' d5 |0 |$ X - RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;. U2 f; z7 Z- N! x) d
- RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2; , d7 c6 B4 L$ L7 D Q8 B% K0 M
- RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2;
* X& S8 j; G$ S& {! S, N' h7 _, @ - RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;
- ?* p+ Y7 a& Q N; i1 p v - RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV2;
0 ~3 k' Q' x" s% }& e6 l; y) g -
! ~- Z' r( [+ F+ Q: ^! z - /* 此函数会更新SystemCoreClock,并重新配置HAL_InitTick */! E! J6 L/ b9 R- p& k7 C7 m
- ret=HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
- ~$ N1 _/ `6 F5 h4 ? - if(ret!=HAL_OK) while(1);
+ z5 R: B; s! R, J - + m4 l9 f' u# B/ M
- $ u4 c, L0 ?7 ?+ D& _8 O
C! o( T5 [/ H% T- /* 使用IO的高速模式,要使能IO补偿,即调用下面三个函数
! H w' ?, E( T* z - (1)使能CSI clock
: V9 d6 z! {9 Z( X0 p - (2)使能SYSCFG clock
- @5 z3 B$ M1 u$ F! i% ~1 s) Z - (3)使能I/O补偿单元, 设置SYSCFG_CCCSR寄存器的bit0& ?2 M, u2 j; x' t) Y
- */
1 z, }# Q; k g1 ^$ |& G- d6 H5 @/ k - __HAL_RCC_CSI_ENABLE() ;
6 G( A8 z$ w m$ {; d# x- I U - $ J. [# F) {7 D: p5 F% U4 z" m2 ?' |3 q
- __HAL_RCC_SYSCFG_CLK_ENABLE() ;
, J1 m4 @( g" X9 q) c# _$ w- } - $ _+ ? g& i. |+ |
- HAL_EnableCompensationCell();
! B& h" x, K% O# s2 R% a( } - ! f7 E2 [9 a; P
- }' N- O0 k/ P% Y y; P& l
复制代码 8 {; |8 B- L3 v. S! y
9 G5 j, h, b: e3 _主函数调用:
: l6 J0 p' j: L: j8 s
- ?* S2 H2 Y' w; M/ p; p- SystemClock_Config(160,5,2,4); //设置时钟400Mhz
复制代码 1 `& l! y7 [( i; W1 j, P: @
3 j) f+ `. V6 i% _$ F: K; F
( }3 j9 ~; S9 C# K' z/ J
, m4 l: X; J% n" [ |