【STM32学习笔记】时钟的配置
程序员文章站
2022-03-03 19:01:20
时钟树简单总结一下:PLLCLK的来源有三个,HSE、HSE/2、HSI/2,一般选 HSE = 8MSYSCLK(系统时钟)的来源有三个,PLLCLK(锁相环)、HSE、HEI,一般选 PLLCLK * 9 = 72MAHB总线上的时钟 HCLK = SYSCLK = 72MAPB1总线上的时钟 PCLK1 = HCLK/2 = 36MAPB2总线上的时钟 PCLK2 = HCLK = 72M官方固件库的时钟配置(通过寄存器)static void SetS...
时钟树
简单总结一下:
PLLCLK的来源有三个,HSE、HSE/2、HSI/2,一般选 HSE = 8M
SYSCLK(系统时钟)的来源有三个,PLLCLK(锁相环)、HSE、HEI,一般选 PLLCLK * 9 = 72M
AHB总线上的时钟 HCLK = SYSCLK = 72M
APB1总线上的时钟 PCLK1 = HCLK/2 = 36M
APB2总线上的时钟 PCLK2 = HCLK = 72M
官方固件库的时钟配置(通过寄存器)
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* 使能 HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* 等待HSE就绪并做超时处理 */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
// 如果HSE启动成功,程序则继续往下执行
if (HSEStatus == (uint32_t)0x01)
{
// 使能预取指
FLASH->ACR |= FLASH_ACR_PRFTBE;
// Flash 2 wait state
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
// HCLK = SYSCLK = 72M
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
// PCLK2 = HCLK = 72M
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
// PCLK1 = HCLK/2 = 36M
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
// 锁相环配置: PLLCLK = HSE * 9 = 72 MHz
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
// 使能 PLL
RCC->CR |= RCC_CR_PLLON;
// 等待PLL稳定
while((RCC->CR & RCC_CR_PLLRDY) == 0);
// 选择PLLCLK作为系统时钟
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
// 等待PLLCLK切换为系统时钟
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08);
}
else
{ /* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */
}
}
自己写的时钟配置(通过固件库中已封装的函数)
可改变倍频,实现不同频率锁相环,从而改变系统时钟的频率
#include "bsp_rccclkconfig.h"
void HSE_SetSysClk(uint32_t RCC_PLLMul_x){
ErrorStatus HSEStatus; /* ErrorStatus RCC_WaitForHSEStartUp(void); */
//寄存器复位
RCC_DeInit();
//使能 HSE
RCC_HSEConfig(RCC_HSE_ON);
//等待HSE稳定
HSEStatus=RCC_WaitForHSEStartUp();
if(HSEStatus==SUCCESS){
// 使能预取指
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
// Flash 2 wait state
FLASH_SetLatency(FLASH_Latency_2);
// HCLK = SYSCLK = 72M
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// PCLK1 = HCLK = 36M
RCC_PCLK1Config(RCC_HCLK_Div2);
// PCLK2 = HCLK = 72M
RCC_PCLK2Config(RCC_HCLK_Div1);
// 锁相环(PLL)配置: PLLCLK = HSE * x = ?? MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
// 使能PLL
RCC_PLLCmd(ENABLE);
// 等待PLL稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 选择系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 等待PLLCLK切换为系统时钟
while(RCC_GetSYSCLKSource() != 0x08);
}
else{
/* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */
}
}
void HSI_SetSysClk(uint32_t RCC_PLLMul_x){
__IO uint32_t HSIStatus; /* ErrorStatus RCC_WaitForHSEStartUp(void); */
//寄存器复位
RCC_DeInit();
//使能 HSI
RCC_HSICmd(ENABLE);
//等待HSI稳定
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
if(HSIStatus==SUCCESS){
// 使能预取指
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
// Flash 2 wait state
FLASH_SetLatency(FLASH_Latency_2);
// HCLK = SYSCLK = 72M
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// PCLK1 = HCLK = 36M
RCC_PCLK1Config(RCC_HCLK_Div2);
// PCLK2 = HCLK = 72M
RCC_PCLK2Config(RCC_HCLK_Div1);
// 锁相环(PLL)配置: PLLCLK = HSI * x = ?? MHz
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);
// 使能PLL
RCC_PLLCmd(ENABLE);
// 等待PLL稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 选择系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 等待PLLCLK切换为系统时钟
while(RCC_GetSYSCLKSource() != 0x08);
}
else{
/* 如果HSI 启动失败,用户可以在这里添加处理错误的代码 */
}
}
//MCO 输出初始化
void MCO_GPIO_Config(void){
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/** 通过 MCO 输出不同源的时钟频率,可连接示波器观察频率
*下列函数为官方固件库中已封装函数,在main中直接调用即可
*如:输出系统时钟的频率:RCC_MCOConfig(RCC_MCO_SYSCLK);
*/
/**
* @brief Selects the clock source to output on MCO pin.
* @param RCC_MCO: specifies the clock source to output.
* @arg RCC_MCO_NoClock: No clock selected
* @arg RCC_MCO_SYSCLK: System clock selected
* @arg RCC_MCO_HSI: HSI oscillator clock selected
* @arg RCC_MCO_HSE: HSE oscillator clock selected
* @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected
*/
void RCC_MCOConfig(uint8_t RCC_MCO)
{
/* Check the parameters */
assert_param(IS_RCC_MCO(RCC_MCO));
/* Perform Byte access to MCO bits to select the MCO source */
*(__IO uint8_t *) CFGR_BYTE4_ADDRESS = RCC_MCO;
}
本文地址:https://blog.csdn.net/Brave_Runer/article/details/107920262
下一篇: 2020-08-10