STM32的时钟系统RCC详细整理

STM32的时钟系统RCC详细整理
STM32的时钟系统RCC详细整理

STM32的时钟系统

本文档由“~风中的叶~”整理;QQ:654705188

一、综述:

1、时钟源

在STM32 中,一共有5 个时钟源,分别是HSI 、HSE 、LSI 、LSE 、PLL 。

①HSI 是高速内部时钟,RC 振荡器,频率为8MHz ;

②HSE 是高速外部时钟,可接石英/ 陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz ;

③LSI 是低速内部时钟,RC 振荡器,频率为40KHz ;

④LSE 是低速外部时钟,接频率为32.768KHz 的石英晶体;

⑤PLL 为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2 、HSE 或

者HSE/2 。PLL倍频可选择为 2 – 16 倍,但是其输出频率最大不得超过72MHz 。

其中,40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。

STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL端获取,可以选择为1.5分频或者1分频,也就是,当需使用到USB模块时,PLL必须使能,并且时钟配置为48MHz或72MHz。

另外STM32还可以选择一个时钟信号输出到MCO脚(PA.8)上,可以选择为PLL输出的2分频、HSI、HSE或者系统时钟。

系统时钟SYSCLK,它是提供STM32中绝大部分部件工作的时钟源。系统时钟可以选择为PLL输出、HSI、HSE。系系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各个模块使用,AHB分频器可以选择1、2、4、8、16、64、128、256、512分频,AHB分频器输出的时钟送给5大模块使用:

①送给AHB总线、内核、内存和DMA使用的HCLK时钟;

②通过8分频后送给Cortex的系统定时器时钟STCLK;

③直接送给Cortex的空闲运行时钟FCLK;

④送给APB1分频器。APB1分频器可以选择1、2、4、8、16分频,其输出一路供APB1

外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。

该倍频器根据PCLK1的分频值自动选择1或者2倍频,时钟输出供定时器2、3、4使用。

⑤送给APB2分频器。APB2分频器可以选择1、2、4、8、16分频,其输出一路供APB2

外设使用(PCLK2,最大频率72MHz),另外一路送给定时器(Timer)1倍频使用。该倍频器根

据PCLK2的分频值自动选择1或2倍频,时钟输出供定时器1使用。另外APB2分频器还有一

路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、

8分频。

需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。

2、APB1和APB2连接的模块

①连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意USB模块虽然需要一个单独的48MHz 的时钟信号,但是它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB 模块的工作时钟应该是由APB1提供的。

②连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、

GPIOx(PA~PE)、第二功能IO 口。

二、寄存器介绍:

typedef struct

{

__IO uint32_t CR;

__IO uint32_t CFGR;

__IO uint32_t CIR;

__IO uint32_t APB2RSTR;

__IO uint32_t APB1RSTR;

__IO uint32_t AHBENR;

__IO uint32_t APB2ENR;

__IO uint32_t APB1ENR;

__IO uint32_t BDCR;

__IO uint32_t CSR;

#ifdef STM32F10X_CL

__IO uint32_t AHBRSTR;

__IO uint32_t CFGR2;

#endif /* STM32F10X_CL */

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)

uint32_t RESERVED0;

__IO uint32_t CFGR2;

#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */

} RCC_TypeDef;

1、时钟控制寄存器(RCC_CR):(复位值为0x0000 xx83,内部低速时钟使能和就绪,内部时钟校准)

主要功能:内外部高速时钟的使能和就绪标志(含内部高速时钟校准调整),外部高速时钟旁路,时钟安全系统CSS使能,PLL使能和PLL就绪标志。

2、时钟配置寄存器(RCC_CFGR):(复位值为0x0000 0000)

主要功能:系统时钟源切换及状态,AHB、APB1、APB2、ADC、USB预分频,PLL输入时钟源选择及HSE输入PLL分频选择,PLL倍频系数,MCO(PA8)引脚微控制器时钟输出。

3、时钟中断寄存器 (RCC_CIR):(复位值: 0x0000 0000)

主要功能:LSI、LSE、HIS、HSE、PLL就绪中断标志,HSE时钟失效导致时钟安全系统中断标志,LSI、LSE、HIS、HSE、PLL就绪中断使能,清除LSI、LSE、HIS、HSE、PLL就绪中断,清除时钟安全系统中断。

4、APB2外设复位寄存器 (RCC_APB2RSTR):(复位值: 0x0000 0000)

主要功能:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3复位。

5、APB1外设复位寄存器 (RCC_APB1RSTR) :(复位值: 0x0000 0000)

主要功能:TIM2、TIM3、TIM4、TIM5、TIM6、TIM7、WWDG、SPI2、SPI3、USART2、USART3、USART4、USART5、I2C1、I2C2、USB、CAN、BKP、PWR、DAC复位。

6、AHB外设时钟使能寄存器 (RCC_AHBENR) :(复位值: 0x0000 0014睡眠模式时SRAM、闪存接口电路时钟开启)

主要功能:DMA1、DMA2、SRAM、FLITF、CRC、FSMC、SDIO时钟使能。

7、APB2外设时钟使能寄存器(RCC_APB2ENR) :(复位值: 0x0000 0000)

主要功能:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3时钟使能。

8、APB1外设时钟使能寄存器(RCC_APB1ENR) :(复位值: 0x0000 0000)

主要功能:TIM2、TIM3、TIM4、TIM5、TIM6、TIM7、WWDG、SPI2、SPI3、USART2、USART3、USART4、USART5、I2C1、I2C2、USB、CAN、BKP、PWR、DAC时钟使能。

9、备份域控制寄存器 (RCC_BDCR) :(复位值: 0x0000 0000)

主要功能:外部低速振荡器使能和就绪标志及旁路、RTC时钟源选择和时钟使能、备份域软件复位。

10、控制/状态寄存器 (RCC_CSR) :(复位值: 0x0C00 0000 NRST引脚复位标志、上电/掉电复位标志)

主要功能:内部低速振荡器就绪、清除复位标志、NRST引脚复位标志、上电/掉电复位标志、软件复位标志、独立看门狗复位标志、窗口看门狗复位标志、低功耗复位标志。

三、初始化设置

采用8MHz 外部HSE 时钟,在MDK 编译平台中,程序的时钟设置参数流程如下:

将RCC 寄存器重新设置为默认值:RCC_DeInit();

打开外部高速时钟晶振HSE :RCC_HSEConfig(RCC_HSE_ON);

等待外部高速时钟晶振工作:HSEStartUpStatus = RCC_WaitForHSEStartUp();

设置AHB 时钟(HCLK) :RCC_HCLKConfig(RCC_SYSCLK_Div1);

设置APB 2时钟(APB2) :RCC_PCLK2Config(RCC_HCLK_Div1);

设置APB1 时钟(APB1) :RCC_PCLK1Config(RCC_HCLK_Div2);

设置PLL :RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

打开PLL :RCC_PLLCmd(ENABLE);

等待PLL 工作:while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

设置系统时钟:RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

判断PLL 是否是系统时钟:while(RCC_GetSYSCLKSource() != 0x08);

1、使用库函数进行时钟系统初始化配置

void RCC_config()//如果外部晶振为8M,PLLCLK=SYSCLK=72M,HCLK=72M,//P2CLK=72M,P1CLK=36M,ADCCLK=36M,USBCLK=48M,TIMCLK=72M

