复位和时钟控制器

RCC :reset clock control 复位和时钟控制器。

 

1 HSE 高速外部时钟信号(由晶振模块产生)
HSE 是高速的外部时钟信号, 可以由有源晶振或者无源晶振提供,频率从 4-16MHZ
等。当使用有源晶振时,时钟从 OSC_IN 引脚进入, OSC_OUT 引脚悬空,当选用无源晶振
时,时钟从 OSC_IN OSC_OUT 进入,并且要配谐振电容。
2 PLL 时钟源
PLL 时钟来源可以有两个,一个来自 HSE ,另外一个是 HSI/2 ,具体用哪个由时钟配置寄存器 CFGR 的位 16 PLLSRC 设置。 HSI 是内部高速的时钟信号,频率为 8M ,根据温度和环境的情况频率会有漂移,一般不作为 PLL 的时钟来源。这里我们选 HSE作为 PLL的时钟来源 .
3 PLL 时钟 PLLCLK
通过设置 PLL 的倍频因子,可以对 PLL 的时钟来源进行 倍频 ,倍频因子可以是:[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] ,具体设置成多少,由时钟配置寄存器 CFGR 的位
21-18 PLLMUL[3:0] 设置。我们这里设置为 9 倍频,因为上一步我们设置 PLL 的时钟来源
HSE=8M ,所以经过 PLL 倍频之后的 PLL 时钟: PLLCLK = 8M *9 = 72M
当确定 PLL 时钟来源的时候, HSE 可以 不分频 或者 2 分频,这个由时钟配置寄存器 CFGR 的位 17 PLLXTPRE 设置,我们设置为 HSE 不分频.
4 系统时钟 SYSCLK
系统时钟来源可以是:HSIPLLCLKHSE ,具体的时钟配置寄存器 CFGR 的位 1-0:SW[1:0]设置。一般设置系统时钟: SYSCLK = PLLCLK = 72M
5 AHB 总线时钟 HCLK
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 APB 总线时钟,即 HCLK
分频因子可以是 :[1,2,4 8 16 64 128 256 512] ,具体的由时钟配置寄存器 CFGR
的位 7-4 :HPRE[3:0]设置。一般 设置为 1 分频,即 HCLK=SYSCLK=72M
6  APB2 总线时钟 HCLK2
APB2 总线时钟 PCLK2 HCLK经过高速 APB2预分频器 得到,分频因子可以是 :[1,2,4
8 16] ,具体由时钟配置寄存器 CFGR 的位 13-11 PPRE2[2:0] 决定。 HCLK2 属于高速的总
线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO USART1 SPI1 等。
一般设置为 1 分频,即 PCLK2 = HCLK = 72M。
7 APB1 总线时钟 HCLK1
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到 ,分频因子可以是 :[1,2,4
8 16] ,具体的由时钟配置寄存器 CFGR 的位 10-8 PRRE1[2:0] 决定。
HCLK1 属于低速的总线时钟,最高为 36M 片上低速的外设 就挂载到这条总线上,比如
USART2/3/4/5 SPI2/3 I2C1/2等。 设置为 2 分频,即 PCLK1 = HCLK/2 = 36M。
8 USB 时钟
USB 时钟是由 PLLCLK 经过 USB 预分频器得到 ,分频因子可以是: [1,1.5] ,具体的由
时钟配置寄存器 CFGR 的位 22 USBPRE 配置。 USB 的时钟最高是 48M。
9 Cortex 系统时钟
Cortex 系统时钟由 HCLK(AHB总线时钟) 8 分频得到,等于 9M Cortex 系统时钟用来 驱动内核的系统定时器 SysTick SysTick 一般用于操作系统的时钟节拍,也可以用做普通的定时。
10 ADC 时钟
ADC 时钟由 PCLK2经过 ADC预分频器 得到,分频因子可以是 [2,4,6,8] ,具体的由时钟
配置寄存器 CFGR 的位 15-14 :ADCPRE[1:0]决定。ADC时钟最高只能是 14M。
鉴于 PCLK2 最高是 72M ,所以只能取28M 和 56M。
11 RTC 时钟、独立看门狗时钟
RTC 时钟可由 HSE/128 分频得到 ,也可由低速外部时钟信号 LSE 提供,频率为
32.768KHZ ,也可由低速内部时钟信号 HSI 提供,具体选用哪个时钟由备份域控制寄存器
BDCR 的位 9-8 RTCSEL[1:0] 配置。
独立看门狗的时钟由LSI提供 ,且只能是由 LSI 提供, LSI 是低速的内部时钟信号,频率为 30~60KHZ 直接不等,一般取 40KHZ
12 MCO 时钟输出
MCO microcontroller clock output 的缩写,是微控制器时钟输出引脚,在 STM32 F1
系列中 由 PA8 复用所得,主要作用是可以 对外提供时钟,相当于一个有源晶振 MCO
时钟来源可以是: PLLCLK/2 HSI HSE SYSCLK ,具体选哪个由时钟配置寄存器
CFGR 的位 26-24 MCO[2:0] 决定。
13 硬件设计
RCC 是单片机内部资源,不需要外部电路。通过 LED 闪烁的频率来直观的判断不同系
统时钟频率对软件延时的效果。
14 软件设计
我们编写两个 RCC 驱动文件, bsp_clkconfig.h bsp_clkconfig.c ,用来存放 RCC 系统
时钟配置函数。
   编程步骤
