STM32时钟学习
- 复位
-
- 编程控制系统复位
- ? 用户选择字节的进一步信息,请参考STM32F10xxx闪存编程手册。
- 时钟树简图
-
- 实际的寄存器操作
-
- (1)对RCC_CR寄存器进行设置
- (2)时钟配置寄存器(RCC_CFGR)
- (3)RCC PLL configuration register (RCC_PLLCFGR)
- (4)RCC clock interrupt register (RCC_CIR)
- (5)RCC AHB1 peripheral reset register (RCC_AHB1RSTR)复位
- (6)RCC AHB1 peripheral clock register (RCC_AHB1ENR)使能
- (7)备份域控制寄存器 (RCC_BDCR)
- 代码学习
f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
f(PLL general clock output) = f(VCO clock) / PLLP
f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
PLLN with 192 ≤ PLLN ≤ 432
PLLM with 2 ≤ PLLM ≤ 63
PLLP = 2, 4, 6, or 8
4 <= PLLQ <= 15
复位
支持三种复位形式,分别为系统复位、上电复位和备份区域复位。
电源复位:除了备份区域外的所有寄存器
系统复位:除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器以外的所有寄存器
备份区域复位:只影响备份区域
产生电源复位的事件:
- 上电/掉电复位(POR/PDR复位)
- 从待机模式中返回
产生备份区域复位的事件:
- 软件复位,备份区域复位可由设置备份域控制寄存器 (RCC_BDCR)中的BDRST位产生。
- 在VDD和VBAT两者掉电的前提下,VDD或VBAT上电将引发备份区域复位
产生一个系统复位的事件:
- NRST引脚上的低电平(外部复位)
- 窗口看门狗计数终止(WWDG复位)
- 独立看门狗计数终止(IWDG复位)
- 软件复位(SW复位)
- 低功耗管理复位
编程控制系统复位
我们所能控制的只有系统复位
(1)可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源。
(2)软件的方式进行系统复位:通过将Cortex™-M3中断应用和复位控制寄存器中的SYSRESETREQ位置’1’
(3)低功耗管理复位
在以下两种情况下可产生低功耗管理复位:
在进入待机模式时产生低功耗管理复位:
通过将用户选择字节中的nRST_STDBY位置’1’将使能该复位。这时,即使执行了进入待
机模式的过程,系统将被复位而不是进入待机模式。
在进入停止模式时产生低功耗管理复位:
通过将用户选择字节中的nRST_STOP位置’1’将使能该复位。这时,即使执行了进入停机
模式的过程,系统将被复位而不是进入停机模式。
? 用户选择字节的进一步信息,请参考STM32F10xxx闪存编程手册。
时钟树简图
STM32为了低功耗,将所有的外设时钟都设置为disable。使用外设,需要打开对应时钟。
看图理解时钟源—>系统时钟来源—>各个外设时钟

三种不同的时钟源可被用来驱动系统时钟(SYSCLK): HSI振荡器时钟、 HSE振荡器时钟、 PLL时钟(内部PLL可以用来倍频HSI RC的输出时钟或HSE晶体输出时钟)。
这些设备有40kHz低速内部RC、32.768kHz低速外部晶体2种二级时钟源,当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
实际的寄存器操作
(1)对RCC_CR寄存器进行设置
Reset value: 0x0000 XX83 where X is undefined.
STM32F207支持一种专用的PLL(PLLI2S),用于在I2S接口上生成精确的时钟,以实现高质量的音频性能。
(2)时钟配置寄存器(RCC_CFGR)
Reset value: 0x0000 0000
(3)RCC PLL configuration register (RCC_PLLCFGR)
Address offset: 0x04
Reset value: 0x24003010
该寄存器用于根据公式配置锁相环时钟输出
(4)RCC clock interrupt register (RCC_CIR)
(5)RCC AHB1 peripheral reset register (RCC_AHB1RSTR)复位
(6)RCC AHB1 peripheral clock register (RCC_AHB1ENR)使能
当外设时钟没有启用时,软件不能读出外设寄存器的数值,返回的数值始终是0x0。
(7)备份域控制寄存器 (RCC_BDCR)
代码学习
没有打开任何外设时钟的代码学习
或操作开,与操作关
开HSI
关HSE、CSS、PLL
关HSEBYP
开HSE
不同应用下,时钟频率的选择和使用过程中出现误差的一个校准(配置对应寄存器)
系统复位后,HSI振荡器被选为系统时钟。当时钟源被直接或通过PLL间接作为系统时钟时,它将不能被停止。只有当目标时钟源准备就绪了(经过启动稳定阶段的延迟或PLL稳定),从一个时钟源到另一个时钟源的切换才会发生。在被选择时钟源没有就绪时,系统时钟的切换不会发生。直至目标时钟源就绪,才发生切换。在时钟控制寄存器(RCC_CR)里的状态位指示哪个时钟已经准备好了,哪个时钟目前被用作系统时钟。通过设置备份域控制寄存器(RCC_BDCR)里的RTCSEL[1:0]位,RTCCLK时钟源可以由HSE/128、LSE或LSI时钟提供。除非备份域复位,此选择不能被改变。
/*********************************系统初始化*************************************/
/* PLL (clocked by HSE) used as System clock source */
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* 其他不变,HSION=1 */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* 其他不变,HSEON, CSSON, PLL OFF*/
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* 其他不变,HSEBYP off */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
/* 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)
{
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* 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_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
/* Select the main PLL as system clock source */
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 */
}