{

ErrorStatus HSEStartUpStatus;//定义错误状态变量

RCC_DeInit();//将RCC寄存器重新设置为默认值

RCC_HSEConfig(RCC_HSE_ON);//打开外部高速时钟晶振

HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待外部高速时钟晶振工作

if(HSEStartUpStatus == SUCCESS)

{

RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB不分频,HCLK=SYSCLK

RCC_PCLK2Config(RCC_HCLK_Div1);//设置APB2不分频,P2CLK=HCLK

RCC_PCLK1Config(RCC_HCLK_Div2);//设置APB1 为2分频,P1CLK=HCLK/2

FLASH_SetLatency(FLASH_Latency_2);//设置FLASH代码延时

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能预取指缓存

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//设置PLL时钟源,

//外部时钟不分频,为HSE的9倍频8MHz * 9 = 72MHz

RCC_PLLCmd(ENABLE);//使能PLL

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL准备就绪

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置PLL为系统时钟源

while(RCC_GetSYSCLKSource() != 0x08);//判断PLL是否是系统时钟

}

/*RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD, ENABLE);//打开PB和PD用于点亮LED灯*/

}

2、使用寄存器进行RCC时钟初始化配置

void RCC_init(u8 PLL)//输入PLL的倍频值2—16倍频

//HCLK=PLLCLK=SYSCLK=P2CLK=P1CLK*2=ADCCLK*2=TIMCLK=USBCLK*2/3

{

unsigned char temp=0;

//RCC_DeInit(); //将RCC寄存器重新设置为默认值

RCC->CR|=0x00010000; //外部高速时钟使能HSEON

while(!(RCC->CR>>17));//等待外部时钟就绪

RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;

PLL-=2;//抵消2个单位

RCC->CFGR|=PLL<<18; //设置PLL倍频值2~16

RCC->CFGR|=1<<16; //PLL时钟源选择

FLASH->ACR|=0x32; //FLASH 2个延时周期

RCC->CR|=0x01000000; //PLLON

while(!(RCC->CR>>25));//等待PLL锁定

RCC->CFGR|=0x00000002;//PLL作为系统时钟

while(temp!=0x02) //等待PLL作为系统时钟设置成功

{

temp=RCC->CFGR>>2;

temp&=0x03;

}

}

四、相关库函数解析

1、库中所涉及到的结构体

typedef struct

{

uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz */

uint32_t HCLK_Frequency; /*!< returns HCLK clock frequency expressed in Hz */

uint32_t PCLK1_Frequency; /*!< returns PCLK1 clock frequency expressed in Hz */

uint32_t PCLK2_Frequency; /*!< returns PCLK2 clock frequency expressed in Hz */

uint32_t ADCCLK_Frequency; /*!< returns ADCCLK clock frequency expressed in Hz */ }RCC_ClocksTypeDef;

2、库函数解析

void RCC_DeInit(void);//将外设RCC寄存器设为缺省值;(除RCC_BDCR和RCC_CSR)void RCC_HSEConfig(uint32_t RCC_HSE);//设置外部高速晶振(HSE);

//输入:RCC_HSE_OFF,RCC_HSE_ON,RCC_HSE_Bypass(HSE旁路)

ErrorStatus RCC_WaitForHSEStartUp(void);//等待HSE起振;

//返回值:SUCCESS,HSE晶振稳定且就绪;ERROR,HSE晶振未就绪

void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue);//调整内部高速晶振(HSI)校准值

//输入:校准补偿值(该参数取值必须在0到0x1F之间)

void RCC_HSICmd(FunctionalState NewState);//使能或者失能内部高速晶振(HSI)

//输入:ENABLE或者DISABLE(如果HSI被用于系统时钟,或者FLASH编写操作进行中,那么它不能被停振)

void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul);//设置PLL时钟源及倍频系数

//输入:RCC_PLLSource_HSI_Div2,RCC_PLLSource_HSE_Div1,RCC_PLLSource_HSE_Div2

//输入:RCC_PLLMul_2到RCC_PLLMul_16

void RCC_PLLCmd(FunctionalState NewState);//使能或者失能PLL

//输入:ENABLE或者DISABLE

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)

void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div);//

#endif

#ifdef STM32F10X_CL

void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div);//

void RCC_PLL2Config(uint32_t RCC_PLL2Mul);//

void RCC_PLL2Cmd(FunctionalState NewState);//

void RCC_PLL3Config(uint32_t RCC_PLL3Mul);//

void RCC_PLL3Cmd(FunctionalState NewState);//

#endif /* STM32F10X_CL */

void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);//设置系统时钟(SYSCLK)源

// RCC_SYSCLKSource_HSI,RCC_SYSCLKSource_HSE,RCC_SYSCLKSource_PLLCLK

uint8_t RCC_GetSYSCLKSource(void);//返回用作系统时钟的时钟源

//返回值:0x00 HSI作为系统时钟,0x04 HSE作为系统时钟,0x08 PLL作为系统时钟

void RCC_HCLKConfig(uint32_t RCC_SYSCLK);//设置AHB时钟(HCLK)

//输入:RCC_SYSCLK_Div1,RCC_SYSCLK_Div2,RCC_SYSCLK_Div4,RCC_SYSCLK_Div8,

RCC_SYSCLK_Div16,

//RCC_SYSCLK_Div32,RCC_SYSCLK_Div64,RCC_SYSCLK_Div128,RCC_SYSCLK_Div256,

RCC_SYSCLK_Div512

void RCC_PCLK1Config(uint32_t RCC_HCLK);//设置低速AHB时钟(PCLK1)

//输入:RCC_HCLK_Div1,RCC_HCLK_Div2,RCC_HCLK_Div4,RCC_HCLK_Div8,RCC_HCLK_Div16

void RCC_PCLK2Config(uint32_t RCC_HCLK);//设置高速AHB时钟(PCLK2)

//输入:RCC_HCLK_Div1,RCC_HCLK_Div2,RCC_HCLK_Div4,RCC_HCLK_Div8,RCC_HCLK_Div16 void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState);//使能或者失能指定的RCC中断

//输入:RCC_IT_LSIRDY LSI就绪中断->ENABLE或者DISABLE

//RCC_IT_LSERDY LSE就绪中断,RCC_IT_HSIRDY HSI就绪中断

//RCC_IT_HSERDY HSE就绪中断,RCC_IT_PLLRDY PLL就绪中断

#ifndef STM32F10X_CL

void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource);//设置USB时钟(USBCLK)

//输入:RCC_USBCLKSource_PLLCLK_1Div5,USB时钟= PLL时钟除以1.5

RCC_USBCLKSource_PLLCLK_Div1,USB时钟= PLL时钟

#else

void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource);//

#endif /* STM32F10X_CL */

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);//设置ADC时钟(ADCCLK)

//RCC_PCLK2_Div2,ADC时钟 = PCLK / 2;RCC_PCLK2_Div4,ADC时钟 = PCLK / 4;

//RCC_PCLK2_Div6,ADC时钟 = PCLK / 6;RCC_PCLK2_Div8,ADC时钟 = PCLK / 8

#ifdef STM32F10X_CL

void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource); //

void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource);//

#endif /* STM32F10X_CL */

void RCC_LSEConfig(uint8_t RCC_LSE);//设置外部低速晶振(LSE)

//输入:RCC_LSE_OFF,LSE晶振OFF;RCC_LSE_ON,LSE晶振ON;

//RCC_LSE_Bypass,LSE晶振被外部时钟旁路

void RCC_LSICmd(FunctionalState NewState);//使能或者失能内部低速晶振(LSI)

//输入:ENABLE或者DISABLE (IWDG运行的话,LSI不能被失能)

void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);//设置RTC时钟(RTCCLK)源(RTC时钟一经选定即不能更改,除非复位后备域)

//输入:RCC_RTCCLKSource_LSE,选择LSE作为RTC时钟;RCC_RTCCLKSource_LSI,选择LSI作为RTC时钟;RCC_RTCCLKSource_HSE_Div128,选择HSE时钟频率除以128作为RTC时钟

void RCC_RTCCLKCmd(FunctionalState NewState);//使能或者失能RTC时钟

//输入:ENABLE或者DISABLE

