您的位置:首页 > 其它

STM32时钟设置

2016-08-18 12:19 316 查看
MCU需要在时钟的驱动下才能正常工作,STM32F407 的工作主频最高能达到168MHz,而其外接晶振只有4-26MHz,需要通过内部的数字PLL电路进行配置,才能将内核时钟频率提升至168MHz,那具体需要怎样进行配置呢?其实,stm32的时钟配置相关的函数都在system_stm32f4xx.c这个文件中,这个c文件可以通过ST官方提供的一个xls文件自动生成,这里是对这个c文件做个详细介绍,知道了原理,便可以根据需要手动进行修改了。
首先看下如下图clock tree的PLL部分,系统时钟最大可以168MHz(PLL升频得来),这个需要对PLL进行配置,从下图可知,具体就是要设定P,Q,M,N这四个参数



由于PLLCLK = SourceCLK / M * N / P,这里SourceCLK代表的是PLL电路的输入时钟源,可以是高速外部时钟HSE,也可以是高速内部时钟HSI(STM32出厂自带的),假设是通过外接的8M晶振HSE作为PLL的输入时钟,显然可以通过168M
= 8M / 8 *336 / 2来得到168M的系统时钟,那么M=2,N=336,P=2,Q=7(USB之类的外设需要48M的时钟),于是便有了下面这样的宏定义:
/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8
#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7
有了这样的宏定义,便可以对相应的寄存器进行设置了,下面这个函数就是完成这个配置任务
/**
* @brief  Configures the System clock source, PLL Multiplier and Divider factors,
*         AHB/APBx prescalers and Flash settings
* @Note   This function should be called only once the RCC clock configuration
*         is reset to the default reset state (done in SystemInit() function).
* @param  None
* @retval None
*/
static void SetSysClock(void)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//必须先使能HSE,也就是外接的晶振 RCC_CR_HSEON = 0x0001 0000

/* Wait till HSE is ready and if Time out is reached exit */
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;
}

if (HSEStatus == (uint32_t)0x01)
{
/* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;

/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;//AHB时钟

/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2时钟,84MHz max for STM32F407

/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;//APB1时钟,42MHz max for STM32F407

/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);//PLL系数设置用的寄存器

/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;//开启PLL

/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}

/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

a0bf
RCC->CFGR |= RCC_CFGR_SW_PLL;

/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}

}
上面这个函数被System_Init()函数引用,stm32上电进入到main函数之前,通过汇编写的启动文件调用System_Init()进行时钟初始化之后,也就是说在所有的c文件中,都不用再去调用System_Init(),系统便可以正常运行起来了。
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;//首先需要用内部高速时钟作为系统主时钟

/* Reset CFGR register */
RCC->CFGR = 0x00000000;

/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;

/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Disable all interrupts */
RCC->CIR = 0x00000000;

#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */

/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();//进行PLL配置

/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: