stm 32 f 4結晶振動管理

13725 ワード

最近STM 32 F 4チップを使って开発して、自分のプログラミングの习惯によって、いくつか学习の记录をして、自分で后で调べやすいようにします.我々は回路を設計する時、一般的にMCUを設計して外部結晶振動を使用して、筆者の仕事の中でかつて外部結晶振動故障チップが正常に起動できない問題(内部結晶振動の古いMCUがない)に出会って、オシロスコープを使って発見して、外部結晶振動を交換した後、問題は解決しました.このことから筆者は,STM 32 F 4シリーズは内部結晶振動を備えており,外部結晶振動が故障した場合には内部結晶振動を完全に使用でき,ソフトウェアが正常に動作することを確保していると考えている.F 4の外部の水晶振動は通常168 Mhzを使うため、内部の水晶振動のデフォルトは168 Mhzではありませんて、ネット上のいくつかの資料を参考にして、チップのハンド・バックを調べて、1つのソフトウェアの保護を設計して、外部の水晶振動が故障する時、自動的に内部の水晶振動を使って168 Mhzにロックします.
        STM 32公式ツアーでは、内部の結晶振動が今では確実に使えるようになったと紹介されていますが、実測することにしましたが、この説はあまり正確ではないことがわかりました.システム滴下タイマーを用いた割り込みでは通常IOを100 HZ方波で間接測定し,オシロスコープ実測では外部結晶振動100 HZを用いて安定し,内部結晶振動を用いて100--103 HZでジャンプするため,最新の公式講演では内部結晶振動の安定性が良好で直接使用できるという説が検討されている.
        具体的な実現構想は以下の通りであり、外部結晶振動ソフトウェア設定関数を記述し、内部結晶振動ソフトウェア設定関数を記述し、クロック安全中断の中でクロック切替をしっかりと行う.コードは次のとおりです.
void NMI_Handler(void)
{
    if(RCC_GetITStatus(RCC_IT_CSS)!= RESET)
    {
        HSI_SetSysClock(); //             
        RCC_ClearITPendingBit(RCC_IT_CSS); //              
    }
}
/ *
 *  HSI ,         
 * 1,  HSI,   HSI  
 * 2,  AHB,APB2,APB1      
 * 3,  PLL     
 *  VCO        m
 *  VCO        
 *  SYSCLK      p
 *  OTG FS,SDIO,RNG      q
 * 4,  PLL,   PLL  
 * 5, PLLCK       SYSCLK
 * 6,         ,  PLLCLK       
 * /
void HSI_SetSysClock(void)	
{
	__IO uint32_t HSIStartUpStatus = 0;
	RCC_DeInit(); //  RCC   
	RCC_HSEConfig(RCC_HSE_OFF); //      (HSE)		
	RCC_HSICmd(ENABLE); //  HSI,HSI = 16M
	while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //    HSI  
	//            1,          
	//             
	RCC-> APB1ENR | = RCC_APB1ENR_PWREN;
	PWR-> CR | = PWR_CR_VOS;
	RCC_HCLKConfig(RCC_SYSCLK_Div1); //  ABH  HCLK =    HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div2); //    APB  PCLK2 =    2  PCLK2 = SYSCLK / 2
	RCC_PCLK1Config(RCC_HCLK_Div4); //    APB  PCLK1 =    4  PCLK = SYSCLK / 4	
	//  VCO    =      /      = 1Mhz,  PLLM =  ,    2 <= PLLM <= 63
	//  VCO    = VCO    * PLLN,  192 <= PLLN <= 432,    PLLN = 336,   VCO         168Mhz
	//  PLL      = VCO    / PLLP,  PLLP = 2,4,6,8     2,  PLL     168Mhz
	//  USB OTG FS    = VCO    / PLLQ,  2 <= PLLQ <= 15     7,       48Mhz	
	RCC_PLLConfig(RCC_PLLSource_HSI,16,336,2,7);
	RCC_PLLCmd(ENABLE);	
	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET); //  PLL  
	/ *  Flash  ,    ,         * /
	FLASH-> ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;		
	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // PLL    , PLL         SYSCLK	
	while(RCC_GetSYSCLKSource()!= 0x08); //         ,  PLLCLK       
}
/ *
 *  HSE ,         
 * 1,  HSE,   HSE  
 * 2,  AHB,APB2,APB1      
 * 3,  PLL     
 *  VCO        m
 *  VCO        
 *  PLLCLK      p
 *  OTG FS,SDIO,RNG      q
 * 4,  PLL,   PLL  
 * 5, PLLCK       SYSCLK
 * 6,         ,  PLLCLK       
 * /
void HSE_SetSysClock(uint32_t frequency)	
{
    __IO uint32_t HSEStartUpStatus = 0;
    RCC_DeInit(); //  RCC   
    RCC_HSEConfig(RCC_HSE_ON); //      HSE
    HSEStartUpStatus = RCC_WaitForHSEStartUp(); //  HSE  
    if(HSEStartUpStatus == SUCCESS)
    {
	RCC_ClockSecuritySystemCmd(ENABLE); //        CSS
	//            1,          
	//             
	RCC-> APB1ENR | = RCC_APB1ENR_PWREN;
	PWR-> CR | = PWR_CR_VOS;
	RCC_HCLKConfig(RCC_SYSCLK_Div1); //  ABH  HCLK =    HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div2); //    APB  PCLK2 =    2  PCLK2 = SYSCLK / 2
	RCC_PCLK1Config(RCC_HCLK_Div4); //    APB  PCLK1 =    4  PCLK = SYSCLK / 4	
	//  VCO    =      /      = 1Mhz,  PLLM =  ,    2 <= PLLM <= 63
	//  VCO    = VCO    * PLLN,  192 <= PLLN <= 432,    PLLN = 336,   VCO         168Mhz
	//  PLL      = VCO    / PLLP,  PLLP = 2,4,6,8     2,  PLL     168Mhz
	//  USB OTG FS    = VCO    / PLLQ,  2 <= PLLQ <= 15     7,       48Mhz
	RCC_PLLConfig(RCC_PLLSource_HSE,  ,336,2,7);
	RCC_PLLCmd(ENABLE); //  PLL		
	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET); //  PLL  
	/ *  Flash  ,    ,         * /
	FLASH-> ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;		
	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // PLL    , PLL         SYSCLK	
	while(RCC_GetSYSCLKSource()!= 0x08); //         ,  PLLCLK       
    }
    else
    {// HSE          HSI  
	HSI_SetSysClock();
    }
}