void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks);//返回时钟的频率

//输入:指向结构RCC_ClocksTypeDef的指针,包含了各个时钟的频率(单位为Hz)

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);//使能或者失能AHB 外设时钟

//输入:RCC_AHBPeriph_DMA,DMA时钟->ENABLE或者DISABLE;

//RCC_AHBPeriph_SRAM,SRAM时钟;RCC_AHBPeriph_FLITF,FLITF时钟

//RCC_AHBPeriph_DMA1,DMA1时钟;RCC_AHBPeriph_DMA2,DMA2时钟

//RCC_AHBPeriph_CRC,CRC时钟;RCC_AHBPeriph_FSMC,FSMC时钟

//RCC_AHBPeriph_SDIO,SDIO时钟

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);//使能或者失能APB2外设时钟

//输入:RCC_APB2Periph_AFIO,功能复用IO时钟->ENABLE或者DISABLE;

//RCC_APB2Periph_GPIOA,GPIOA时钟;RCC_APB2Periph_GPIOB,GPIOB时钟;

//RCC_APB2Periph_GPIOC,GPIOC时钟;RCC_APB2Periph_GPIOD,GPIOD时钟;

//RCC_APB2Periph_GPIOE,GPIOE时钟;RCC_APB2Periph_ADC1,ADC1时钟;

//RCC_APB2Periph_ADC2,ADC2时钟;RCC_APB2Periph_TIM1,TIM1时钟;

//RCC_APB2Periph_SPI1,SPI1时钟;RCC_APB2Periph_USART1,USART1时钟;

//RCC_APB2Periph_ALL,全部APB2外设时钟

void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);//使能或者失能APB1外设时钟

//输入:RCC_APB1Periph_TIM2,TIM2时钟->ENABLE或者DISABLE;

//RCC_APB1Periph_TIM3,TIM3时钟;RCC_APB1Periph_TIM4,TIM4时钟

//RCC_APB1Periph_WWDG,WWDG时钟;RCC_APB1Periph_SPI2,SPI2时钟

//RCC_APB1Periph_USART2,USART2时钟;RCC_APB1Periph_USART3,USART3时钟

//RCC_APB1Periph_I2C1,I2C1时钟;RCC_APB1Periph_I2C2,I2C2时钟

//RCC_APB1Periph_USB,USB时钟;RCC_APB1Periph_CAN,CAN时钟

//RCC_APB1Periph_BKP,BKP时钟;RCC_APB1Periph_PWR,PWR时钟

//RCC_APB1Periph_ALL,全部APB1外设时钟

#ifdef STM32F10X_CL

void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);//

#endif /* STM32F10X_CL */

void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);//强制或者释放高速APB(APB2)外设复位

//输入:同void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);函数的值void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);//强制或者释放低速APB(APB1)外设复位

//输入:同void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);函数的值//例:/* Enter the SPI1 peripheral to reset */

//RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);

/* Exit the SPI1 peripheral from reset */

//RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);

void RCC_BackupResetCmd(FunctionalState NewState);//强制或者释放后备域复位

void RCC_ClockSecuritySystemCmd(FunctionalState NewState);//使能或者失能时钟安全系统

//输入:ENABLE或者DISABLE

void RCC_MCOConfig(uint8_t RCC_MCO);//选择在MCO管脚上输出的时钟源

//输入:RCC_MCO_NoClock 无时钟被选中;RCC_MCO_SYSCLK 选中系统时钟;

//RCC_MCO_HSI 选中HSI ;RCC_MCO_HSE 选中HSE ;

//RCC_MCO_PLLCLK_Div2 选中PLL时钟除以2

//警告:当选中系统时钟作为MCO管脚的输出时,注意它的时钟频率不超过50MHz(最大I/O速率)。

FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);//检查指定的RCC标志位设置与否

//输入:待检查的RCC标志位

//RCC_FLAG_HSIRDY ,HSI晶振就绪;RCC_FLAG_HSERDY ,HSE晶振就绪;

//RCC_FLAG_PLLRDY ,PLL就绪;RCC_FLAG_LSERDY ,LSI晶振就绪;

//RCC_FLAG_LSIRDY ,LSE晶振就绪;RCC_FLAG_PINRST ,管脚复位;

//RCC_FLAG_PORRST ,POR/PDR复位;RCC_FLAG_SFTRST ,软件复位;

//RCC_FLAG_IWDGRST ,IWDG复位;RCC_FLAG_WWDGRST ,WWDG复位;

//RCC_FLAG_LPWRRST ,低功耗复位

//返回值:RCC_FLAG的新状态(SET或者RESET)

//例:/* Test if the PLL clock is ready or not */

//FlagStatus Status;

//Status = RCC_GetFlagStatus(RCC_FLAG_PLLRDY);

//if(Status == RESET)

//{

//...

//}

//else

void RCC_ClearFlag(void);//清除RCC的复位标志位

//(可以清除的复位标志位有:RCC_FLAG_PINRST, RCC_FLAG_PORRST,

//RCC_FLAG_SFTRST, RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST,

RCC_FLAG_LPWRRST)

ITStatus RCC_GetITStatus(uint8_t RCC_IT);//检查指定的RCC中断发生与否

//输入:RCC_IT_LSIRDY,LSI晶振就绪中断;RCC_IT_LSERDY,LSE晶振就绪中断//RCC_IT_HSIRDY,HSI晶振就绪中断;RCC_IT_HSERDY,HSE晶振就绪中断

//RCC_IT_PLLRDY,PLL就绪中断;RCC_IT_CSS,时钟安全系统中断

//返回值:RCC_IT的新状态

//例:

/* Test if the PLL Ready interrupt has occurred or not */

//ITStatus Status;

//Status = RCC_GetITStatus(RCC_IT_PLLRDY);

//if(Status == RESET)

//{

//...

//}

//else

//{

//...

//}

void RCC_ClearITPendingBit(uint8_t RCC_IT);//清除RCC的中断待处理位

//RCC_IT_LSIRDY,LSI晶振就绪中断;RCC_IT_LSERDY,LSE晶振就绪中断

//RCC_IT_HSIRDY,HSI晶振就绪中断;RCC_IT_HSERDY,HSE晶振就绪中断

//RCC_IT_PLLRDY,PLL就绪中断;RCC_IT_CSS,时钟安全系统中断

五、实例详解

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined

STM32F10X_HD_VL)//如果定义了这些系统时钟将设为24M,如果没有定义则为72M

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

#else

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz 24000000 */

/* #define SYSCLK_FREQ_36MHz 36000000 */

/* #define SYSCLK_FREQ_48MHz 48000000 */

/* #define SYSCLK_FREQ_56MHz 56000000 */

#define SYSCLK_FREQ_72MHz 72000000 //系统时钟默认值的定义,如果没有定义外部高速时钟则用内部高速时钟,为8000000

/*只需修改以上几句就可以自动设置使用外部倍频作为系统时钟,如果以上宏都未定义则在下边把内部高速时钟作为系统时钟*/

#endif

/*!< Uncomment the following line if you need to use external SRAM mounted

on STM3210E-EVAL board (STM32 High density and XL-density devices) or on STM32100E-EVAL board (STM32 High-density value line devices) as data memory */

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)//内外部SRAM选择

/* #define DATA_IN_ExtSRAM */

#endif

/*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */

/* #define VECT_TAB_SRAM */

#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. //向量表的基址偏移量

This value must be a multiple of 0x100. */

/**

* @}

*/

/** @addtogroup STM32F10x_System_Private_Macros

* @{

*/

/**

* @}

*/

/** @addtogroup STM32F10x_System_Private_Variables

* @{

*/

