三种不同的时钟源可被用来驱动系统时钟(SYSCLK):
HSI振荡器时钟
HSE振荡器时钟
PLL时钟
还有LSE LSI 时钟,AHB总线时钟,APB1总线时钟(低速)APB2总线时钟(高速)
HSE时钟
在时钟控制寄存器RCC_CR中的HSERDY位用来指示高速外部振荡器是否稳定。在启动时,直到这一位被硬件置’1’,时钟才被释放出来。如果在时钟中断寄存器RCC_CIR中允许产生中断,
将会产生相应中断。
HSE晶体可以通过设置时钟控制寄存器里RCC_CR中的HSEON位被启动和关闭。
HSI时钟
HSI RC可由时钟控制寄存器中的HSION位来启动和关闭。
如果HSE晶体振荡器失效,HSI时钟会被作为备用时钟源。
PLL时钟
内部PLL可以用来倍频HSI RC的输出时钟或HSE晶体输出时钟
RCC 寄存器
时钟控制寄存器(RCC_CR)
位0:HSION:内部高速时钟使能 (Internal high-speed clock enable)
0:内部8MHz振荡器关闭;1:内部8MHz振荡器开启
位1:HSIRDY:内部高速时钟就绪标志 (Internal high-speed clock ready flag)
0: 部8MHz振荡器没有就绪;
1:内部8MHz振荡器就绪。
位17:HSEON:外部高速时钟使能 位18:HSERDY:外部高速时钟就绪标志
位24:PLLON:PLL使能 (PLL enable) 位25:PLLRDY:PLL时钟就绪标志
时钟配置寄存器 时钟配置寄存器(RCC_CFGR)
PLLMUL:PLL倍频系数 (PLL multiplication factor) 位21:18
由软件设置来确定PLL倍频系数。只有在PLL关闭的情况下才可被写入。
注意:PLL的输出频率不能超过72MHz
0000:PLL 2倍频输出 1000:PLL 10倍频输出
0001:PLL 3倍频输出 1001:PLL 11倍频输出
0010:PLL 4倍频输出 1010:PLL 12倍频输出
0011:PLL 5倍频输出 1011:PLL 13倍频输出
0100:PLL 6倍频输出 1100:PLL 14倍频输出
0101:PLL 7倍频输出 1101:PLL 15倍频输出
0110:PLL 8倍频输出 1110:PLL 16倍频输出
0111:PLL 9倍频输出 1111:PLL 16倍频输出
PLLXTPRE:HSE分频器作为PLL输入 (HSE divider for PLL entry) 位17
由软件置’1’或清’0’来分频HSE后作为PLL输入时钟。只能在关闭PLL时才能写入此位。
0:HSE不分频
1:HSE 2分频
PLLSRC:PLL输入时钟源 (PLL entry clock source) 位16
由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。
0:HSI振荡器时钟经2分频后作为PLL输入时钟
1:HSE时钟作为PLL输入时钟。
PPRE2[2:0]:高速APB预分频(APB2) (APB high-speed prescaler (APB2)) 位13:11
由软件置’1’或清’0’来控制高速APB2时钟(PCLK2)的预分频系数。
0xx:HCLK不分频
100:HCLK 2分频
101:HCLK 4分频
110:HCLK 8分频
111:HCLK 16分频
PPRE1[2:0]:低速APB预分频(APB1) (APB low-speed prescaler (APB1)) 位10:8
由软件置’1’或清’0’来控制低速APB1时钟(PCLK1)的预分频系数。
警告:软件必须保证APB1时钟频率不超过36MHz。
0xx:HCLK不分频
100:HCLK 2分频
101:HCLK 4分频
110:HCLK 8分频
111:HCLK 16分频
HPRE[3:0]: AHB预分频 (AHB Prescaler) 位7:4
由软件置’1’或清’0’来控制AHB时钟的预分频系数。
0xxx:SYSCLK不分频
1000:SYSCLK 2分频 1100:SYSCLK 64分频
1001:SYSCLK 4分频 1101:SYSCLK 128分频
1010:SYSCLK 8分频 1110:SYSCLK 256分频
1011:SYSCLK 16分频 1111:SYSCLK 512分频
2.3.3节)。 注意:当AHB时钟的预分频系数大于1时,必须开启预取缓冲器。
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* 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)
{
/* Enable Prefetch Buffer */
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 */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: 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);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}