时钟配置
1、概述
F407的内部时钟有LSI(32Hz)、HSI(16MHz)
外部时钟有 HSE 25MHz,用外部时钟比较稳定。
用HSE时钟配置系统时钟如下
25Mhz,通过PLL倍频,作为PllClk和PLL48CLK时钟,(m分频因子一般为HSE大小:配置为输入VCO为1MHz,XN倍频为输出VCO =336Mhz,通过分频因子p(=2)和R(=7)给外部总线提供时钟,ABB(HCLK)=168,APB1总线为42Hz、APB2总线为84Hz,定时器时钟是APB总线时钟2倍,)
2、时钟配置总结
/*
- 使用 HSE 时,设置系统时钟的步骤
- 1、开启 HSE ,并等待 HSE 稳定
- 2、设置 AHB、 APB2、 APB1 的预分频因子
- 3、设置 PLL 的时钟来源
- 设置 VCO 输入时钟 分频因子 m
- 设置 VCO 输出时钟 倍频因子 n
- 设置 PLLCLK 时钟分频因子 p
- 设置 OTG FS,SDIO,RNG 时钟分频因子 q
- 4、开启 PLL,并等待 PLL 稳定
- 5、把 PLLCK 切换为系统时钟 SYSCLK
- 6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
- m: VCO 输入时钟 分频因子,取值 2~63
- n: VCO 输出时钟 倍频因子,取值 192~432
- p: PLLCLK 时钟分频因子 ,取值 2, 4, 6, 8
- q: OTG FS,SDIO,RNG 时钟分频因子,取值 4~15
- 函数调用举例,使用 HSE 设置时钟
- SYSCLK=HCLK=168M,PCLK2=HCLK/2=84M,PCLK1=HCLK/4=42M
*/
3、用寄存器编程
void hseCfg(void)
{
/*****************************************************************************/
/ PLL (clocked by HSE) used as System clock source /
/****************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/ 复位RCC的所有寄存器 */
RCC_DeInit();
RCC->CR |=(uint32_t)RCC_CR_HSEON;//使能HSE时钟
// 下面是等着硬件自动设置CR寄存器为HSERDY为1表示HSE时钟就绪
do
{
HSEStatus=RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
}while((HSEStatus==0)&&(StartUpCounter!=HSE_STARTUP_TIMEOUT));
if((RCC->CR & RCC_CR_HSERDY)!=RESET)
{
HSEStatus=0x1;
}
else
{
HSEStatus=0x0;
}
if(HSEStatus==0x1)
{
/* Select regulator voltage output Scale 1 mode */
/* 选择电压调节器的模式为1,用来平衡电压,减低功耗 */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;
/* 给系统各总线分频
AHB 分频为1
APB1 分频为4
APB1 分频为2
*/
RCC->CFGR |=RCC_CFGR_HPRE_DIV1;
RCC->CFGR |=RCC_CFGR_PPRE1_DIV4;
RCC->CFGR |=RCC_CFGR_PPRE2_DIV2;
/* PLL倍频* RCC_PLLCFGR_PLLSRC_HSE 作为系统时钟/
RCC->PLLCFGR = 25 | (336 << 6) | (((2 >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (7 << 24);
/* Enable the main PLL /
/ 使能主PLL /
RCC->CR |= RCC_CR_PLLON;
/ Wait till the main PLL is ready /
/ 等待主PLL稳定 */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
/* 配置FLASH预取指,指令缓存,数据缓存,等待周期 */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
RCC->CFGR &=~(RCC_CFGR_SW);
RCC->CFGR |=RCC_CFGR_SW_PLL;//选择PLL作为系统时钟
while((RCC->CFGR &(uint32_t)RCC_CFGR_SWS_PLL) !=RCC_CFGR_SWS_PLL)
{
}//等待PLL就绪,有硬件设置
}
else
{
异常做其他处理
}
}
4、用固件库编程
void HseCFg(uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
{
ErrorStatus errorStatus=ERROR;
RCC_DeInit(); /* 复位RCC的所有寄存器 */
RCC_HSEConfig(RCC_HSE_ON);//使能HSE时钟
// 下面是等着硬件自动设置CR寄存器为HSERDY为1表示HSE时钟就绪
errorStatus=RCC_WaitForHSEStartUp();
if(errorStatus==SUCCESS)
{
/* 给系统各总线分频
AHB 分频为1
APB1 分频为4
APB1 分频为2
*/
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div4);
RCC_PCLK2Config(RCC_HCLK_Div2);
/* PLL倍频* RCC_PLLCFGR_PLLSRC_HSE 作为系统时钟/
RCC_PLLConfig(RCC_PLLSource_HSE, PLLM, PLLN, PLLP, PLLQ);
RCC_PLLCmd(ENABLE);//用的位带操作,给寄存器X位置1
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
/* 配置FLASH预取指,指令缓存,数据缓存,等待周期 */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while((RCC->CFGR &(uint32_t)RCC_CFGR_SWS_PLL) !=RCC_CFGR_SWS_PLL)
{
}
}
else
{
}
}
5、HSI配置为系统时钟
void HSIFun(uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
// ErrorStatus errorStatus=ERROR;
/* 复位RCC的所有寄存器 */
RCC_DeInit();
RCC->CR |=(uint32_t)RCC_CR_HSION;
do
{
HSEStatus=RCC->CR & RCC_CR_HSIRDY;
StartUpCounter++;
}while((HSEStatus==0)&&(StartUpCounter!=HSE_STARTUP_TIMEOUT));
if((RCC->CR & RCC_CR_HSIRDY)==RCC_CR_HSIRDY)
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div4);
RCC_PCLK2Config(RCC_HCLK_Div2);
RCC_PLLConfig(RCC_PLLSource_HSI, PLLM, PLLN, PLLP, PLLQ);
RCC_PLLCmd(ENABLE);
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
/* 配置FLASH预取指,指令缓存,数据缓存,等待周期 */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while((RCC->CFGR &(uint32_t)RCC_CFGR_SWS_PLL) !=RCC_CFGR_SWS_PLL)
{
}
}
else
{
}
}