当前位置:网站首页>学习记录:STM32F103 时钟系统概述工作原理
学习记录:STM32F103 时钟系统概述工作原理
2022-07-06 09:25:00 【Bitter tea seeds】
目录
前言
想要运用好一款单片机必须要知道微控制器原理性的东西,这样在对它进行应用的时候,才能得心应手明白它如何进行的工作。项目出问题时,也能在底层找到问题的源头和解决方案。STM32的时钟系统比51单片机的时钟系统要复杂很多,毕竟51单片机只有一个时钟系统。
从STM32参考手册上,我了解到STM32F103MCU有三种不同的时钟源可被用来驱动系统时钟(SYSCLK): HSI振荡器时钟 、HSE振荡器时钟 、PLL时钟。当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
所以能够知道, STM32采取多种时钟源是为了减少时钟的功耗,在数字电子技术中:同一个电路,时钟越快它消耗的功率就越大,并且抗电磁场的干扰能力也就越弱,脉冲越不稳定。
一、看如下时钟树我们能发现STM32有5个时钟源
(参考正点原子的开发指南)
ⅰ、HSI 是高速内部时钟,RC 振荡器(在Multisim专栏里,对文氏桥电路进行了仿真,想详细了解可以去看一看),频率为 8MHz。
ⅱ、HSE 是高速外部时钟,可接石英/陶瓷谐振器(在Multisim专栏里,对石英晶体电路进行了仿真,想详细了解可以去看一看),或者接外部时钟源,频率范围为4MHz~16MHz。
ⅲ、LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同 时 LSI 还可以作为 RTC 的时钟源。
ⅳ、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
ⅴ、PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为 2~16 倍,但是其输出频率最大不得超过 72MHz。
①、MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,可以选择为 PLL 输出的 2 分频、HSI、HSE或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源。
②、 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及 HSE 的 128 分频。
③、从图中可以看出 USB 的时钟是来自 PLL 时钟源。STM32 中有一个全速功能 的 USB 模块,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB 模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。
④、 STM32 的系统时钟 SYSCLK,它是供 STM32 中绝大部分部件工作的时钟源。系统时钟可选择为 PLL 输出、HSI 或者 HSE。系统时钟最大频率为 72MHz, 当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。
⑤、是指其他所有外设了。从时钟图上可以看出,其他所有外设的时钟最终来源都是 SYSCLK。SYSCLK 通过 AHB 分频器分频后送给各模块使用。这些模块包括:
1、AHB 总线、内核、内存和 DMA 使用的 HCLK 时钟。
2、通过 8 分频后送给 Cortex 的系统定时器时钟,也就是 systick 。
3、直接送给 Cortex 的空闲运行时钟 FCLK。
4、送给 APB1 分频器。APB1 分频器输出一路供 APB1外设使用(PCLK1,最大频率 36MHz),另一路送给定时器(Timer)2、3、4 倍频器使用。
5、送给 APB2分频器。APB2分频器分频输出一路供 APB2 外设使用(PCLK2:最大频率 72MHz),另一路给定时器(Timer)1倍频器使用。
APB1 上面连接的是低速外设,包括电源接口、 备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,APB2 上面连接的是高速外设包 括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。
二、 STM32F103 时钟系统配置
(都是根据STM32的寄存器进行编程的)
typedef struct /*寄存器*/
{
__IO uint32_t CR; //HSI,HSE,CSS,PLL等的使能和就绪标志位
__IO uint32_t CFGR; //PLL等的时钟源选择,分频系数设定
__IO uint32_t CIR; // 清除/使能 时钟就绪中断
__IO uint32_t APB2RSTR; //APB2线上外设复位寄存器
__IO uint32_t APB1RSTR; //APB1线上外设复位寄存器
__IO uint32_t AHBENR; //DMA,SDIO等时钟使能
__IO uint32_t APB2ENR; //APB2线上外设时钟使能
__IO uint32_t APB1ENR; //APB1线上外设时钟使能
__IO uint32_t BDCR; //备份域控制寄存器
__IO uint32_t CSR; //控制状态寄存器
} RCC_TypeDef;
1.SystemInit 初始化程序:
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001; //打开 HSION 位
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;// 复位 HSEON, CSSON 和 PLLON 位
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF; // 复位 HSEBYP 位
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;//复位 CFGR 寄存器
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();
#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
}
SystemInit 主要做了如下三个方面工作: 1) 复位 RCC 时钟配置为默认复位值(默认开始了 HIS) 2) 外部存储器配置 3) 中断向量表地址配置。
2.SetSysClockTo72
将系统时钟频率设置为 72MHz 并配置 HCLK、PCLK2和 PCLK1 预分频器。
初始化之后的状态:
SYSCLK 72MHz
AHB 72MHz
PCLK1 36MHz
PCLK2 72MHz
PLL 72MHz
初始化之后可以通过变量SystemCoreClock获取系统变量。如果SYSCLK=72MHz,那么变量SystemCoreClock=72000000。
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;//HCLK2分频
#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)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
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 */
}
}
SetSysClockTo72 将系统时钟频率设置为 72MHz 并配置 HCLK、PCLK2和 PCLK1 预分频器。
主要通过查询STM32中文参考手册,找到相应的寄存器,明白各个代码的作用。
边栏推荐
- LeetCode#412. Fizz Buzz
- UCORE lab2 physical memory management experiment report
- pytest
- Réponses aux devoirs du csapp 7 8 9
- ucore Lab 1 系统软件启动过程
- Practical cases, hand-in-hand teaching you to build e-commerce user portraits | with code
- A method and implementation of using VSTO to prohibit excel cell editing
- Contest3145 - the 37th game of 2021 freshman individual training match_ A: Prizes
- Sleep quality today 81 points
- LeetCode#36. Effective Sudoku
猜你喜欢
Brief introduction to libevent
CSAPP shell lab experiment report
转行软件测试必需要知道的知识
ucore lab6 调度器 实验报告
Rearrange spaces between words in leetcode simple questions
Example 071 simulates a vending machine, designs a program of the vending machine, runs the program, prompts the user, enters the options to be selected, and prompts the selected content after the use
全网最详细的postman接口测试教程,一篇文章满足你
Réponses aux devoirs du csapp 7 8 9
Es6---es6 content details
Sorting odd and even subscripts respectively for leetcode simple problem
随机推荐
软件测试需求分析之什么是“试纸测试”
Automated testing problems you must understand, boutique summary
Brief description of compiler optimization level
Video scrolling subtitle addition, easy to make with this technique
The most detailed postman interface test tutorial in the whole network. An article meets your needs
What are the commonly used SQL statements in software testing?
Réponses aux devoirs du csapp 7 8 9
Leetcode simple question: check whether two strings are almost equal
Winter vacation daily question - maximum number of balloons
線程及線程池
Introduction to variable parameters
LeetCode#412. Fizz Buzz
UCORE lab2 physical memory management experiment report
遇到程序员不修改bug时怎么办?我教你
ucorelab3
MySQL development - advanced query - take a good look at how it suits you
Nest and merge new videos, and preset new video titles
Sleep quality today 81 points
UCORE LaB6 scheduler experiment report
Knowledge that you need to know when changing to software testing