为什么stm32要设计如此复杂的时钟树?
大大节省功耗,需要用到的外设开启时钟,不需要的则关闭,这将大大节省功耗。
系统时钟要了然于胸,脑子中得存储着时钟树框图,能复述具体时钟的配置过程。
一、总体时钟树框图
时钟源(如上图的左边4个蓝色框所示):
HSI RC
HSE Osc
LSE Osc
LSI RC
倍频器与分频器:
PLL 锁相环、TIMx Multiplier,起倍频作用。
AHB Prescaler、APB1Prescaler、APB2Prescaler、USB Prescaler起分频作用。
时钟输出:
HCLK:内核CPU时钟
PCLK1:外设1时钟
TIMxCLK:通用定时器时钟
PCLK2:TIM1时钟
ADCCLK:ADC时钟
USBCLK:USB 48MHz时钟
RTCCLK:RTC时钟
IWDGCLK:独立看门狗时钟
MOC:可以选择输出SYSCLK、HSI、HSE、PLLCLK的其中一个,用示波器连接此接口判断时钟是否故障。此接口也可提供晶振。
css时钟监视系统:
自动切换时钟来源
通常以HSE作为时钟源产生HCLK供CPU使用,万一HSE失效了,CPU就无法正常工作了。为了增加健壮性,stm32时钟系统中使用css时钟监视系统,在HSE失效的时候,产生中断,自动切换选择HSI作为时钟源。
二、主系统时钟
2.1 总体介绍
追溯根源,起时钟来源于 HSE 或者 HSI 。
HSE、HSI 可经过 锁相环 倍频后作为 SYSCLK系统时钟 ,或者直接作为 SYSCLK系统时钟 。通过SW进行选择。
SYSCLK系统时钟 经过 AHB 预分频器 分频后,作为 FCLK时钟 (作为CPU时钟)、HCLK高速时钟(用于高速外设,比如内存控制器,中断控制器,LCD控制器, DMA 等)。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB1 预分频器 分频后,作为 PCLK1时钟 (主要用于低速外设)。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB1预分频器 分频后,再经过 TIM2,3,4 Multiplier倍频器 倍频,作为 通用定时器的时钟。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB2 预分频器 分频后,作为 PCLK2时钟 。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB2 预分频器 分频后,再经过 TIM1 Multiplier倍频器 倍频,作为高级定时器的时钟。
SYSCLK系统时钟 经过 AHB预分频器 及 ADC预分频器 分频后,作为 ADC时钟。
主系统时钟大体如下图黄色所示。
2.2 细分介绍
HSE时钟
HSE :
High Speed External Clock signal ,即高速的外部时钟。
来源:
无源晶振( 4-16M ),通常使用8M。
控制:
RCC_CR时钟控制寄存器的位16: HSEON控制。
开启HSE的时候,需要一定时间来起振。
根据RCC_CR时钟控制寄存器的位17: HSERDY 来判断起振是否完毕。
HSI时钟
HSI :
Low Speed Internal Clock signal ,高速的内部时钟。
来源:
芯片内部,大小为8M,当HSE故障时1系统时钟会自动切换到HSI ,直到HSE启动成功。
控制:
RCC_CR时钟控制寄存器的位0 : HSION控制。
控制原理同HSE。
PLLCLK锁相环时钟
锁相环时钟:
来源:
(HSI/2、HSE)经过倍频所得
控制:
CFGR : PLLXTPRE、PLLMUL
注意:
PLL时钟源头使用HSI/2的时候, PLLMUL最大只能是16,这个时候PLLCLK最大只能是64M ,小于ST官方推
荐的最大时钟72M。
如果需要在应用中使用USB接口,PLL必须被设置为输出48或72MHZ时钟,用于提供48MHz的USBCLK时钟。
HCLK时钟
HCLK :
AHB高速总线时钟,速度最高为72M。为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟(SysTick)、为内核cpu提供时钟( FCLK )。AHB : advanced high-performance bus。
来源:
系统时钟分频得到, -般设置HCLK=SYSCLK= 72M
控制:
CFGR:HPRE
PCLK1时钟
PCLK1 :
APB1低速总线时钟,最高为36M。为APB1总线的外设提供时钟。2倍频之后则为APB1总线的定时器2-7提供时钟,最大为72M。
来源:
HCLK分频得到,一般配置PCLK1=HCLK/2=36M
控制:
RCC_CFGR时钟配置寄存器的PPRE1位
PCLK2时钟
PCLK2 :
APB2高速总线时钟,最高为72M。为APB1总线 的外设提供时钟。为APB1总线的定时器1和8提供时钟,最大为72M。
来源:
HCLK分频得到,一般配置PCLK1=HCLK= 72M
控制:
RCC_CFGR时钟配置寄存器的PPRE2位
三、其他时钟
3.1 RTC时钟
RTC时钟:
为芯片内部的RTC外设提供时钟。
来源:
HSE_ RTC ( HSE分频得到)、LSE (外部32.768KHZ的晶体提供)、LSI(32KHZ)。
控制:
RCC备份域控制寄存器RCC_ BDCR : RTCSEL位控制
3.2 IWDG独立看门狗时钟
IWDG时钟:
来源:
由芯片内部的 LSI RC 提供
控制:
略
其他时钟如下图标号D所示。
四、MCO时钟输出
MCO时钟输出
MCO :
microcontroller clock output ,微控制器时钟输出引脚,由PA8复用所得。
来源:
PLLCLK/2 , HSE、HSI、 SYSCLK
控制:
CRGR:MCO
查看下图E。
五、stm32时钟系统的编程
5.1 系统启动文件的默认时钟配置
在启动文件中,SystemInit()函数就对系统时钟进行了配置。
SystemInit() 后时钟频率大小:
PLL 主时钟=72MHz
SYSCLK (系统时钟) =72MHz
AHB 总线时钟(HCLK=SYSCLK) =72MHz
APB1 总线时钟(PCLK1+SYSCL K/2) =36MHz
APB2 总线时钟(PCLK2=SYSCLK/1) =72MHz
5.2 自定义主系统时钟配置函数
时钟使能配置函数
时钟源使能:
RCC_ HSICmd
RCC_ LSICmd
RCC_ PLLCmd
外设时钟使能:
RCC RTCCLKCmd
RCC_ AHBPeri phClockCmd
RCC_ APBxPeri phCl ockCmd
设置时钟流程:
将RCC寄存器重新设置为默认值
RCC_Delnit
打开外部高速时钟晶振
HSE RCC_HSEConfig(RCC_HSE_ON);
等待外部高速时钟晶振工作
HSEStartUpStatus = RCC_WaitForHSEStartUp();
设置AHB时钟
RCC_HCLKConfig;
设置高速APB时钟
RCC_PCLK2Config;
设置低速速APB时钟
RCC_PCLK1Config
设置PLL,主要通过修改PLL的倍频系数改变系统时钟
RCC_PLLConfig
打开PLL
RCC_PLLCmd(ENABLE);
等待PLL工作
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
设置系统时钟
RCC_SYSCLKConfig
判断是否PLL是系统时钟
while(RCC_GetSYSCLKSource() != 0x08)
代码:
#include “stm32f10x.h”
/*******************************************************************
*函数:void RCC_HSE_Config
*功能:通过修改pll的分频、倍频系数改变系统时钟
*输入:
u32 div, HSE的分频系数1-2:RCC_PLLSource_HSE_Div1、RCC_PLLSource_HSE_Div2
u32 pllm, HSE的倍频系数2-16:RCC_PLLMul_2、RCC_PLLMul_3、、、RCC_PLLMul_16
*输出:
*特殊说明:
*******************************************************************/
void RCC_HSE_Config(u32 div,u32 pllm)
{
RCC_DeInit(); //将外设RCC寄存器重设为缺省值
RCC_HSEConfig(RCC_HSE_ON); //开启外部高速晶振(HSE)
if (RCC_WaitForHSEStartUp()==SUCCESS) //等待HSE起振
{
RCC_HCLKConfig (RCC_SYSCLK_Div1) ;//设置AHB时钟HCLK,1分频。HCLK==SYSCLK
RCC_PCLK1Config(RCC_HCLK_Div2) ;//设置低速AHB时钟PCLK1,2分频。PCLK1==1/2HCLK
RCC_PCLK2Config (RCC_HCLK_Div1) ;//设置高速AHB时钟PCLK2,1分频。PCLK2==HCLK
RCC_PLLConfig (div, pllm) ;//设置PLL时钟源及倍频系数
RCC_PLLCmd (ENABLE) ; //使能PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //检查指定的RCC标志位设置与否,PLL就绪
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟SYSCLK来源 设置来源为PLL
while (RCC_GetSYSCLKSource() !=0x08) ; //返回用作系统时钟的时钟源,0x08:PLL作为系统时钟
}
}
int main(void)
{
RCC_HSE_Config(RCC_PLLSource_HSE_Div1,RCC_PLLMul_5);
while(1)
{
}
}
我们使用软件仿真观察实验现象。
进入仿真调试后,打开Power,Reset and Clock Control
可以观察到默认的时钟配置。由图观察到 PLLMUL为7:PLL Clock*9。SYSCLK=9 * OSC=9 * 8=40.
运行RCC_HSE_Config()之后,观察到 PLLMUL变成了3:PLL Clock*5。SYSCLK=5 * OSC=5 * 8=40.
为什么stm32要设计如此复杂的时钟树?
大大节省功耗,需要用到的外设开启时钟,不需要的则关闭,这将大大节省功耗。
系统时钟要了然于胸,脑子中得存储着时钟树框图,能复述具体时钟的配置过程。
一、总体时钟树框图
时钟源(如上图的左边4个蓝色框所示):
HSI RC
HSE Osc
LSE Osc
LSI RC
倍频器与分频器:
PLL 锁相环、TIMx Multiplier,起倍频作用。
AHB Prescaler、APB1Prescaler、APB2Prescaler、USB Prescaler起分频作用。
时钟输出:
HCLK:内核CPU时钟
PCLK1:外设1时钟
TIMxCLK:通用定时器时钟
PCLK2:TIM1时钟
ADCCLK:ADC时钟
USBCLK:USB 48MHz时钟
RTCCLK:RTC时钟
IWDGCLK:独立看门狗时钟
MOC:可以选择输出SYSCLK、HSI、HSE、PLLCLK的其中一个,用示波器连接此接口判断时钟是否故障。此接口也可提供晶振。
css时钟监视系统:
自动切换时钟来源
通常以HSE作为时钟源产生HCLK供CPU使用,万一HSE失效了,CPU就无法正常工作了。为了增加健壮性,stm32时钟系统中使用css时钟监视系统,在HSE失效的时候,产生中断,自动切换选择HSI作为时钟源。
二、主系统时钟
2.1 总体介绍
追溯根源,起时钟来源于 HSE 或者 HSI 。
HSE、HSI 可经过 锁相环 倍频后作为 SYSCLK系统时钟 ,或者直接作为 SYSCLK系统时钟 。通过SW进行选择。
SYSCLK系统时钟 经过 AHB 预分频器 分频后,作为 FCLK时钟 (作为CPU时钟)、HCLK高速时钟(用于高速外设,比如内存控制器,中断控制器,LCD控制器, DMA 等)。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB1 预分频器 分频后,作为 PCLK1时钟 (主要用于低速外设)。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB1预分频器 分频后,再经过 TIM2,3,4 Multiplier倍频器 倍频,作为 通用定时器的时钟。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB2 预分频器 分频后,作为 PCLK2时钟 。
SYSCLK系统时钟 经过 AHB 预分频器 及 APB2 预分频器 分频后,再经过 TIM1 Multiplier倍频器 倍频,作为高级定时器的时钟。
SYSCLK系统时钟 经过 AHB预分频器 及 ADC预分频器 分频后,作为 ADC时钟。
主系统时钟大体如下图黄色所示。
2.2 细分介绍
HSE时钟
HSE :
High Speed External Clock signal ,即高速的外部时钟。
来源:
无源晶振( 4-16M ),通常使用8M。
控制:
RCC_CR时钟控制寄存器的位16: HSEON控制。
开启HSE的时候,需要一定时间来起振。
根据RCC_CR时钟控制寄存器的位17: HSERDY 来判断起振是否完毕。
HSI时钟
HSI :
Low Speed Internal Clock signal ,高速的内部时钟。
来源:
芯片内部,大小为8M,当HSE故障时1系统时钟会自动切换到HSI ,直到HSE启动成功。
控制:
RCC_CR时钟控制寄存器的位0 : HSION控制。
控制原理同HSE。
PLLCLK锁相环时钟
锁相环时钟:
来源:
(HSI/2、HSE)经过倍频所得
控制:
CFGR : PLLXTPRE、PLLMUL
注意:
PLL时钟源头使用HSI/2的时候, PLLMUL最大只能是16,这个时候PLLCLK最大只能是64M ,小于ST官方推
荐的最大时钟72M。
如果需要在应用中使用USB接口,PLL必须被设置为输出48或72MHZ时钟,用于提供48MHz的USBCLK时钟。
HCLK时钟
HCLK :
AHB高速总线时钟,速度最高为72M。为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟(SysTick)、为内核cpu提供时钟( FCLK )。AHB : advanced high-performance bus。
来源:
系统时钟分频得到, -般设置HCLK=SYSCLK= 72M
控制:
CFGR:HPRE
PCLK1时钟
PCLK1 :
APB1低速总线时钟,最高为36M。为APB1总线的外设提供时钟。2倍频之后则为APB1总线的定时器2-7提供时钟,最大为72M。
来源:
HCLK分频得到,一般配置PCLK1=HCLK/2=36M
控制:
RCC_CFGR时钟配置寄存器的PPRE1位
PCLK2时钟
PCLK2 :
APB2高速总线时钟,最高为72M。为APB1总线 的外设提供时钟。为APB1总线的定时器1和8提供时钟,最大为72M。
来源:
HCLK分频得到,一般配置PCLK1=HCLK= 72M
控制:
RCC_CFGR时钟配置寄存器的PPRE2位
三、其他时钟
3.1 RTC时钟
RTC时钟:
为芯片内部的RTC外设提供时钟。
来源:
HSE_ RTC ( HSE分频得到)、LSE (外部32.768KHZ的晶体提供)、LSI(32KHZ)。
控制:
RCC备份域控制寄存器RCC_ BDCR : RTCSEL位控制
3.2 IWDG独立看门狗时钟
IWDG时钟:
来源:
由芯片内部的 LSI RC 提供
控制:
略
其他时钟如下图标号D所示。
四、MCO时钟输出
MCO时钟输出
MCO :
microcontroller clock output ,微控制器时钟输出引脚,由PA8复用所得。
来源:
PLLCLK/2 , HSE、HSI、 SYSCLK
控制:
CRGR:MCO
查看下图E。
五、stm32时钟系统的编程
5.1 系统启动文件的默认时钟配置
在启动文件中,SystemInit()函数就对系统时钟进行了配置。
SystemInit() 后时钟频率大小:
PLL 主时钟=72MHz
SYSCLK (系统时钟) =72MHz
AHB 总线时钟(HCLK=SYSCLK) =72MHz
APB1 总线时钟(PCLK1+SYSCL K/2) =36MHz
APB2 总线时钟(PCLK2=SYSCLK/1) =72MHz
5.2 自定义主系统时钟配置函数
时钟使能配置函数
时钟源使能:
RCC_ HSICmd
RCC_ LSICmd
RCC_ PLLCmd
外设时钟使能:
RCC RTCCLKCmd
RCC_ AHBPeri phClockCmd
RCC_ APBxPeri phCl ockCmd
设置时钟流程:
将RCC寄存器重新设置为默认值
RCC_Delnit
打开外部高速时钟晶振
HSE RCC_HSEConfig(RCC_HSE_ON);
等待外部高速时钟晶振工作
HSEStartUpStatus = RCC_WaitForHSEStartUp();
设置AHB时钟
RCC_HCLKConfig;
设置高速APB时钟
RCC_PCLK2Config;
设置低速速APB时钟
RCC_PCLK1Config
设置PLL,主要通过修改PLL的倍频系数改变系统时钟
RCC_PLLConfig
打开PLL
RCC_PLLCmd(ENABLE);
等待PLL工作
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
设置系统时钟
RCC_SYSCLKConfig
判断是否PLL是系统时钟
while(RCC_GetSYSCLKSource() != 0x08)
代码:
#include “stm32f10x.h”
/*******************************************************************
*函数:void RCC_HSE_Config
*功能:通过修改pll的分频、倍频系数改变系统时钟
*输入:
u32 div, HSE的分频系数1-2:RCC_PLLSource_HSE_Div1、RCC_PLLSource_HSE_Div2
u32 pllm, HSE的倍频系数2-16:RCC_PLLMul_2、RCC_PLLMul_3、、、RCC_PLLMul_16
*输出:
*特殊说明:
*******************************************************************/
void RCC_HSE_Config(u32 div,u32 pllm)
{
RCC_DeInit(); //将外设RCC寄存器重设为缺省值
RCC_HSEConfig(RCC_HSE_ON); //开启外部高速晶振(HSE)
if (RCC_WaitForHSEStartUp()==SUCCESS) //等待HSE起振
{
RCC_HCLKConfig (RCC_SYSCLK_Div1) ;//设置AHB时钟HCLK,1分频。HCLK==SYSCLK
RCC_PCLK1Config(RCC_HCLK_Div2) ;//设置低速AHB时钟PCLK1,2分频。PCLK1==1/2HCLK
RCC_PCLK2Config (RCC_HCLK_Div1) ;//设置高速AHB时钟PCLK2,1分频。PCLK2==HCLK
RCC_PLLConfig (div, pllm) ;//设置PLL时钟源及倍频系数
RCC_PLLCmd (ENABLE) ; //使能PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //检查指定的RCC标志位设置与否,PLL就绪
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟SYSCLK来源 设置来源为PLL
while (RCC_GetSYSCLKSource() !=0x08) ; //返回用作系统时钟的时钟源,0x08:PLL作为系统时钟
}
}
int main(void)
{
RCC_HSE_Config(RCC_PLLSource_HSE_Div1,RCC_PLLMul_5);
while(1)
{
}
}
我们使用软件仿真观察实验现象。
进入仿真调试后,打开Power,Reset and Clock Control
可以观察到默认的时钟配置。由图观察到 PLLMUL为7:PLL Clock*9。SYSCLK=9 * OSC=9 * 8=40.
运行RCC_HSE_Config()之后,观察到 PLLMUL变成了3:PLL Clock*5。SYSCLK=5 * OSC=5 * 8=40.
举报