1 、开启 HSE/HSI ,并等待 HSE/HSI 稳定
2 、设置 AHB APB2 APB1 的预分频因子
3 、设置 PLL 的时钟来源,和 PLL 的倍频因子,设置各种频率主要就是在这里设置
4 、开启 PLL ,并等待 PLL 稳定
5 、把 PLLCK 切换为系统时钟 SYSCLK
6 、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
使用 HSE 配置系统时钟
1 void HSE_SetSysClock( uint32_t pllmul)
2 {
3 __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
4
5 // RCC 外设初始化成复位状态
6 RCC_DeInit();
7
8 // 使能 HSE ,开启外部晶振,秉火 STM32F103 系列开发板用的是 8M
9 RCC_HSEConfig(RCC_HSE_ON);
10
11 // 等待 HSE 启动稳定
12 HSEStartUpStatus = RCC_WaitForHSEStartUp();
13
14 // 只有 HSE 稳定之后则继续往下执行
15 if (HSEStartUpStatus == SUCCESS) {
16 //-----------------------------------------------------------------//
17 // 这两句是操作 FLASH 闪存用到的,如果不操作 FLASH ,这两个注释掉也没影响
18 // 使能 FLASH 预存取缓冲区
19 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
20
21 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
22 // 设置成 2 的时候, SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
23 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
24 // 0 0 < SYSCLK <= 24M
25 // 1 24< SYSCLK <= 48M
26 // 2 48< SYSCLK <= 72M
27 FLASH_SetLatency(FLASH_Latency_2);
28 //-----------------------------------------------------------------//
29
30 // AHB 预分频因子设置为 1 分频, HCLK = SYSCLK
31 RCC_HCLKConfig(RCC_SYSCLK_Div1);
32
33 // APB2 预分频因子设置为 1 分频, PCLK2 = HCLK
34 RCC_PCLK2Config(RCC_HCLK_Div1);
35
36 // APB1 预分频因子设置为 1 分频, PCLK1 = HCLK/2
37 RCC_PCLK1Config(RCC_HCLK_Div2);
38
39 //----------------- 设置各种频率主要就是在这里设置 -------------------//
40 // 设置 PLL 时钟来源为 HSE ,设置 PLL 倍频因子
41 // PLLCLK = 8MHz * pllmul
42 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
43 //-------------------------------------------------------------//
44
45 // 开启 PLL
46 RCC_PLLCmd(ENABLE);
47
48 // 等待 PLL 稳定
49 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
50 }
51
52 // PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK
53 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
54
55 // 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
56 while (RCC_GetSYSCLKSource() != 0x08) {
57 }
58 } else {
59 // 如果 HSE 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
60 // HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,
61 // HSI 是内部的高速时钟, 8MHZ
62 while (1) {
63 }
64 }
65 }
使用 HSI 配置系统时钟
1 void HSI_SetSysClock( uint32_t pllmul)
2 {
3 __IO uint32_t HSIStartUpStatus = 0;
4
5 // RCC 外设初始化成复位状态
6 RCC_DeInit();
7
8 // 使能 HSI
9 RCC_HSICmd(ENABLE);
10
11 // 等待 HSI 就绪
12 HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
13
14 // 只有 HSI 就绪之后则继续往下执行
15 if (HSIStartUpStatus == RCC_CR_HSIRDY) {
16 //-------------------------------------------------------------//
17 // 这两句是操作 FLASH 闪存用到的,如果不操作 FLASH ,这两个注释掉也没影响
18 // 使能 FLASH 预存取缓冲区
19 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
20
21 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
22 // 设置成 2 的时候, SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
23 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
24 // 0 0 < SYSCLK <= 24M
25 // 1 24< SYSCLK <= 48M
26 // 2 48< SYSCLK <= 72M
27 FLASH_SetLatency(FLASH_Latency_2);
28 //------------------------------------------------------------//
29
30 // AHB 预分频因子设置为 1 分频, HCLK = SYSCLK
31 RCC_HCLKConfig(RCC_SYSCLK_Div1);
32
33 // APB2 预分频因子设置为 1 分频, PCLK2 = HCLK
34 RCC_PCLK2Config(RCC_HCLK_Div1);
35
36 // APB1 预分频因子设置为 1 分频, PCLK1 = HCLK/2
37 RCC_PCLK1Config(RCC_HCLK_Div2);
38
39 //----------- 设置各种频率主要就是在这里设置 -------------------//
40 // 设置 PLL 时钟来源为 HSE ,设置 PLL 倍频因子
41 // PLLCLK = 4MHz * pllmul
42 RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);
43 //-- -----------------------------------------------------//
44
45 // 开启 PLL
46 RCC_PLLCmd(ENABLE);
47
48 // 等待 PLL 稳定
49 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
50 }
51
52 // PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK
53 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
54
55 // 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
56 while (RCC_GetSYSCLKSource() != 0x08) {
57 }
58 } else {
59 // 如果 HSI 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
60 // HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,
61 // HSI 是内部的高速时钟, 8MHZ
62 while (1) {
63 }
64 }
65 }
HSI 必须 2 分频之后才能作为 PLL 的时钟来源,所以使用 HSI 时,最大的系统时
SYSCLK 只能是 HSI/2*16=4*16=64MHZ
函数调用举例: HSI_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为: 4MHZ * 9 =
36MHZ
软件延时
1 void Delay(__IO uint32_t nCount)
2 {
3 for (; nCount != 0; nCount--);
4 }
软件延时函数,使用不同的系统时钟,延时时间不一样,可以通过 LED 闪烁的频率来
判断。
MCO 输出
STM32F103 系列中, PA8 可以复用为 MCO 引脚,对外提供时钟输出,我们也可以
用示波器监控该引脚的输出来判断我们的系统时钟是否设置正确
MCO GPIO 初始化
1 /*
2 * 初始化 MCO 引脚 PA8
3 * F103 系列中 MCO 引脚只有一个,即 PA8 ,在 F4 系列中, MCO 引脚有两个
4 */
5 void MCO_GPIO_Config( void )
6 {
7 GPIO_InitTypeDef GPIO_InitStructure;
8 // 开启 GPIOA 的时钟
9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
10
11 // 选择 GPIO8 引脚
12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
13
14 // 设置为复用功能推挽输出
15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
16
17 // 设置 IO 的翻转速率为 50M
18 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
19
20 // 初始化 GPIOA8
21 GPIO_Init(GPIOA, &GPIO_InitStructure);
22 }
输出时钟选择
1 // 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,
2 // 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确
3 // MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK
4 //RCC_MCOConfig(RCC_MCO_HSE);
5 //RCC_MCOConfig(RCC_MCO_HSI);
6 //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
7 RCC_MCOConfig(RCC_MCO_SYSCLK);
主函数
1 int main( void )
2 {
3 // 程序来到 main 函数之前,启动文件: statup_stm32f10x_hd.s 已经调用
4 // SystemInit() 函数把系统时钟初始化成 72MHZ
5 // SystemInit() system_stm32f10x.c 中定义
6 // 如果用户想修改系统时钟,可自行编写程序修改
7
8 // 重新设置系统时钟,这时候可以选择使用 HSE 还是 HSI
9
10 // 使用 HSE 时, SYSCLK = 8M * RCC_PLLMul_x, x:[2,3,...16], 最高是 128M
11 HSE_SetSysClock(RCC_PLLMul_9);
12
13 // 使用 HSI 时, SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16], 最高是 64MH
14 //HSI_SetSysClock(RCC_PLLMul_16);
15
16 // MCO 引脚初始化
17 MCO_GPIO_Config();
18
19 // 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,
20 // 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确
21 // MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK
22 //RCC_MCOConfig(RCC_MCO_HSE);
23 //RCC_MCOConfig(RCC_MCO_HSI);
24 //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
25 RCC_MCOConfig(RCC_MCO_SYSCLK);
26
27 // LED 端口初始化
28 LED_GPIO_Config();
29 while (1) {
30 LED1( ON ); //
31 Delay(0x0FFFFF);
32 LED1( OFF ); //
33 Delay(0x0FFFFF);
34 }
35 }

你可能感兴趣的:(单片机,嵌入式硬件,stm32)