/****************************************************************************** *

* Clock Definitions;以下为把系统时钟的定义值传给系统内核时钟变量,如果没有定义外部高速时钟则用内部高速时钟,为8M

******************************************************************************* /

#ifdef SYSCLK_FREQ_HSE

uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_24MHz

uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_36MHz

uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_48MHz

uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_56MHz

uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_72MHz

uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */

#else /*!< HSI Selected as System Clock source */

uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) 如果没有定义外部高速时钟则用内部高速时钟,为8000000*/ #endif

__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};//AHB 配方表

/**

* @}

*/

/** @addtogroup STM32F10x_System_Private_FunctionPrototypes

* @{

*/

/****************************************************************************** ***

以下为函数声明

******************************************************************************* **/

static void SetSysClock(void); //设置系统时钟的函数声明

//以下为根据不同的系统时钟的定义来声明用到的相应的函数,为后面的函数调用做好准备#ifdef SYSCLK_FREQ_HSE

static void SetSysClockToHSE(void);

#elif defined SYSCLK_FREQ_24MHz

static void SetSysClockTo24(void);

#elif defined SYSCLK_FREQ_36MHz

static void SetSysClockTo36(void);

#elif defined SYSCLK_FREQ_48MHz

static void SetSysClockTo48(void);

#elif defined SYSCLK_FREQ_56MHz

static void SetSysClockTo56(void);

#elif defined SYSCLK_FREQ_72MHz

static void SetSysClockTo72(void);

#endif

#ifdef DATA_IN_ExtSRAM //外部SRAM选择后的初始化函数声明

static void SystemInit_ExtMemCtl(void);

#endif /* DATA_IN_ExtSRAM */

/**

* @}

*/

/** @addtogroup STM32F10x_System_Private_Functions

* @{

*/

/**

* @brief Setup the microcontroller system

* Initialize the Embedded Flash Interface, the PLL and update the * SystemCoreClock variable.

* @note This function should be used only after reset.

* @param None

* @retval None

*/

void SystemInit (void)//系统初始化函数,设置系统的时钟及时钟中断(在

startup_stm32f10x_md.s中调用)(复位RCC时钟配置为默认状态,直到设置时钟函数) {

/* Reset the RCC clock configuration to the default reset state(for debug purpose) */

/* Set HSION bit */

RCC->CR |= (uint32_t)0x00000001; //内部高速时钟使能,内部8MHz时钟开启

/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

#ifndef STM32F10X_CL

RCC->CFGR &= (uint32_t)0xF8FF0000;//MCO微控制器没有时钟输出(对外部引脚),ADC

预分频PCLK2 2分频后作为ADC时钟,APB预分频HCLK不分频,AHB预分频SYSCLK不分频,HSI 作为系统时钟

//HSI作为系统时钟输出(已输出),

SYSCLK=PCLK=PCLK1=PCLK2=8M,ADCCLK=1/2(PCLK2)=4M

#else

RCC->CFGR &= (uint32_t)0xF0FF0000;//同上;RCC->CFGR的27位为保留位始终为0 ,HSI作为系统时钟输出(未输出原因为未编译)

#endif /* STM32F10X_CL */

/* Reset HSEON, CSSON and PLLON bits */

RCC->CR &= (uint32_t)0xFEF6FFFF;//时钟监测器关闭,HSE振荡器关闭

/* Reset HSEBYP bit */

RCC->CR &= (uint32_t)0xFFFBFFFF;//外部4-25MHz振荡器没有旁路

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

RCC->CFGR &= (uint32_t)0xFF80FFFF; //PLL时钟1.5倍分频作为USB时钟,PLL 2倍频输出,HSE不分频,HSI时钟2分频后作为PLL输入时钟

//PLLCLK=HSICLK=8M(还未输

出),HSECLK=HSEOSC,USBCLK=PLLCLK/1.5 ,除PLL外其他分频系数都为0

#ifdef STM32F10X_CL

/* Reset PLL2ON and PLL3ON bits */

RCC->CR &= (uint32_t)0xEBFFFFFF;//CR中的26和28位置0

/* 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();//如果宏定义了外部SRAM则对其初始化控制

#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. 向量表放在内部SRAM中*/

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. 向量表放在内部flash中*/

#endif

}

/**

* @brief Update SystemCoreClock according to Clock Register Values

* @note None

* @param None

* @retval None

*/

void SystemCoreClockUpdate (void)

{

uint32_t tmp = 0, pllmull = 0, pllsource = 0;

#ifdef STM32F10X_CL

uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0; #endif /* STM32F10X_CL */

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined

STM32F10X_HD_VL)

uint32_t prediv1factor = 0;

#endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */

/* Get SYSCLK source -------------------------------------------------------*/ tmp = RCC->CFGR & RCC_CFGR_SWS;

switch (tmp)

{

case 0x00: /* HSI used as system clock */

SystemCoreClock = HSI_VALUE;

break;

case 0x04: /* HSE used as system clock */

SystemCoreClock = HSE_VALUE;

break;

case 0x08: /* PLL used as system clock */

/* Get PLL clock source and multiplication factor ----------------------*/ pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;

pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;

#ifndef STM32F10X_CL

pllmull = ( pllmull >> 18) + 2;

if (pllsource == 0x00)

{

/* HSI oscillator clock divided by 2 selected as PLL clock entry */

SystemCoreClock = (HSI_VALUE >> 1) * pllmull;

}

else

{

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined

STM32F10X_HD_VL)

prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;

/* HSE oscillator clock selected as PREDIV1 clock entry */

SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;

#else

/* HSE selected as PLL clock entry */

if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)

{/* HSE oscillator clock divided by 2 */

SystemCoreClock = (HSE_VALUE >> 1) * pllmull;

}

else

{

SystemCoreClock = HSE_VALUE * pllmull;

}

#endif

}

#else

pllmull = pllmull >> 18;

if (pllmull != 0x0D)

{

pllmull += 2;

}

else

{ /* PLL multiplication factor = PLL input clock * 6.5 */

pllmull = 13 / 2;

}

if (pllsource == 0x00)

{

/* HSI oscillator clock divided by 2 selected as PLL clock entry */ SystemCoreClock = (HSI_VALUE >> 1) * pllmull;

}

else

{/* PREDIV1 selected as PLL clock entry */

/* Get PREDIV1 clock source and division factor */

prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;

prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;

if (prediv1source == 0)

{

/* HSE oscillator clock selected as PREDIV1 clock entry */

SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; }

else

{/* PLL2 clock selected as PREDIV1 clock entry */

/* Get PREDIV2 division factor and PLL2 multiplication factor */ prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1;

pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2;

SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;

}

}

#endif /* STM32F10X_CL */

break;

default:

SystemCoreClock = HSI_VALUE;

break;

}

/* Compute HCLK clock frequency ----------------*/

/* Get HCLK prescaler */

tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];

/* HCLK clock frequency */

SystemCoreClock >>= tmp;

}

/**

* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. * @param None

* @retval None

*/

static void SetSysClock(void)//根据不同的宏定义,设置不同的系统时钟

{

#ifdef SYSCLK_FREQ_HSE

SetSysClockToHSE();

#elif defined SYSCLK_FREQ_24MHz

SetSysClockTo24();

#elif defined SYSCLK_FREQ_36MHz

SetSysClockTo36();

#elif defined SYSCLK_FREQ_48MHz

SetSysClockTo48();

#elif defined SYSCLK_FREQ_56MHz

SetSysClockTo56();

#elif defined SYSCLK_FREQ_72MHz

SetSysClockTo72();

#endif

/* If none of the define above is enabled, the HSI is used as System clock

source (default after reset) */

}

/**

* @brief Setup the external memory controller. Called in startup_stm32f10x.s * before jump to __main

* @param None

* @retval None

*/

#ifdef DATA_IN_ExtSRAM

/**

* @brief Setup the external memory controller.

* Called in startup_stm32f10x_xx.s/.c before jump to main.

* This function configures the external SRAM mounted on STM3210E-EVAL * board (STM32 High density devices). This SRAM will be used as program * data memory (including heap and stack).

* @param None

* @retval None

*/

void SystemInit_ExtMemCtl(void)

{

/*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is

required, then adjust the Register Addresses */

/* Enable FSMC clock */

RCC->AHBENR = 0x00000114;

/* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */

RCC->APB2ENR = 0x000001E0;

/* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ /*---------------- SRAM Address lines configuration -------------------------*/ /*---------------- NOE and NWE configuration --------------------------------*/ /*---------------- NE3 configuration ----------------------------------------*/ /*---------------- NBL0, NBL1 configuration ---------------------------------*/

GPIOD->CRL = 0x44BB44BB;

GPIOD->CRH = 0xBBBBBBBB;

GPIOE->CRL = 0xB44444BB;

GPIOE->CRH = 0xBBBBBBBB;

GPIOF->CRL = 0x44BBBBBB;

GPIOF->CRH = 0xBBBB4444;

GPIOG->CRL = 0x44BBBBBB;

GPIOG->CRH = 0x44444B44;

/*---------------- FSMC Configuration

---------------------------------------*/

/*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/

FSMC_Bank1->BTCR[4] = 0x00001011;

FSMC_Bank1->BTCR[5] = 0x00000200;

}

#endif /* DATA_IN_ExtSRAM */

#ifdef SYSCLK_FREQ_HSE

/**

* @brief Selects HSE as System clock source and configure HCLK, PCLK2

* and PCLK1 prescalers.

* @note This function should be used only after reset.

* @param None

* @retval None

*/

static void SetSysClockToHSE(void)

{

__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

stm32:系统时钟

实验4 系统时钟实验 上一章,我们介绍了STM32 内部系统滴答定时器,该滴答定时器产生的延时非常精确。在本章中,我们将自定义RCC系统时钟,通过改变其倍频与分频实现延时时间变化,实现LED灯闪烁效果。通过本章的学习,你将了解 RCC系统时钟的使用。本章分为以下学习目标: 1、了解 STM32 的系统构架。 2、了解 STM32 的时钟构架。 3、了解 RCC 时钟的操作步骤。 1.1 STM32 的系统构架 STM32 的时钟比较复杂,它可以选择多种时钟源,也可以选择不一样的时钟频率,而且在系统总线上面,每条系统的时钟选择都是有差异的。所以想要清楚的了解 STM32 的时钟分配,我们先来了解一下 STM32 的系统构架是什么样的。 从上图我们知道,RCC 时钟输出时钟出来,然后经过 AHB 系统总线,分别

分配给其他外设时钟,而不一样的外设,是先挂在不一样的桥上的。比如: ADC1、ADC2、 SPI1、GPIO 等都是挂在 APB2 上面,而有些是挂在 APB1上面,所以,虽然它们都是从 RCC 获取的时钟,但是它们的频率有时候是不一样的。 1.2 STM32 的时钟树 STM32 单片机上电之后,系统默认是用的时钟是单片机内部的高速晶振时钟,而这个晶振容易受到温度的影响,所以晶振跳动的时候不是有一定的影响,所以一般开发使用的时候都是使用外部晶振,而且单片机刚启动的时候,它的时钟频率是 8MHZ,而 STM32 时钟的最高频率是 72MHZ,所以单片机一般开机之后运行的程序是切换时钟来源,并设置时钟频率。大家可能有点疑惑,在第一章到第三章之中,我们并没有看到单片机开机之后设置时钟来源和时钟频率的。其实在使用库函数的时候,其实在库函数启动文件里面,是帮助我们把时钟频率设置到 72MHZ 了。大家可以打开一个库函数工程,在 system_stm32f10x.c 的第 106行,它定义了一个 SYSCLK_FREQ_72MHz: #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else #define SYSCLK_FREQ_72MHz 72000000 然后在下面的程序中,根据这个 SYSCLK_FREQ_72MHz 定义,它默认设置成 72MHZ。接下来我们来看一下具体的 RCC 时钟树:

stm32时钟详细说明

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。其实是四个时钟源,如下图所示(灰蓝色),PLL是由锁相环电路倍频得到PLL时钟。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、 4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。 ⑤、送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。

STM32时钟初始化函数SysInit详解

花了一天的时间,总算是了解了SystemInit()函数实现了哪些功能,初学STM32,,现记录如下(有理解错误的地方还请大侠指出):使用的是3.5的库,用的是STM32F107VC,开发环境RVMDK4.23 我已经定义了STM32F10X_CL,SYSCLK_FREQ_72MHz 函数调用顺序: startup_stm32f10x_cl.s(启动文件)→SystemInit() → SetSysClock () →SetSysClockTo72() 初始化时钟用到的RCC寄存器复位值: RCC_CR = 0x0000 xx83; RCC_CFGR = 0x0000 0000;RCC_CIR = 0x0000 0000; RCC_CFGR2 = 0x0000 0000; SystemInit() 在调用SetSysClock()之前RCC寄存器的值如下(都是一些与运算,或运算,在此就不赘述了): RCC->CR = 0x0000 0083; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;至于这些寄存器都代表着什么意思,详见芯片资料RCC寄存器,该文重点不在此处;SetSysClock()函数如下: static void SetSysClock(void) { #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz//我的定义的是SYSCLK_FREQ_72MHz,所以调用SetSysClockTo72() SetSysClockTo72(); #endif } SetSysClockTo72()函数如下: 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

设置stm32系统各部分时钟

设置stm32系统各部分时钟 函数如下: /******************************************************************** ****** * 函数名: RccInitialisation* 函数描述: 设置系统各部分时钟* 输入参数: 无* 输出结果: 无* 返回值: 无 ******************************************************************** ******/void RccInitialisation(void){/* 定义枚举类型变量HSEStartUpStatus */ErrorStatus HSEStartUpStatus;/* 复位系统时钟设置*/RCC_DeInit();/* 开启HSE*/RCC_HSEConfig(RCC_HSE_ON);/* 等待HSE 起振并稳定*/HSEStartUpStatus = RCC_WaitForHSEStartUp();/* 判断HSE 起是否振成功,是则进入if()内部*/if(HSEStartUpStatus == SUCCESS){/* 选择HCLK(AHB)时钟源为SYSCLK 1 分频*/RCC_HCLKConfig(RCC_SYSCLK_Div1);/* 选择PCLK2 时钟源为HCLK(AHB) 1 分频 */RCC_PCLK2Config(RCC_HCLK_Div1);/* 选择PCLK1 时钟源为HCLK(AHB) 2 分频*/RCC_PCLK1Config(RCC_HCLK_Div2);/* 设置FLASH 延时周期数为2 */FLASH_SetLatency(FLASH_Latency_2);/* 使能FLASH 预取缓存*/FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* 选择锁相环(PLL)时钟源为HSE 1 分频,倍频数为9,则PLL 输出频率为 8MHz * 9 = 72MHz*/RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/* 使能PLL */RCC_PLLCmd(ENABLE);/* 等待PLL 输出稳 定*/while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);/* 选择

stm32如何配置时钟

学习STM32笔记2 如何配置时钟 学习STM32笔记2 如何配置时钟 /************************************************************* 该程序目的是用于测试核心板回来后是否能正常工作。包括 两个按键、两个LED现实。按键为PC4、PC5,LED为PA0\PA1。LED为 低电平时点亮。按键为低电平时触发。 ************************************************************/ #i nclude "stm32f10x_lib.h" void RCC_Configuration(void);//设置系统主时钟 void GPIO_Configuration(void);//设置邋邋IO参数 void NVIC_Configuration(void);//设置中断表地址 void delay(void);//延时函数 int main(void) { #ifdef DEBUG debug(); #endifRCC_Configuration(); NVIC_Configuration(); GPIO_Configuration(); while (1) { delay(); //设置指定的数据端口位 GPIO_SetBits(GPIOA,GPIO_Pin_0); //设置指定的数据端口位 delay(); GPIO_ResetBits(GPIOA,GPIO_Pin_0); //清除指定的数据端口位 GPIO_SetBits(GPIOA,GPIO_Pin_1); delay(); GPIO_ResetBits(GPIOA,GPIO_Pin_1); delay(); /********************************************* 使用setbits 与resetbits 是比较简单,其实还是可以使用 其它函数。例如可以使用GPIO_WriteBit GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET); GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);对于好像流水灯呀这些一个整段IO,可以使用GPIO_Write(GPIOA, 0x1101); *********************************************/

stm32系统时钟配置问题

stm32系统时钟配置问题 系统从上电复位到72mz 配置好之前,提供时钟的是内如高速rc 振荡器提 供8MZ 的频率,这个由下面void SystemInit (void)函数的前面的一部分代码来 完成的和保证的:RCC->CR |= (uint32_t)0x00000001; #ifndef STM32F10X_CLRCC->CFGR &= (uint32_t)0xF8FF0000;#elseRCC- >CFGR &= (uint32_t)0xF0FF0000;#endif RCC->CR &= (uint32_t)0xFEF6FFFF; RCC->CR &= (uint32_t)0xFFFBFFFF; RCC->CFGR &= (uint32_t)0xFF80FFFF; #ifdef STM32F10X_CLRCC->CR &= (uint32_t)0xEBFFFFFF; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)RCC->CIR = 0x009F0000; RCC->CFGR2 = 0x00000000;#elseRCC->CIR = 0x009F0000;#endif#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl();#endif#endif 接着void SystemInit (void)调用SetSysClock();函数,将系统时钟配置到 72m,将AHB,APB1,APB2 等外设之前的时钟都配置好,然后切换到72mz 下 运行。所以在使用哪个外设的时候,只需要使能相应的外设时钟就可以了 tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

05_STM32F4通用定时器详细讲解

STM32F4系列共有14个定时器,功能很强大。14个定时器分别为: 2个高级定时器:Timer1和Timer8 10个通用定时器:Timer2~timer5 和 timer9~timer14 2个基本定时器: timer6和timer7 本篇欲以通用定时器timer3为例,详细介绍定时器的各个方面,并对其PWM 功能做彻底的探讨。 Timer3是一个16位的定时器,有四个独立通道,分别对应着PA6 PA7 PB0 PB1 主要功能是:1输入捕获——测量脉冲长度。 2 输出波形——PWM 输出和单脉冲输出。 Timer3有4个时钟源: 1:内部时钟(CK_INT ),来自RCC 的TIMxCLK 2:外部时钟模式1:外部输入TI1FP1与TI2FP2 3:外部时钟模式2:外部触发输入TIMx_ETR ,仅适用于TIM2、TIM3、TIM4,TIM3,对应 着PD2引脚 4:内部触发输入:一个定时器触发另一个定时器。 时钟源可以通过TIMx_SMCR 相关位进行设置。这里我们使用内部时钟。 定时器挂在高速外设时钟APB1或低速外设时钟APB2上,时钟不超过内部高速时钟HCLK ,故当APBx_Prescaler 不为1时,定时器时钟为其2倍,当为1时,为了不超过HCLK ,定时器时钟等于HCLK 。 例如:我们一般配置系统时钟SYSCLK 为168MHz ,内部高速时钟 AHB=168Mhz ,APB1欲分频为4,(因为APB1最高时钟为42Mhz ),那么挂在APB1总线上的timer3时钟为84Mhz 。 《STM32F4xx 中文参考手册》的424~443页列出与通用定时器相关的寄存器一共20个, 以下列出与Timer3相关的寄存器及重要寄存器的简单介绍。 1 TIM3 控制寄存器 1 (TIM3_CR1) 作用:1使能自动重载TIM3_ARR 2定时器的计数器递增或递减计数。 3 事件更新。 4 计数器使能 2 TIM 3 控制寄存器 2 (TIM3_CR2) 3 TIM3 从模式控制寄存器 (TIM3_SMCR) 4 TIM3 DMA/中断使能寄存器 (TIM3_DIER) SYSCLK(最高 AHB_Prescaler APBx_Prescaler

STM32学习笔记(3):系统时钟和SysTick定时器

STM32学习笔记(3):系统时钟和SysTick定时器 1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但 是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为 48MHz的时钟源。该时钟源只能从PLL端获取,可以选择为1.5分频或者1分频,也就是,当需使用到USB模块时,PLL必须使能,并且时钟配置为48MHz 或72MHz。 另外STM32还可以选择一个时钟信号输出到MCO脚(PA.8)上,可以选择为PLL输出的2分频、HSI、HSE或者系统时钟。 系统时钟SYSCLK,它是提供STM32中绝大部分部件工作的时钟源。系统时钟可以选择为PLL输出、HSI、HSE。系系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各个模块使用,AHB分频器可以选择1、2、4、8、16、64、128、256、512分频,其分频器输出的时钟送给5大模块使用: (1)送给AHB总线、内核、内存和DMA使用的HCLK时钟; (2)通过8分频后送给Cortex的系统定时器时钟; (3)直接送给Cortex的空闲运行时钟FCLK; (4)送给APB1分频器。APB1分频器可以选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一

STM32时钟系统与软件配置

STM32时钟系统与软件配置 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法 如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理: 1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。 2)对于少于100脚的产品,有2种接法: 2.1)OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。 2.2)分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面2.1)节省2个外部电阻。 使用HSE时钟,程序设置时钟参数流程: 1、将RCC寄存器重新设置为默认值RCC_DeInit; 2、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON); 3、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp(); 4、设置AHB时钟RCC_HCLKConfig; 5、设置高速AHB时钟RCC_PCLK2Config; 6、设置低速速AHB时钟RCC_PCLK1Config;

STM32定时时间的计算

STM32 定时器定时时间的计算 假设系统时钟是72Mhz,TIM1 是由PCLK2 (72MHz)得到,TIM2-7是由 PCLK1 得到关键是设定时钟预分频数,自动重装载寄存器周期的值/*每1秒发生一次更新事件(进入中断服务程序)。RCC_Configuration()的SystemInit()的 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2表明TIM3CLK为72MHz。因此,每次进入中断服务程序间隔时间为: ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒。定时器的基本设置如下: 1、TIM_TimeBaseStructure.TIM_Prescaler = 7199;//时钟预分频数例如:时钟频率=72/(时钟预分频+1)。 2、TIM_TimeBaseStructure.TIM_Period = 9999; // 自动重装载寄存器周期的值(定时时间)累计 0xFFFF个频率后产生个更新或者中断(也是说定时时间到)。 3、TIM_TimeBaseStructure.TIM_CounterMode=TIM1_CounterMode_Up; //定时器模式向上计数。 4、 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时间分割值。 5、 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//初始化定时器2。 6、 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //打开中断溢出中断。 7、 TIM_Cmd(TIM2, ENABLE);//打开定时器或者: TIM_TimeBaseStructure.TIM_Prescaler = 35999;//分频35999,72M/ (35999+1)/2=1Hz 1秒中断溢出一次。 8、 TIM_TimeBaseStructure.TIM_Period = 2000; //计数值2000 ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+35999)/72M)*(1+2000)=1秒。 9、注意使用不同定时器时,要注意对应的时钟频率。例如TIM2对应的是APB1,而TIM1对应的是APB2 通用定时器实现简单定时功能 以TIME3为例作为说明,简单定时器的配置如下: void TIM3_Config(void) { TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; TIM_DeInit(TIM3); //复位TIM2定时器 /* TIM2 clock enable [TIM2定时器允许]*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* TIM2 configuration */ TIM_TimeBaseStructure.TIM_Period = 49; // 0.05s定时 TIM_TimeBaseStructure.TIM_Prescaler = 35999; // 分频36000 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数方向向上计数 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* Clear TIM2 update pending flag[清除TIM2溢出中断标志] */

STM32滴答时钟

关于STM32 滴答时钟 相信不论是初学者还是高手,都会被STM32的滴答时钟所吸引。STM32有很多计数器,也有很多计数器中断。当别人还在用计数器做定时扫描的时候,我们就默默的开始了滴答时钟做扫描了。让他们去任意的浪费资源吧,我们节约资源,把计数器发挥更大的作用。 Systick定时器属于cortex内核部件,在芯片介绍的datasheet中没有提到过,可以参考 《CortexM3权威指南》或《STM32xxx-Cortex编程手册》。 首先来看Systick的时钟来源,如图一。可以看出在STM32中Systick以HCLK(AHB 时钟)或HCLK/8作为运行时钟。 图1 另外要注意Systick是一个24位的定时器,即一次最多可以计数224个时钟脉冲,这个脉冲计数值被保存到当前计数值寄存器STK_VAL中,这个计数器只能向下计数,每接收到一个时钟脉冲STK_VAL的值就向下减1,直至0,当STK_VAL的值被减至0时,由硬件自动把重载寄存器STK_LOAD中保存的数据加载到STK_VAL,意思就是它会自动重装。当STK_VAL 的值被倒计至0时,触发中断,就可以在中断服务函数中处理定时事件了。 要让Systick正常工作,必须要对Systick进行配置。它的配置很简单,只有三个控制位和一个标志位,都位于寄存器STK_CRL中,见图二。

图二 ENABLE: 为Systick timer的使能位,此位为1的时候开始计数,为0则关闭Systick timer。 TICKINT: 为中断触发使能位,此位为1的时候并且STK_VAL倒计至0的时候会触发Systick 中断,此位为0的时候不触发中断。 CLKSOURCE: 为Systick的时钟选择位,此位为1的时候Systick的时钟为AHB时钟,此位为0 的时候Systick的时钟为AHB/8(AHB的8分频)。 COUNTFLAG: 为Systick的标志位,当STK_VAL倒计至0,此标志位会被置1。 现在我们不会再为滴答时钟而感到迷惑了吧! 下面将详细描述如何去设置计数器,我们在很多地方看到这样一个函数: SysTick_Config(SystemCoreClock / 1000) 配置为1ms中断一次 SysTick_Config(SystemCoreClock / 100000) 配置为10us中断一次 SysTick_Config(SystemCoreClock / 1000000) 配置为10us中断一次 我们将细说一下,SystemCoreClock/100000 为什么是10us 我们从图1时钟数可以看出Systick的时钟和AHB有关,从图2中了解到滴答时钟可设置,结合两处就能看明白。若不去设置,系统默认为AHB时钟,即72MHz。 系统文件中可查找出以下描述: /************************************************************************** ***** * Clock Definitions *************************************************************************** ****/ #ifdef SYSCLK_FREQ_HSE uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */ #elif defined SYSCLK_FREQ_24MHz uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */ #elif defined SYSCLK_FREQ_36MHz uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System

stm32学习之系统时钟

stm32学习之系统时钟 STM32入门学习心得 — 系统时钟 STM32的时钟与单片机相比要复杂的多,它能够对每一个外设以及IO口进行时钟的设置,这是单片机是无法和它比拟的,所以正确的理解和灵活的运用stm32的时 钟是很重要的。 STM32有3个不同的时钟源可以用于驱动系统时钟(SYSCLK),分别为: HSI振荡器时钟(内部高速时钟)。 HSE振荡器时钟(外部高速时钟)。 PLL时钟。 STM32还有两个二级时钟用来驱动独立的看门狗和选择性的驱动RTC。分别为:32KHZ低速内部RC振荡器(LSI RC)用来驱动独立的开门狗和选择性的驱动用于从停止/ 待机模式自动唤醒的RTC。 32.768kHz低速外部晶体振荡器(LSE 晶体振荡器)用来选择性的驱动实时时钟。 注:每个时钟源在使用时都可以独立的打开/关掉,以节省功耗。 在这里我们可以通过框图来直观的理解STM32的系统时钟。系统时钟框图如图1所示。 图一系统框图

通过图一不妨来详细分析下系统各个部分的时钟。 HSI时钟 HSI时钟通过一个8MHz的内部RC振荡器产生,并且可以被直接用作系统时钟,或者经过2倍频后作为PLL的输出作为SYSCLKS时钟。在系统复位时,HSI振荡器被选择默认的系统SYSCLKS时钟。内部时钟的缺点是频率的精确度没有外部晶体振荡器的高。 程序实现(所有程序都是基于固件库): 直接作为SYSCLKS时钟:RCC_DeInit();系统默认 经过PLL输出作为SYSCLKS时钟: RCC_DeInit(); SystemInit (); 可以在固件库中的stm32f10x_rcc.c文件中通过开放宏定义来选择系统时 钟经过倍频后的频率,固件库默认为72MHZ。如图2所示: 如图2所示 HSE时钟 高速外部时钟信号可以通过2个可能的时钟源产生。分别为: HSE 外部晶体/陶瓷共振器。 HSE 外部时钟。 外部时钟源 在该种模式下,必须提高外部时钟源,外部时钟源可以达到25MHz,用户可以通过设置时钟控制寄存器(RCC_CR)中的HSEBYP和HSEON 位选择该模式。占空必50%的外部时钟信号(方波,正弦波,三角波)必须用来驱动OSC_IN引脚,同时OSC_OUT引脚置于高 阻态。 外部晶体振荡器/陶瓷共振器(HSE晶体) 4~16MHz的外部振荡器具有能够在主时钟上产生一个非常精确地速率的优 点。 时钟控制寄存器(RCC_CR)中的HSERDY标志指示了高速外部振荡器是否是稳定的,在启动时,时钟直到硬件设置了该标志位才释放,如果在时钟中断寄存器(RCC_CR)中打开了, 就会产生一个中断。 HSE晶体振荡器可以通过时钟控制寄存器(RCC_CR)中的HSEON位来打开或 禁止。 程序实现(所有程序都是基于固件库): 1.直接作为SYSCLKS时钟: RCC_DeInit(); /*************************外部时钟设置 *****************************/

图文详解stm32时钟树

对于广大初次接触STM32的读者朋友(甚至是初次接触ARM器件的读者朋友)来说,在熟悉了开发环境的使用之后,往往“栽倒”在同一个问题上。这问题有个关键字叫:时钟树。 众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如51,AVR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固定的,用户无法将此时钟速率更改,除非更换晶振。 而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,本文将来详细解析STM32微控制器的时钟树。

图1是STM32微控制器的时钟树,表1是图中各个标号所表示的部件。 标号图1标号释义 1 内部低速振荡器(LSI,40Khz) 2 外部低速振荡器(LSE,32.768Khz) 3 外部高速振荡器(HSE,3-25MHz) 4 内部高速振荡器(HIS,8MHz) 5 PLL输入选择位 6 RTC时钟选择位 7 PLL1分频数寄存器 8 PLL1倍频寄存器 9 系统时钟选择位 10 USB分频寄存器 11 AHB分频寄存器 12 APB1分频寄存器 13 AHB总线 14 APB1外设总线 15 APB2分频寄存器 16 APB2外设总线 17 ADC预分频寄存器 18 ADC外设 19 PLL2分频数寄存器 20 PLL2倍频寄存器 21 PLL时钟源选择寄存器 22 独立看门狗设备 23 RTC设备 图1 STM32的时钟树 在认识这颗时钟树之前,首先要明确“主干”和最终的“分支”。假设使用外部8MHz 晶振作为STM32的时钟输入源(这也是最常见的一种做法),则这个8MHz便是“主干”,而“分支”很显然是最终的外部设备比如通用输入输出设备(GPIO)。这样可以轻易找出第一条时钟的“脉络”:3——5——7——21——8——9——11——13 对此条时钟路径做如下解析: 对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入; 对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振); 对于7,设置外部晶振的分频数(假设1分频); 对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟); 对于8,设置PLL倍频数(假设9倍频); 对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟); 对于11,设置AHB总线分频数(假设1分频); 对于13,时钟到达AHB总线; 在上一章节中所介绍的GPIO外设属于APB2设备,即GPIO的时钟来源于APB2总线,同样在图1中也可以寻获GPIO外设的时钟轨迹:

基于STM32-RTC实时时钟

1 课程设计内容 本文将利用ALIENTEK 2.8寸TFTLCD模块来显示日期时间,实现一个简单的时钟。 2 STM32芯片简介 2006年ARM公司推出了基于ARMv7架构的Cortex系列的标准体系结构,以满足各种技术的不同性能要求,包含A、R、M三个分工明确的系列[1]。其中,A系列面向复杂的尖端应用程序,用于运行开放式的复杂操作系统;R系列适合实时系统;M系列则专门针对低成本的微控制领域。Cortex-M3是首款基于ARMv7-M体系结构的32位标准处理器,具有低功耗、少门数、短中断延迟、低调试成本等众多优点。它是专门为在微控制系统、汽车车身系统、工业控制系统和无线网络等对功耗和成本敏感的嵌入式应用领域实现高系统性能而设计的,它大大简化了编程的复杂性,集高性能、低功耗、低成本于一体[2]。半导体制造厂商意法半导体ST公司是ARM公司Cortex-M3内核开发项目一个主要合作方,2007年6月11日ST公司率先推出了基于Cortex-M3内核的STM32系列MCU。本章将简要介绍STM32系列处理器的分类、内部结构及特点,并对本设计中重点应用的通用定时器做进一步分析。 2.1 STM32 RTC时钟简介 STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC 模块和时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前,先要取消备份区域(BKP)写保护。 RTC 的简化框图,如图 20.1.1 所示:

STM32 时钟详解及范例

一、综述: 1、时钟源 在STM32 中,一共有5 个时钟源,分别是HSI 、HSE 、LSI 、LSE 、PLL 。 ①HSI 是高速内部时钟,RC 振荡器,频率为8MHz ; ②HSE 是高速外部时钟,可接石英/ 陶瓷谐振器,或者接外部时钟源,频率范围是4MHz –16MHz ; ③LSI 是低速内部时钟,RC 振荡器,频率为40KHz ; ④LSE 是低速外部时钟,接频率为32.768KHz的石英晶体; ⑤PLL 为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2 、HSE 或者HSE/2 。PLL倍频可选择为2– 16 倍,但是其输出频率最大不得超过72MHz 。 其中,40kHz 的LSI 供独立看门狗IWDG 使用,另外它还可以被选择为实时时钟RTC 的时钟源。另外,实时时钟RTC 的时钟源还可以选择LSE ,或者是HSE 的128 分频。 STM32 中有一个全速功能的USB 模块,其串行接口引擎需要一个频率为48MHz 的时钟源。该时钟源只能从PLL 端获取,可以选择为 1.5 分频或者1分频,也就是,当需使用到USB 模块时,PLL 必须使能,并且时钟配置为48MHz 或72MHz 。 另外STM32 还可以选择一个时钟信号输出到MCO 脚(PA.8) 上,可以选择为PLL 输出的2分频、HSI 、HSE 或者系统时钟。 系统时钟SYSCLK ,它是提供STM32 中绝大部分部件工作的时钟源。系统时钟可以选择为PLL 输出、HSI 、HSE 。系系统时钟最大频率为72MHz ,它通过AHB 分频器分频后送给各个模块使用,AHB 分频器可以选择 1 、2 、4 、8 、16 、64 、128 、256 、512 分频,AHB分频器输出的时钟送给5大模块使用: ①送给AHB 总线、内核、内存和DMA 使用的HCLK 时钟; ②通过8分频后送给Cortex 的系统定时器时钟STCLK; ③直接送给Cortex 的空闲运行时钟FCLK ; ④送给APB1 分频器。APB1 分频器可以选择1 、2 、4 、8 、16 分频,其输出一路供APB1 外设使用(PCLK1 ,最大频率36MHz ),另一路送给定时器(Timer)2 、3 、4 倍频器使用。该倍频器根据PCLK1的分频值自动选择1或者2倍频,时钟输出供定时器2、3、4使用。 ⑤送给APB2 分频器。APB2 分频器可以选择1 、2 、4 、8 、16 分频,其输出一路供APB2 外设使用(PCLK2 ,最大频率72MHz ),另外一路送给定时器(Timer)1 倍频使用。该倍频器根据PCLK2的分频值自动选择1 或2 倍频,时钟输出供定时器1使用。另外APB2 分频器还有一路输出供ADC 分频器使用,分频后送给ADC 模块使用。ADC 分频器可选择为 2 、4 、6 、8 分频。 需要注意的是定时器的倍频器,当APB 的分频为1 时,它的倍频值为1 ,否则它的倍频值就为2 。file:///C:/DOCUME~1/LU/LOCALS~1/Temp/msohtml1/01/clip_image002.jpg 2、APB1和APB2连接的模块 ①连接在APB1( 低速外设)上的设备有:电源接口、备份接口、CAN 、USB 、I2C1 、I2C2 、UART2 、UART3 、SPI2 、窗口看门狗、Timer2 、Timer3 、Timer4 。注意USB 模块虽然需要一个单独的48MHz 的时钟信号,但是它应该不是供USB 模块工作的时钟,而只是提供给串行接口引擎(SIE) 使用的时钟。USB 模块的工作时钟应该是由APB1 提供的。 ②连接在APB2 (高速外设)上的设备有:UART1 、SPI1 、Timer1 、ADC1 、ADC2 、GPIOx(PA~PE) 、第二功能IO 口。 file:///C:/DOCUME~1/LU/LOCALS~1/Temp/msohtml1/01/clip_image004.jpg 二、寄存器介绍: typedefstruct { __IO uint32_t CR;

STM32时钟简述教学文稿

在STM32F4中,有5个重要的时钟源,为 HSI、 HSE、 LSI、 LSE、 PLL。其中 PLL 实际是分为两个时钟源,分别为主 PLL 和专用 PLL。从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HSI, HSE 以及 PLL 是高速时钟, LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和LSE 是外部时钟源,其他的是内部时钟源。下面我们看看 STM32F4 的这 5 个时钟源,我们讲解顺序是按图中红圈标示的顺序: ①、LSI 是低速内部时钟,RC 振荡器,频率为32kHz 左右。供独立看门狗和自动唤醒单元使用。 ②、LSE 是低速外部时钟,接频率为32.768kHz 的石英晶体。这个主要是RTC 的时钟源。 ③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。核心板接的是8M 的晶振。HSE 也可以直接做为系统时钟或者PLL 输入。 ④、HSI 是高速内部时钟,RC 振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入。 ⑤、PLL 为锁相环倍频输出。STM32F4 有两个PLL:

1)主PLL(PLL)由HSE 或者HSI 提供时钟信号,并具有两个不同的输出时钟。第一个输出PLLP 用于生成高速的系统时钟(最高168MHz) 第二个输出PLLQ 用于生成USB OTG FS 的时钟(48MHz),随机数发生器的时钟和SDIO时钟。 2)专用PLL(PLLI2S)用于生成精确时钟,从而在I2S 接口实现高品质音频性能。

相关文档
最新文档