一、STM32系统架构
STM32 主系统主要由四个驱动单元和四个被动单元构成。
四个驱动单元是:(1)内核 DCode 总线(2)系统总线(3)通用 DMA1(4)通用 DMA2
四个被动单元是:(1)AHB 到 APB 的桥:连接所有的 APB 设备(2)内部 FlASH 闪存(3)内部 SRAM(4)FSMC;
AHB/APB 桥:这两个桥在 AHB 和 2 个 APB 总线间提供同步连接, APB1 操作速度限于36MHz,APB2 操作速度全速72MHz。
二、STM32系统时钟
时钟是单片机的核心,如果没有时钟STM32所有外设都不起作用,因此在进行外设配置时,都要首先开启相对应的时钟。
1.在 STM32 中有五个时钟源,为高速内部时钟(HSI)、 高速外部时钟(HSE)、低速内部时钟(LSI)、 低速外部时钟(LSE)、 锁相环倍频输出(PLL)。(1)其中HSI是由内部RC电路产生时钟,频率为 8MHz。(2)HSE 是高速外部时钟, 可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz,一般都是接8MHz。(3)LSI也是由内部RC 振荡器产生时钟,频率为 40kHz, 独立看门狗的时钟源只能是 LSI,同时 LSI 还可以作为 RTC 的时钟源。(4)LSE也是接外部时钟源,频率为 32.768kHz 的石英晶体,主要作为 RTC 的时钟源。(5)PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、 HSE 或者 HSE/2。倍频可选择为2~16 倍,但是其输出频率最大不得超过 72MHz。
2.系统时钟(SYSCLK)是STM32最重要的时钟,所有外设时钟源都是来自系统时钟。系统时钟主要来自三种时钟源1.HSI、2.PLLCLK、3.HSE。如果系统时钟选择HSE作为时钟来源,当HSE失效则由时钟监视系统(CSS)自动切换为HSI时钟源。
3.RTC实时时钟可以来自1.HSE/128、2.LSE、3.LSI
4.MCO可以输出芯片内部时钟,是PA8引脚。可以输出SYSCLK、HSI、HSE、PLLCLK/2。
5.USB时钟源来自系统时钟,在中间还要经过USB分频器,频率为48MHz。
6. HCLK、PCLK1、TIMxCLK、PCLK2、TIM1CLK、ADCCLK都是经过相对应的分频器或倍成器获得最终时钟频率。其中HCLK最高72MHz,PCLK1最高36MHz、PCLK2最高72MHz。
三、常用的时钟寄存器
1.时钟控制寄存器(RCC_CR)
主要是对HSI、HSE、CSS、PLL等时钟源使能和就绪标志位。使能之后需要因时钟会出现振荡,因此需要通过就绪标志位判断是否稳定。
2.时钟配置寄存器(RCC_CFGR)
主要是用来选择时钟源和分频系数。
3.AHB外设时钟使能寄存器 (RCC_AHBENR)
主要对SDIO、FSMC、CRC、SRAM、DMA、闪存接口时钟使能。
4.APB2 外设时钟使能寄存器(RCC_APB2ENR)
主要对APB2悬挂的外设进行使能
5.APB1 外设时钟使能寄存器(RCC_APB1ENR)
主要对APB1悬挂的外设进行使能
6.备份域控制寄存器 (RCC_BDCR)
备份域控制寄存器中(RCC_BDCR)的LSEON、 LSEBYP、 RTCSEL和RTCEN位处于备份域。因
此,这些位在复位后处于写保护状态,只有在电源控制寄存器(PWR_CR)中的DBP位置’1’后才
能对这些位进行改动。主要是对实时时钟RTC进行相关配置。
四、RCC相关库函数功能及作用
1.void RCC_DeInit(void);
将RCC外设寄存器重置为默认值 ,该函数不改动RCC_CR中的叠加在内部高速时钟校准上的内部高速时钟调整值,该函数不重置备份域控制寄存器RCC_BDCR以及控制/状态寄存器RCC_CSR。
2.void RCC_HSEConfig(uint32_t RCC_HSE);
配置外部高速晶振(HSE),主要分为三种情况1.RCC_HSE_OFF(关闭)2.RCC_HSE_ON (打开)3.RCC_HSE_Bypass (外部高速时钟振荡器旁路)
3.ErrorStatus RCC_WaitForHSEStartUp(void);
等待HSE起振就绪,带超时退出功能
4.void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue);
调整内部高速晶振(HSI)的校准值。
5.void RCC_HSICmd(FunctionalState NewState);
内部高速时钟使能函数。
6.void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul);
锁存器PLL配置,主要包括1.时钟源选择,三种时钟来源。2.倍频系数选择(2-16)
7.void RCC_PLLCmd(FunctionalState NewState);
锁存器PLL使能函数。
8.void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
配置系统时钟的时钟来源,主要有三种来源1. RCC_SYSCLKSource_HSI。2.RCC_SYSCLKSource_HSE 。3.RCC_SYSCLKSource_PLLCLK 。
9.uint8_t RCC_GetSYSCLKSource(void);
获取系统的时钟源
10.void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
对HCLK进行配置,选取系统时钟的倍频因子。
11.void RCC_PCLK1Config(uint32_t RCC_HCLK);
对PCLK1进行配置,选取 HCLK时钟的倍频因子。
12.void RCC_PCLK2Config(uint32_t RCC_HCLK);
对PCLK2进行配置,选取 HCLK时钟的倍频因子。
13.void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState);
使能或者失能RCC中断,HSI / LSE / HSE / PLL就绪中断。
14.void RCC_LSEConfig(uint8_t RCC_LSE);
配置外部高速晶振(LSE),主要分为三种情况1.RCC_LSE_OFF(关闭)2.RCC_LSE_ON (打开)3.RCC_LSE_Bypass (外部高速时钟振荡器旁路)
15.void RCC_LSICmd(FunctionalState NewState);
内部低速时钟使能函数。
16.void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
RTC实时时钟时钟源选择,主要包括1.RCC_RTCCLKSource_LSE。 2.RCC_RTCCLKSource_LSI。3.RCC_RTCCLKSource_HSE_Div128
17.void RCC_RTCCLKCmd(FunctionalState NewState);
使能RTC时钟。
18.void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
对AHB下的外设进行使能, 包括SDIO、FSMC、CRC、SRAM、DMA、闪存接口时钟使能。
19.void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
对APB2下的设备进行使能。
20. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
对APB1下的设备进行使能。
21.void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
对相应总线下的外设进行复位。
22.void RCC_MCOConfig(uint8_t RCC_MCO);
对MCO进行配置,主要选择是那种时钟源输出。
23.FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);
获取RCC状态标志,HSI / HSE / PLL / LSI / LSE就绪标志 ; PIN / POR / PDR / SFT / WWDG / IWDG / LPWG复位标志 。
24.void RCC_ClearFlag(void);
清除RCC复位标志,清除PIN / POR / PDR / SFT / WWDG / IWDG / LPWG复位标志。
25.ITStatus RCC_GetITStatus(uint8_t RCC_IT);
获取中断标志位以检查指定的RCC中断是否已经发生
26.void RCC_ClearITPendingBit(uint8_t RCC_IT);
清除RCC的中断挂起位,清除HSI / LSE / HSE / PLL / CSS(时钟安全系统)就绪中断标志位
五、 系统时钟初始化函数SystemInit
1. SystemInit()初始化函数是在system_stm32f10x.c中。
2. SystemInit()内部函数详解:
(1)RCC->CR |= (uint32_t)0x00000001;//打开高速内部时钟HSI
(2)RCC->CR &= (uint32_t)0xFEF6FFFF;//复位HSE、CSS 、 PLL,设置为0
(3)RCC->CR &= (uint32_t)0xFFFBFFFF;//复位HSEBYP,设置为0
(4)RCC->CFGR &= (uint32_t)0xFF80FFFF;//复位PLLSRC, PLLXTPRE, PLLMUL 等
(5)RCC->CIR = 0x009F0000;//关掉所有中断,清除所有位
(6) SetSysClock();
3.SetSysClock()函数详解:
定义那一种频率就执行相对应的函数,默认系统时钟为72MHz,如果需要其他的可以修改。因默认系统时钟为72MHz,对tatic void SetSysClockTo72(void)函数进行详解
1.RCC->CR |= ((uint32_t)RCC_CR_HSEON);//打开HSE外部时钟
2.do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));//等待外部振荡稳定,如果HSERDY为1时,说明稳定了。
3.RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//使HCLK = SYSCLK
4.RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//使PCLK2 = HCLK
5.RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//使PCLK1 = HCLK/2
6. 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);
//设置HSE作为PLL时钟源,倍频因数选择为9,最终使PLLCLK = HSE * 9 = 72 MHz
7.RCC->CR |= RCC_CR_PLLON;//打开PLL时钟
8.while((RCC->CR & RCC_CR_PLLRDY) == 0){ }//等待时钟稳定
9.RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //把PLL时钟作为系统时钟的时钟源
10.while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){ }//等待PLL作为时钟源
经过系统初始化函数后,最终的配置为:HSE作为PLL时钟源->倍频系数设置为9->PLLCLK为72MHz->HCLK=72MHz->PCLK1=36MHz->PCLK2=72MHz
系统时钟初始化不用调用,在启动文件startup_stm32f10x_hd.s,会直接调用!!!