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でジャンプするため,最新の公式講演では内部結晶振動の安定性が良好で直接使用できるという説が検討されている.
具体的な実現構想は以下の通りであり、外部結晶振動ソフトウェア設定関数を記述し、内部結晶振動ソフトウェア設定関数を記述し、クロック安全中断の中でクロック切替をしっかりと行う.コードは次のとおりです.
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();
}
}