STM32的时钟系统RCC详细整理
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. */
/*******************************************************************************
*? 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;
??
? /* 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)//系統時鐘設置為72M:SYSCLK=72M,HCLK=72M,PCLK1=36M(最高36M),PCLK2=72M,ADCCLK=36M,
{
? __IO uint32_t StartUpCounter = 0, HSEStatus = 0;//啟動計數,HSE狀態
??
? /* 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 //循環,直到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預分頻把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倍頻系數PLL 2倍頻輸出(為了清零其他位)
??? RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//PLL輸入時鐘源HSE時鐘作為PLL輸入時鐘,PLL倍頻系數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作為系統時鐘(為了清零其他位)
??? RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //PLL輸出作為系統時鐘??
??? /* Wait till PLL is used as system clock source */
??? while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)//等待直到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 */
? }
}
#endif
總結
以上是生活随笔為你收集整理的STM32的时钟系统RCC详细整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 串口初始化结构体和固件库讲解
- 下一篇: STM32通过串口如何接收服务器发来的数