1、時鐘源
在 STM32 中,一共有 5 個時鐘源,分別是 HSI 、 HSE 、 LSI 、 LSE 、 PLL 。
①HSI 是高速內(nèi)部時鐘, RC 振蕩器,頻率為 8MHz ;
②HSE 是高速外部時鐘,可接石英 / 陶瓷諧振器,或者接外部時鐘源,頻率范圍是 4MHz – 16MHz ;
③LSI 是低速內(nèi)部時鐘, RC 振蕩器,頻率為 40KHz ;
④LSE 是低速外部時鐘,接頻率為 32.768KHz 的石英晶體;
⑤PLL 為鎖相環(huán)倍頻輸出,嚴格的來說并不算一個獨立的時鐘源, 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 或者系統(tǒng)時鐘。
系統(tǒng)時鐘 SYSCLK ,它是提供 STM32 中絕大部分部件工作的時鐘源。系統(tǒng)時鐘可以選擇為 PLL 輸出、 HSI 、 HSE 。系系統(tǒng)時鐘最大頻率為 72MHz ,它通過 AHB 分頻器分頻后送給各個模塊使用, AHB 分頻器可以選擇 1 、 2 、 4 、 8 、 16 、 64 、 128 、 256 、 512 分頻,AHB分頻器輸出的時鐘送給 5 大模塊使用:
①送給 AHB 總線、內(nèi)核、內(nèi)存和 DMA 使用的 HCLK 時鐘;
②通過 8 分頻后送給 Cortex 的系統(tǒng)定時器時鐘STCLK;
③直接送給 Cortex 的空閑運行時鐘 FCLK ;
④送給 APB1 分頻器。 APB1 分頻器可以選擇 1 、 2 、 4 、 8 、 16 分頻,其輸出一路供 APB1 外設(shè)使用( PCLK1 ,最大頻率 36MHz ),另一路送給定時器 (Timer)2 、 3 、 4 倍頻器使用。該倍頻器根據(jù)PCLK1的分頻值自動選擇 1 或者 2 倍頻,時鐘輸出供定時器 2 、 3 、 4 使用。
⑤送給 APB2 分頻器。 APB2 分頻器可以選擇 1 、 2 、 4 、 8 、 16 分頻,其輸出一路供 APB2 外設(shè)使用( PCLK2 ,最大頻率 72MHz ),另外一路送給定時器 (Timer)1 倍頻使用。該倍頻器根據(jù)PCLK2的分頻值自動選擇1 或 2 倍頻,時鐘輸出供定時器 1 使用。另外 APB2 分頻器還有一路輸出供 ADC 分頻器使用,分頻后送給 ADC 模塊使用。 ADC 分頻器可選擇為 2 、 4 、 6 、 8 分頻。
需要注意的是定時器的倍頻器,當 APB 的分頻為 1 時,它的倍頻值為 1 ,否則它的倍頻值就為 2 。
2、APB1和APB2連接的模塊
①連接在 APB1( 低速外設(shè) ) 上的設(shè)備有:電源接口、備份接口、 CAN 、 USB 、 I2C1 、 I2C2 、 UART2 、 UART3 、 SPI2 、窗口看門狗、 Timer2 、 Timer3 、 Timer4 。 注意 USB 模塊雖然需要一個單獨的 48MHz 的時鐘信號,但是它應(yīng)該不是供 USB 模塊工作的時鐘,而只是提供給串行接口引擎 (SIE) 使用的時鐘。 USB 模塊的工作時鐘應(yīng)該是由 APB1 提供的。
②連接在 APB2 (高速外設(shè))上的設(shè)備有: 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):(復(fù)位值為0x0000 xx83,內(nèi)部低速時鐘使能和就緒,內(nèi)部時鐘校準)
主要功能:內(nèi)外部高速時鐘的使能和就緒標志(含內(nèi)部高速時鐘校準調(diào)整),外部高速時鐘旁路,時鐘安全系統(tǒng)CSS使能,PLL使能和PLL就緒標志。
2、時鐘配置寄存器(RCC_CFGR):(復(fù)位值為0x0000 0000)
主要功能:系統(tǒng)時鐘源切換及狀態(tài),AHB、APB1、APB2、ADC、USB預(yù)分頻,PLL輸入時鐘源選擇及HSE輸入PLL分頻選擇,PLL倍頻系數(shù),MCO(PA8)引腳微控制器時鐘輸出。
3、時鐘中斷寄存器 (RCC_CIR):(復(fù)位值: 0x0000 0000)
主要功能:LSI、LSE、HIS、HSE、PLL就緒中斷標志,HSE時鐘失效導(dǎo)致時鐘安全系統(tǒng)中斷標志,LSI、LSE、HIS、HSE、PLL就緒中斷使能,清除LSI、LSE、HIS、HSE、PLL就緒中斷,清除時鐘安全系統(tǒng)中斷。
4、APB2外設(shè)復(fù)位寄存器 (RCC_APB2RSTR):(復(fù)位值: 0x0000 0000)
主要功能:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3復(fù)位。
5、APB1外設(shè)復(fù)位寄存器 (RCC_APB1RSTR) :(復(fù)位值: 0x0000 0000)
主要功能:TIM2、TIM3、TIM4、TIM5、TIM6、TIM7、WWDG、SPI2、SPI3、USART2、USART3、USART4、USART5、I2C1、I2C2、USB、CAN、BKP、PWR、DAC復(fù)位。
6、AHB外設(shè)時鐘使能寄存器 (RCC_AHBENR) :(復(fù)位值: 0x0000 0014睡眠模式時SRAM、閃存接口電路時鐘開啟)
主要功能:DMA1、DMA2、SRAM、FLITF、CRC、FSMC、SDIO時鐘使能。
7、APB2外設(shè)時鐘使能寄存器(RCC_APB2ENR) :(復(fù)位值: 0x0000 0000)
主要功能:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3時鐘使能。
8、APB1外設(shè)時鐘使能寄存器(RCC_APB1ENR) :(復(fù)位值: 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) :(復(fù)位值: 0x0000 0000)
主要功能:外部低速振蕩器使能和就緒標志及旁路、RTC時鐘源選擇和時鐘使能、備份域軟件復(fù)位。
10、控制/狀態(tài)寄存器 (RCC_CSR) :(復(fù)位值: 0x0C00 0000 NRST引腳復(fù)位標志、上電/掉電復(fù)位標志)
主要功能:內(nèi)部低速振蕩器就緒、清除復(fù)位標志、NRST引腳復(fù)位標志、上電/掉電復(fù)位標志、軟件復(fù)位標志、獨立看門狗復(fù)位標志、窗口看門狗復(fù)位標志、低功耗復(fù)位標志。
三、初始化設(shè)置
采用8MHz 外部HSE 時鐘,在 MDK 編譯平臺中,程序的時鐘設(shè)置參數(shù)流程如下:
將 RCC 寄存器重新設(shè)置為默認值:RCC_DeInit();
打開外部高速時鐘晶振 HSE : RCC_HSEConfig(RCC_HSE_ON);
等待外部高速時鐘晶振工作: HSEStartUpStatus = RCC_WaitForHSEStartUp();
設(shè)置 AHB 時鐘 (HCLK) : RCC_HCLKConfig(RCC_SYSCLK_Div1);
設(shè)置APB 2時鐘 (APB2) : RCC_PCLK2Config(RCC_HCLK_Div1);
設(shè)置APB1 時鐘 (APB1) : RCC_PCLK1Config(RCC_HCLK_Div2);
設(shè)置 PLL : RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
打開 PLL : RCC_PLLCmd(ENABLE);
等待 PLL 工作: while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
設(shè)置系統(tǒng)時鐘: RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
判斷 PLL 是否是系統(tǒng)時鐘: while(RCC_GetSYSCLKSource() != 0x08);
1、使用庫函數(shù)進行時鐘系統(tǒng)初始化配置
void RCC_config()//如果外部晶振為8M,PLLCLK=SYSCLK=72M,HCLK=72M,//P2CLK=72M,P1CLK=36M,ADCCLK=36M,USBCLK=48M,TIMCLK=72M
{
ErrorStatus HSEStartUpStatus; // 定義錯誤狀態(tài)變量
RCC_DeInit();//將RCC寄存器重新設(shè)置為默認值
RCC_HSEConfig(RCC_HSE_ON); //打開外部高速時鐘晶振
HSEStartUpStatus = RCC_WaitForHSEStartUp();// 等待外部高速時鐘晶振工作
if(HSEStartUpStatus == SUCCESS)
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);//設(shè)置AHB不分頻,HCLK=SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1);//設(shè)置APB2不分頻,P2CLK=HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //設(shè)置APB1 為2分頻,P1CLK=HCLK/2
FLASH_SetLatency(FLASH_Latency_2);//設(shè)置FLASH代碼延時
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能預(yù)取指緩存
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//設(shè)置PLL時鐘源,
//外部時鐘不分頻,為HSE的9倍頻8MHz * 9 = 72MHz
RCC_PLLCmd(ENABLE);//使能PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL準備就緒
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//設(shè)置PLL為系統(tǒng)時鐘源
while(RCC_GetSYSCLKSource() != 0x08);//判斷PLL是否是系統(tǒng)時鐘
}
/*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寄存器重新設(shè)置為默認值
RCC->CR|=0x00010000; //外部高速時鐘使能HSEON
while(!(RCC->CR>>17));//等待外部時鐘就緒
RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2個單位
RCC->CFGR|=PLL<<18; //設(shè)置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作為系統(tǒng)時鐘
while(temp!=0x02) //等待PLL作為系統(tǒng)時鐘設(shè)置成功
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
四、相關(guān)庫函數(shù)解析
1、庫中所涉及到的結(jié)構(gòu)體
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、庫函數(shù)解析
void RCC_DeInit(void);//將外設(shè)RCC寄存器設(shè)為缺省值;(除RCC_BDCR和RCC_CSR)
void RCC_HSEConfig(uint32_t RCC_HSE);//設(shè)置外部高速晶振(HSE);
//輸入:RCC_HSE_OFF,RCC_HSE_ON,RCC_HSE_Bypass(HSE旁路)
ErrorStatus RCC_WaitForHSEStartUp(void);//等待HSE起振;
//返回值:SUCCESS,HSE晶振穩(wěn)定且就緒;ERROR,HSE晶振未就緒
void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue);//調(diào)整內(nèi)部高速晶振(HSI)校準值
//輸入:校準補償值(該參數(shù)取值必須在0到0x1F之間)
void RCC_HSICmd(FunctionalState NewState);//使能或者失能內(nèi)部高速晶振(HSI)
//輸入:ENABLE或者DISABLE(如果HSI被用于系統(tǒng)時鐘,或者FLASH編寫操作進行中,那么它不能被停振)
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul);//設(shè)置PLL時鐘源及倍頻系數(shù)
//輸入: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);//設(shè)置系統(tǒng)時鐘(SYSCLK)源
// RCC_SYSCLKSource_HSI,RCC_SYSCLKSource_HSE,RCC_SYSCLKSource_PLLCLK
uint8_t RCC_GetSYSCLKSource(void);// 返回用作系統(tǒng)時鐘的時鐘源
//返回值:0x00 HSI作為系統(tǒng)時鐘,0x04 HSE作為系統(tǒng)時鐘,0x08 PLL作為系統(tǒng)時鐘
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);//設(shè)置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);// 設(shè)置低速AHB時鐘(PCLK1)
//輸入: RCC_HCLK_Div1, RCC_HCLK_Div2, RCC_HCLK_Div4, RCC_HCLK_Div8, RCC_HCLK_Div16
void RCC_PCLK2Config(uint32_t RCC_HCLK);// 設(shè)置高速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);// 設(shè)置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);// 設(shè)置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);// 設(shè)置外部低速晶振(LSE)
//輸入:RCC_LSE_OFF,LSE晶振OFF;RCC_LSE_ON,LSE晶振ON;
//RCC_LSE_Bypass,LSE晶振被外部時鐘旁路
void RCC_LSICmd(FunctionalState NewState);// 使能或者失能內(nèi)部低速晶振(LSI)
//輸入:ENABLE或者DISABLE (IWDG運行的話,LSI不能被失能)
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);//設(shè)置RTC時鐘(RTCCLK)源(RTC時鐘一經(jīng)選定即不能更改,除非復(fù)位后備域)
//輸入: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);// 返回時鐘的頻率
//輸入:指向結(jié)構(gòu)RCC_ClocksTypeDef的指針,包含了各個時鐘的頻率(單位為Hz)
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);// 使能或者失能AHB外設(shè)時鐘
//輸入: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外設(shè)時鐘
//輸入:RCC_APB2Periph_AFIO,功能復(fù)用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外設(shè)時鐘
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);// 使能或者失能APB1外設(shè)時鐘
//輸入: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外設(shè)時鐘
#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)外設(shè)復(fù)位
//輸入:同void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);函數(shù)的值
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);// 強制或者釋放低速APB(APB1)外設(shè)復(fù)位
//輸入:同void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);函數(shù)的值
//例:/* 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);// 強制或者釋放后備域復(fù)位
void RCC_ClockSecuritySystemCmd(FunctionalState NewState);//使能或者失能時鐘安全系統(tǒng)
//輸入:ENABLE或者DISABLE
void RCC_MCOConfig(uint8_t RCC_MCO);// 選擇在MCO管腳上輸出的時鐘源
//輸入:RCC_MCO_NoClock 無時鐘被選中 ;RCC_MCO_SYSCLK 選中系統(tǒng)時鐘;
//RCC_MCO_HSI 選中HSI ;RCC_MCO_HSE 選中HSE ;
//RCC_MCO_PLLCLK_Div2 選中PLL時鐘除以2
//警告:當選中系統(tǒng)時鐘作為MCO管腳的輸出時,注意它的時鐘頻率不超過50MHz(最大I/O速率)。
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);// 檢查指定的RCC標志位設(shè)置與否
//輸入:待檢查的RCC標志位
//RCC_FLAG_HSIRDY ,HSI晶振就緒;RCC_FLAG_HSERDY ,HSE晶振就緒;
//RCC_FLAG_PLLRDY ,PLL就緒;RCC_FLAG_LSERDY ,LSI晶振就緒;
//RCC_FLAG_LSIRDY ,LSE晶振就緒;RCC_FLAG_PINRST ,管腳復(fù)位 ;
//RCC_FLAG_PORRST ,POR/PDR復(fù)位;RCC_FLAG_SFTRST ,軟件復(fù)位 ;
//RCC_FLAG_IWDGRST ,IWDG復(fù)位;RCC_FLAG_WWDGRST ,WWDG復(fù)位;
//RCC_FLAG_LPWRRST ,低功耗復(fù)位
//返回值:RCC_FLAG的新狀態(tài)(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的復(fù)位標志位
//(可以清除的復(fù)位標志位有: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中斷發(fā)生與否
//輸入:RCC_IT_LSIRDY,LSI晶振就緒中斷;RCC_IT_LSERDY,LSE晶振就緒中斷
//RCC_IT_HSIRDY,HSI晶振就緒中斷;RCC_IT_HSERDY,HSE晶振就緒中斷
//RCC_IT_PLLRDY,PLL就緒中斷;RCC_IT_CSS,時鐘安全系統(tǒng)中斷
//返回值:RCC_IT的新狀態(tài)
//例:
/* 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,時鐘安全系統(tǒng)中斷
五、實例詳解
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)//如果定義了這些系統(tǒng)時鐘將設(shè)為
/* #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 //系統(tǒng)時鐘默認值的定義 ,如果沒有定義外部高速時鐘則用內(nèi)部高速時鐘,為8000000
/*只需修改以上幾句就可以自動設(shè)置使用外部倍頻作為系統(tǒng)時鐘,如果以上宏都未定義則在下邊把內(nèi)部高速時鐘作為系統(tǒng)時鐘*/
#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)//內(nèi)外部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. */
/*******************************************************************************
* Clock Definitions;以下為把系統(tǒng)時鐘的定義值傳給系統(tǒng)內(nèi)核時鐘變量,如果沒有定義外部高速時鐘則用內(nèi)部高速時鐘,為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) 如果沒有定義外部高速時鐘則用內(nèi)部高速時鐘,為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
* @{
*/
/*********************************************************************************
以下為函數(shù)聲明
*********************************************************************************/
static void SetSysClock(void); //設(shè)置系統(tǒng)時鐘的函數(shù)聲明
//以下為根據(jù)不同的系統(tǒng)時鐘的定義來聲明用到的相應(yīng)的函數(shù),為后面的函數(shù)調(diào)用做好準備
#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選擇后的初始化函數(shù)聲明
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)//系統(tǒng)初始化函數(shù),設(shè)置系統(tǒng)的時鐘及時鐘中斷(在startup_stm32f10x_md.s中調(diào)用)(復(fù)位RCC時鐘配置為默認狀態(tài),直到設(shè)置時鐘函數(shù))
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001; //內(nèi)部高速時鐘使能,內(nèi)部8MHz時鐘開啟
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;//MCO微控制器沒有時鐘輸出(對外部引腳),ADC預(yù)分頻PCLK2 2分頻后作為ADC時鐘,APB預(yù)分頻HCLK不分頻,AHB預(yù)分頻SYSCLK不分頻,HSI作為系統(tǒng)時鐘
//HSI作為系統(tǒng)時鐘輸出(已輸出),SYSCLK=PCLK=PCLK1=PCLK2=8M,ADCCLK=1/2(PCLK2)=4M
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;//同上;RCC->CFGR的27位為保留位始終為0 ,HSI作為系統(tǒng)時鐘輸出(未輸出原因為未編譯)
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;//時鐘監(jiān)測器關(guān)閉,HSE振蕩器關(guān)閉
/* 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外其他分頻系數(shù)都為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;//清除中斷標志,關(guān)閉一些中斷
/* 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;//清除中斷標志,關(guān)閉一些中斷
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000; //沒有此寄存器
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000; //清除中斷標志,關(guān)閉一些中斷
#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();//設(shè)置系統(tǒng)時鐘
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. 向量表放在內(nèi)部SRAM中*/
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. 向量表放在內(nèi)部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)//根據(jù)不同的宏定義,設(shè)置不同的系統(tǒng)時鐘
{
#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;
/* 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)
{
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
#ifndef STM32F10X_CL
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#else
if (HSE_VALUE <= 24000000)
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
}
else
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
}
#endif /* STM32F10X_CL */
#endif
/* 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_DIV1;
/* Select HSE as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04)
{
}
}
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 */
}
}
#elif defined SYSCLK_FREQ_24MHz
static void SetSysClockTo72(void)//系統(tǒng)時鐘設(shè)置為72M:SYSCLK=72M,HCLK=72M,PCLK1=36M(最高36M),PCLK2=72M,ADCCLK=36M,
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;//啟動計數(shù),HSE狀態(tài)
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//HSE使能
/* Wait till HSE is ready and if Time out is reached exit */
do //循環(huán),直到HSE使能成功或者超時
{
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;//HSE使能成功
}
else
{
HSEStatus = (uint32_t)0x00;//HSE使能不成功
}
if (HSEStatus == (uint32_t)0x01)//HSE使能成功
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;//flash緩存使能
/* 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;//RCC_CFGR_HPRE_DIV1=0,CFGR中的值不變
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//RCC_CFGR_PPRE2_DIV1=0,CFGR中的值不變
/* PCLK1 = HCLK/2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//低速APB預(yù)分頻把HCLK 2分頻,APB1CLK=HCLK/2
#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 | //PLL輸入時鐘源HSI時鐘2分頻后作為PLL輸入時鐘,HSE分頻器作為PLL輸入HSE不分頻
RCC_CFGR_PLLMULL)); //PLL倍頻系數(shù)PLL 2倍頻輸出(為了清零其他位)
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//PLL輸入時鐘源HSE時鐘作為PLL輸入時鐘,PLL倍頻系數(shù)PLL 9倍頻輸出
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON; //PLL使能
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)//等待PLL使能成功
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));//HSI作為系統(tǒng)時鐘(為了清零其他位)
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //PLL輸出作為系統(tǒng)時鐘
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)//等待直到PLL成功用作系統(tǒng)時鐘源
{
}
}
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 */
}
}
#endif
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |