static void SetSysClock(void)
{
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
/*------------------------------------------------------------------------------------------------启动HSE-------------------------------------------------------*/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Enable HSE
#define RCC_CR_HSEON ((uint32_t)0x00010000)
位 16 HSEON:HSE 时钟使能 (HSE clock enable)
由软件置 1 和清零。
由硬件清零,用于在进入停机或待机模式时停止 HSE 振荡器。如果 HSE 振荡器直接或间接
用于作为系统时钟,则此位不可复位。
0:HSE 振荡器关闭
1:HSE 振荡器打
*/
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
/* #define RCC_CR_HSERDY ((uint32_t)0x00020000)
位 17 HSERDY:HSE 时钟就绪标志 (HSE clock ready flag)
由硬件置 1,用以指示 HSE 振荡器已稳定。在将 HSEON 位清零后,HSERDY 将在 6 个
HSE 振荡器时钟周期后转为低电平。
0:HSE 振荡器未就绪
1:HSE 振荡器已就绪
*/
HSEStatus = RCC->CR & RCC_CR_HSERDY;
/*超时控制*/
StartUpCounter++;
/*#define HSE_STARTUP_TIMEOUT ((uint16_t)0x05000)*/
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
/*HSE启动是否成功,写HSE状态标志HSEStatus*/
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
/*-------------------------------------------------------------------------系统时钟分频----------------------------------------------------------------*/
/*HSE启动成功执行*/
if (HSEStatus == (uint32_t)0x01)
{
/* Select regulator voltage output Scale 1 mode
#define RCC_APB1ENR_PWREN ((uint32_t)0x10000000)
位 28 PWREN:电源接口时钟使能 (Power interface clock enable)
由软件置 1 和清零。
0:禁止电源接口时钟
1:使能电源接口时钟
*/
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/*调压器输出电压级别选择
#define PWR_CR_VOS ((uint32_t)0x0000C000)
Bits 15:14 VOS[1:0]: Regulator voltage scaling output selection
These bits control the main internal voltage regulator output voltage to achieve a trade-off
between performance and power consumption when the device does not operate at the
maximum frequency (refer to the corresponding datasheet for more details).
These bits can be modified only when the PLL is OFF. The new value programmed is active
only when the PLL is ON. When the PLL is OFF, the voltage regulator is set to scale 3
independently of the VOS register content.
00: Reserved (Scale 3 mode selected)
01: Scale 3 mode <= 64 MHz
10: Scale 2 mode (reset value) <= 84 MHz
11: Scale 1 mode <= 100 MHz
*/
PWR->CR |= PWR_CR_VOS;
/* HCLK = SYSCLK / 1
#define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000)
位 7:4 HPRE:AHB 预分频器 (AHB prescaler)
由软件置位和清零,用于控制 AHB 时钟分频系数。
小心: 在 HPRE 写入后,时钟将通过 1 AHB 到 16 AHB 周期新预分频系数进行分频。
小心: 当使用以太网时,AHB 时钟频率必须至少为 25 MHz。
0xxx:系统时钟不分频
1000:系统时钟 2 分频
1001:系统时钟 4 分频
1010:系统时钟 8 分频
1011:系统时钟 16 分频
1100:系统时钟 64 分频
1101:系统时钟 128 分频
1110:系统时钟 256 分频
1111:系统时钟 512 分频
*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 2
位 15:13 PPRE2:APB 高速预分频器 (APB2) (APB high-speed prescaler (APB2))
由软件置位和清零,用于控制 APB 高速时钟分频系数。
小心: 软件必须正确设置这些位,使其在此域中不超过 84 MHz。在 PPRE2 写入后,时钟
将通过 1 AHB 到 16 AHB 周期新预分频系数进行分频。
0xx:AHB 时钟不分频
100:AHB 时钟 2 分频
101:AHB 时钟 4 分频
110:AHB 时钟 8 分频
111:AHB 时钟 16 分频
*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4
位 12:10 PPRE1:APB 低速预分频器 (APB1) (APB Low speed prescaler (APB1))
由软件置位和清零,用于控制 APB 低速时钟分频系数。
小心: 软件必须正确设置这些位,使其在此域中不超过 42 MHz。在 PPRE1 写入后,时钟
将通过 1 AHB 到 16 AHB 周期新预分频系数进行分频。
0xx:AHB 时钟不分频
100:AHB 时钟 2 分频
101:AHB 时钟 4 分频
110:AHB 时钟 8 分频
111:AHB 时钟 16 分频
*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/*-------------------------------------------------------------------------------------主PLL分频----------------------------------------*/
/* Configure the main PLL
RCC PLL 配置寄存器 (RCC_PLLCFGR)
#define RCC_PLLCFGR_PLLSRC_HSE ((uint32_t)0x00400000)
*/
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL
#define RCC_CR_PLLON ((uint32_t)0x01000000)
位 24 PLLON:主 PLL (PLL) 使能 (Main PLL (PLL) enable)
由软件置 1 和清零,用于使能 PLL。
当进入停机或待机模式时由硬件清零。如果 PLL 时钟用作系统时钟,则此位不可清零。
0:PLL 关闭
*/
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready
位 25 PLLRDY:主 PLL (PLL) 时钟就绪标志 (Main PLL (PLL) clock ready flag)
由硬件置 1,用以指示 PLL 已锁定。
0:PLL 未锁定
1:PLL 已锁定
*/
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/*----------------------------------------------------------------------------------Flash访问设置--------------------------------------------------------------*/
/* Configure Flash prefetch, Instruction cache, Data cache and wait state
位 2:0 LATENCY:延迟 (Latency)
这些位表示 CPU 时钟周期与 Flash 访问时间之比。
000:零等待周期
001:一个等待周期
010:两个等待周期
011:三个等待周期
100:四个等待周期
101:五个等待周期
110:六个等待周期
111:七个等待周期
位 8 PRFTEN:预取使能 (Prefetch enable)
位 9 ICEN:指令缓存使能 (Instruction cache enable)
位 10 DCEN:数据缓存使能 (Data cache enable)
*/
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
/*-----------------------------------------------------------------------------------系统时钟源选择----------------------------------------------------------------------*/
/* Select the main PLL as system clock source
位 1:0 SW:系统时钟切换 (System clock switch)
由软件置 1 和清零,用于选择系统时钟源。
由硬件置 1,用于在退出停机或待机模式时或者在直接或间接用作系统时钟的 HSE 振荡器发
生故障时强制 HSI 的选择。
00:选择 HSI 振荡器作为系统时钟
01:选择 HSE 振荡器作为系统时钟
10:选择 PLL 作为系统时钟
11:不允许
*/
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
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 */
}
}
标签:AHB,分频,PLL,HSE,system,时钟,stm32f4xx,RCC From: https://www.cnblogs.com/Yannnnnn/p/17701142.html