|
stm32时钟系统的意义: 1、电源的开关作用,达到低功耗效果; 2、调节时钟的速度; 对于每个外设,都要设置设置,stm32的时钟系统为了更低功耗; STM32时钟系统框图分析:
4 t1 v/ a0 H9 O$ X! D2 }6 R, s
4 w1 e2 @* w/ m- L# j# t时钟源: 时钟是STM32的脉搏,是驱动源。使用任何一个外设都必须打开相应的时钟。这样的好处就是,如果不是用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果; stm32的时钟可以有以下4个时钟源提供: 1、HSI:高速内部时钟信号stm32单片机内带的时钟(8M频率),缺点是精度较差; 2、HSE:高速外部时钟信号,精度高 来源:(1)、外部晶振 (2)、HSE用户外部时钟; 3、LSE:低速外部晶振 32.768khz主要提供一个精准的时钟源,一般作为RTC时钟使用; 4、LSI:内部低速时钟,提供独立看门狗,也可以给RTC; STM32将时钟信号(例如HSE)经过分频或倍频(PLL)后,得到系统时钟,系统时钟经过分频,产生外设所使用的时钟; RCC设置流程: 1、将RCC寄存器重新设置为默认值 RCC_DeInit 2、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON) 3、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp(); 4、设置AHB时钟 RCC_HCLKConfig 5、设置高速APB时钟 RCC_PCLK2Config 6、设置低速APB时钟 RCC_PCLK1Config 7、设置PLL RCC_PLLConfig 8、打开PLL RCC_PLLCmd(ENABLE) 9、等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET) 10、设置系统时钟 RCC_SYSCLOCKConfig 11、判断是否PLL是系统时钟 while(RCC_GetSYSCLKSource()!=0x08) 12、打开要使用的外设时钟 RCC_APB2PerphClockCmd()/RCC_APB1PeriphClockCmd() 实例: - /*******************************************************************************
+ R+ W6 B& Q9 ~3 a0 u3 N - * Function Name : RCC_Configuration7 x& Z- P7 _" ]* O4 H
- * Description : Configures the different system clocks.3 S4 ~! N0 l I/ @, ^
- * Input : None" t& L9 h' t5 R/ ]5 K$ M
- * Output : None- l- z+ j, u( q2 I
- * Return : None" d. c4 ]# X) U3 @' Y ^ v
- *******************************************************************************/. D4 [ U9 |" n" _0 O% y
- void RCC_Configuration(void)
" ?+ @; q1 \; s/ r' q. b9 U5 y0 M - {
: v. {0 u3 {0 U- e3 S; Z+ C - /*------使用外部RC晶振----------*/4 I8 P% p% |* ?) f
- RCC_DeInit(); //时钟默认初始化
4 C, B4 S4 O3 I5 |8 t - RCC_HSEConfig(RCC_HSE_ON);//使能外部的高速时钟! C+ z# @, H8 @
- while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);//等待外部的高速时钟就绪4 W. d# g' X: H2 r' [; e
% z8 K3 y0 R4 g* s" {& Y- x- c- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能指令预存取$ [" Q' l$ q; h& E- o8 @
- FLASH_SetLatency(FLASH_Latency_2); //等待两个周期! l$ I2 w# ^4 j- O' O% j
- 6 v% [0 p, ^7 G" b' C* X
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟为系统时钟
* x( L; }( ~( |. h! S/ a - RCC_PCLK2Config(RCC_HCLK_Div1); //设置APB2时钟为AHB时钟2 p# _6 ^2 K( y1 v' N$ e5 y3 W
- RCC_PCLK1Config(RCC_HCLK_Div2); //设置APB1时钟为AHB/2时钟1 S6 ^, z/ F' B: h) N9 l( R
- //以下3行是PLL的设置
" o2 X" R ?: N" ^9 A. j - RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //设置PLL时钟为外部高速时钟的9倍频
" X4 Z Z- M1 g$ ] - RCC_PLLCmd(ENABLE); //使能PLL时钟, c5 Z5 N( l8 F- X5 ~4 [
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL时钟使能就绪7 o8 r5 N2 X* y5 ~# v
- //选择为PLL的CLOCK0 b5 B2 N4 _$ g* v# d# z
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //配置PLL时钟为系统时钟' S s: F% O) O/ l
- while(RCC_GetSYSCLKSource()!=0x08); //等待PLL时钟作为系统时钟& X! ?& E; C% Q) q% q
- 3 x/ p/ }1 R# Z+ ?. s
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC);- W) F+ i8 Y* @
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_UASRT3,ENABLE);9 s$ n: t& x0 B( \
- }
复制代码
) c% S, a' m4 d8 b9 p; r
( E1 i9 I% F y8 a6 BRTC模块: RTC(Real_Time Clock)实时时钟; 实时时钟是一个独立的定时器,RTC模块拥有一组连续计数的计数器,在相应软件的配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期; RTC由两个主要部分组成。第一部分(APB1接口)用来和APB1总线相连。此单元包含一组16位寄存器,可通过APB1总线对其进行读写操作。APB1接口以APB1总线时钟为时钟; 另一部分(RTC核)由一系列可编程计数器组成,分成两个主要模块; 第一个模块是RTC的预分频模块,它可编程产生最长为1秒的RTC时间基准TR_CLK,RTC的预分频模块包含了一个20位的可编程分频器(RTC预分频器)。在每个TR_CLK周期中,如果在RTC_CR寄存器中设置了相应允许位,则RTC产生一个中断(秒中断) 第二个模块是一个32位的可编程的计数器,它可以被初始化为当前的系统时钟时间。系统时间以TR_CLK速度增长并与存储在RTC_ALR寄存器中的可编程的时间相比较,如果RTC_CR控制寄存器设置了相应允许为则比较匹配时将产生一个闹钟中断;
+ c. D/ R( V+ E3 v% X2 Y! w
RTC主要特性: 可编程的预分频系数:分频系数最高为220。 32 位的可编程计数器,可用于较长时间段的测量。 2个单独的时钟:用于APB1 接口的PCLK1 和RTC 时钟(此时的RTC 时钟必须小于 PCLK1 时钟的四分之一以上) 2种独立的复位类型: ─ APB1 接口由系统复位 ─ RTC 只能由后备域复位。 3个专门的可屏蔽中断: ─ 闹钟中断,用来产生一个软件可编程的闹钟中断。 ─ 秒中断,用来产生一个可编程的周期性中断信号(最长可达1 秒)。 ─ 溢出中断,检测内部可编程计数器溢出并回转为0 的状态。
: c2 \/ M7 ~( v2 z8 z) n 8 Z) C6 I* w5 z8 y3 z
RTC的一些设置是保存在后备区域中的:RTC_PRL, RTC_ALR, RTC_CNT 和RTC_DIV寄存器; 这些寄存器仅能通过备份复位信号复位,不受系统复位或电源复位的影响; 备份区域复位: 当以下时间中之一发生时,产生备份区域复位: 1、软件复位,备份区域复位可有设置备份区域控制器RCC_BDCR中的BDRST位产生; 2、后备电池和系统电源都没电的情况下;引发备份区域复位; 配置RTC: RTC有两种模式(工作模式和配置模式),要对RTC进行配置,首先设置RTC处于设置模式下;通过对RTC_CRL寄存器中的CNF位置位使RTC进入配置模式;另外,对RTC的任何寄存器的写操作都必须在前一次写操作结束之后再进行,要使用软件来查询当前的状态,同可通过查询RTC_CR寄存器中的RT0FF状态位来判断RTC寄存器是否处于更新中,仅当RTOFF状态位是“1”时,RTC寄存器可写入新的值;(这些是对RTC的保护措施) 配置过程: 1、查询RTOFF位,直到RTOFF的值变为“1” 2、置CNF值为1,进入配置模式; 3、对一个或多个RTC寄存器进行写操作; 4、清楚CNF标志位,退出配置模式; 5、查询RTOFF,直到RTOFF位变为“1”,以确认写操作已经完成; 仅当CNF标志位被清零时,写操作才能进行;这个过程至少需要3个RTCCLK周期; 配置实例:- /*************************************************************************************5 `- k U0 A( _
- **名称 ;void RTC_Configuration(void)
! Y3 o a1 N0 |4 w* k9 \ - **功能 ;RTC实时时钟的配置) U6 ?; G3 d$ B; d/ I; u/ V% z
- **入口参数 ;无
% W7 g6 W8 s9 X& U( Q3 m - **出口参数 ;无6 U: z) p. O L; n4 g7 h5 |
- *************************************************************************************/
# i. e1 K- P9 ]
+ d4 a% o8 |1 E9 W- void RTC_Configuration(void)
. p y, A3 [# F& |! f3 ]- p. y) a, f - {
+ C, p# ]- {# ]9 I C - /* Enable PWR and BKP clocks */ //使能APB1外设PWR and BKP 的时钟' u! T( e! U+ X; Z; s( g* ^
- /*打开电源和后备时钟*/' P. u Z! E- f. r* {" @# F! n
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);, D8 V* f0 j, n; r3 Z5 L- _- a
- $ g/ ~+ L0 n& j3 |0 o
- /* Allow access to BKP Domain*/ //允许RTC 和后备区域寄存器的访问
' c* d$ v6 g9 e" @% }+ K* C) e - PWR_BackupAccessCmd(ENABLE);
9 m5 W0 z+ [# r# K! G8 \( o2 i - 0 t) q6 o+ `- X8 D0 [ c+ F
- /* Reset Backup Domain*/ //将外设BKP的全部 寄存器重设为缺省值
' E: w/ r# S$ B4 ?0 }! @& S, | - BKP_DeInit();
; k" H9 _5 ~$ ~# I, I6 M8 ~5 N. p- j8 c
$ Q* l3 [! u, ]$ O9 }6 H2 @- /* Enable LSE */ //设置(打开)外部低速时钟 T |7 \ v4 g& `
- RCC_LSEConfig(RCC_LSE_ON);
: H" ^# d- k) d% e0 G( g' n6 ?
0 Z3 m5 Z) d1 o- /* Wait till LSE is ready */ //等待外部低速时钟准备好
, P" I# S" c5 y" L( N: g" }+ K, H - while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
5 X* x; s6 D& x6 I7 [2 q( O j - ! |$ {5 \0 @% @+ z9 _
- /* Select LSE as RTC Clock Source */ //设置LSE为RTC时钟
8 a; t* x9 B, \4 _1 ~. E - RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);* d- u: ~$ O: H Y
- 0 p% \9 m9 i( w7 `- H; S& q
- /* Enable RTC Clock */ //使能RT时钟
: }& o2 q! e. ~, e- j$ r5 H. b2 N - RCC_RTCCLKCmd(ENABLE);4 W; a9 X6 i& _8 A4 l& [; f
3 o! L: a. T: g0 N- //开始设置RTC,下面同步原因是:有两个时钟
; E/ [. K5 p: l2 U* D( o: \1 } - /* Wait for RTC registers synchronization *///等待RTC寄存器(RTC_CNT,RTC_ALR and RTC_PRL)与RTC的APB时钟同步
2 z. ]% l# z$ l- g - RTC_WaitForSynchro();0 @/ W! k* q. [7 d
- 1 |8 O( {$ a2 Y/ t; Q# D- I0 J
- /* Wait untill last write operation on RTC register has finised *///等待最近一次对RTC的写操作完成( T/ j- Y' U) T/ o) K
- RTC_WaitForLastTask();
0 B% x3 u0 A4 U7 W
# z5 K* k0 N8 I5 h- /* Enable the RTC Second interrup */ //使能RTC的秒中断
& ~- f( j" Y8 J" I4 I. R - RTC_ITConfig(RTC_IT_SEC,ENABLE);' S. {& C+ {* b, U3 y
- 3 B% x, G" j( B+ n7 A5 I
- /* Wait untill last write operation on RTC register has finised */' N E1 A! j; n* x
- //等待最近一次对RTC的写操作完成6 _5 }, b( }$ C/ e
- RTC_WaitForLastTask();: o5 F, J) }/ l
- ' @0 h/ \$ t7 e1 v# h v
- //分频值为32767+1=32768
, a$ s, G% T0 o- [/ O: |1 p - //计数频率=(32.768khz/32768)= 1hz
1 c$ w; Q9 v* k7 Y! k3 N+ X! v+ I4 H+ I" V - /* Set RTC prescaler : set RTC period to 1 sec*/ //设置RTC预分频的值
' q& V. S- Y5 o2 B0 V9 f - RTC_SetPrescaler(32767);
: Y- G0 C! j$ L% M, G - ^4 n3 G$ @- x5 a6 m" u+ E' J
- /* Wait untill last write operation on RTC register has finised */- C& t7 O+ g+ v
- //等待最近一次对RTC的写操作完成
/ d( u7 M8 B) j5 f! r3 t9 ?3 X% `- Q - RTC_WaitForLastTask();
4 I9 }5 @3 N) X( t u - * q- k+ c, J5 w2 Z) T3 {
- //设置当前的时间值5 u7 k& F) o( m7 u5 m
- /*2014.4.5 10:20:4) b! H6 F% @1 B! b
- *t = 4+20*60+10*60*60 + 5*24*60*60+0 K# O6 O1 f1 E% K1 z
- *5 @2 O) U" V7 v; ]4 _3 H$ @
- */
a1 m" i. m5 V/ u8 v3 b" C - RTC_SetCounter((u32)t);
: V: c9 b# q5 B$ M u9 W0 H - RTC_WaitForLastTask();" v. @3 P" O" y" [, Q8 n
- }
复制代码
5 i' U/ \( c# t w3 b0 @" y |