運動控制器34:STM32的復(fù)位與時鐘及庫函數(shù)

復(fù)位

系統(tǒng)復(fù)位

系統(tǒng)復(fù)位有5個來源

  1. NRST引腳的低電平
  2. IWDG
  3. WWDG
  4. 軟件復(fù)位SW
  5. 低功耗管理復(fù)位
    如果設(shè)置了nRST_STDBY和nRST_STOP=1,則進入待機和停止模式時,將產(chǎn)生復(fù)位。
    • 在進入待機模式時產(chǎn)生復(fù)位
    • 進入停止模式時產(chǎn)生復(fù)位
      可以通過查看寄存器來知道復(fù)位的來源

電源復(fù)位

產(chǎn)生電源復(fù)位可能是上電和掉電,POR/PDR或者是從待機模式返回,芯片內(nèi)部有一個20us的脈沖發(fā)出,此時可以保證芯片的復(fù)位。

備份域復(fù)位

備份區(qū)域的復(fù)位只影響備份區(qū)域,可以通過軟件,或者VDD和VBAT兩者都掉電的時候進行復(fù)位,這就是為什么要進行備份重啟時,我們要取掉電池。

時鐘

  • 三種時鐘可以驅(qū)動系統(tǒng)時鐘,HSE,HSI和PLL,內(nèi)部有一個40KHZ的RC,用來保證看門狗的時鐘RTC,RTC在停機后的自動喚醒。另外驅(qū)動RTC的時鐘也可以選擇內(nèi)部的32.768KHZ的時鐘。
  • 簡單來說,外部的高速時鐘就是晶振,低速時鐘是32.768時鐘,而內(nèi)部的高速時鐘是8M,低速時鐘是40KHZ。


    RCC1.png

HSE時鐘

外部高速時鐘可以直接輸入時鐘,或者用晶振產(chǎn)生。

HSI時鐘

時鐘的精度不夠,并且最大只有64M,不太推薦使用。

PLL

如果要用到USB接口,時鐘必須設(shè)置為48M或者72M,可以優(yōu)先選擇72M

LSE

32.768KHZ的時鐘,啟動以后,要等待釋放信號再進行下一步,和上面的晶振的要求一樣。也可以用外部的32.768來提供,此時為旁路模式。

LSI

內(nèi)部的低速時鐘主要用于產(chǎn)生低功耗,在停機和待機模式下運行,提供看門狗和喚醒時鐘。所有的內(nèi)部時鐘都有一個校準(zhǔn),可以用TIM5來進行校準(zhǔn)。

系統(tǒng)時鐘選擇

系統(tǒng)復(fù)位后,HSI被選擇為系統(tǒng)時鐘,這個時候如果我們用到了HSE,需要進行切換。

時鐘安全系統(tǒng)

如果系統(tǒng)出現(xiàn)故障,比如外部時鐘壞了,此時首先關(guān)閉高級定時器的剎車,放置出現(xiàn)燒毀器件,同時將外部時鐘通道關(guān)閉,并自動的切換到內(nèi)部時鐘。

RTC時鐘

RTC是重要的時鐘源,可以有三個來源,內(nèi)部40K,外部32.768K和外部高速時鐘的分頻。

  • 32.768時鐘時,重要電池還可以用,RTC都會運行
  • 內(nèi)部40K,此時VDD如果沒電,不能保證提供。
  • 外部高速時鐘分頻:當(dāng)然不工作啦。

看門狗時鐘

如果看門狗啟動,40K的時鐘強制打開。

時鐘輸出

如果設(shè)置為72M,相當(dāng)于可以通過GPIO給外面輸出:

  • 72M
  • 晶振時鐘
  • 8M
  • PLL/2時鐘

我們先來看一個典型的時鐘配置的程序調(diào)用。

  1. 在MAIN函數(shù)中,最先調(diào)用BSP_Init
  2. 在BSP中,最先進行SystemInit
  3. 系統(tǒng)初始化函數(shù)中,調(diào)用了SetSysClock函數(shù),里面根據(jù)不同的SYSCLK_FREQ_HSE調(diào)用了SetSysClockToHSE();
  4. 如果調(diào)用的是SetSysClockTo72,將時鐘設(shè)置為72M

時鐘都在system_stm32f10x.h里面進行了設(shè)置,標(biāo)準(zhǔn)的RCC庫函數(shù)還有如下的函數(shù)可以使用:另外,還需要特別注意一下的符號的意義:

  • PCLK1 最大36,APB1的時鐘
  • PCLK2 最大72M,APB2的時鐘
  • HCLK 提供給外設(shè)的時鐘,最大72M
  • SYSCLK 經(jīng)AHB分頻以后給HCLK,最大為72M

ADC時鐘配置:ADCCLKConfig

分頻設(shè)置

AdjustHSICalibrationValue

內(nèi)部高速時鐘校準(zhǔn),內(nèi)部時鐘不準(zhǔn)。

AHBPeriphClockCmd

外設(shè)時鐘設(shè)置,其中APB1PeriphClockCmd 和 APB2包括了哪些外設(shè),要稍微留意一下。

備份寄存器復(fù)位:BackupResetCmd

清復(fù)位源的標(biāo)志:ClearFlag

清中斷ClearITPendingBit

如果設(shè)置時鐘的中斷, 比如:RCC_IT_LSIRDY: LSI ready interrupt

安全系統(tǒng)開啟:ClockSecuritySystemCmd

去初始化DeInit

獲取時鐘頻率GetClocksFreq

包括ADC,HCLK,PCLK1,PCLK2,SYSCLK

GetFlagStatus

GetITStatus

獲取系統(tǒng)時鐘源GetSYSCLKSource

HCLKConfig

也就是SYSCLK到HCLK的分頻

HSEConfig LSEConfig

旁路還是用晶振

HSICmd LSICmd

內(nèi)部8M是否使能

ITConfig

時鐘輸出:MCOConfig

PCLK1Config 外設(shè)時鐘設(shè)置

PLLCmd PLL是否使能 PLLConfig

RTCCLKConfig RTCCLKCmd

三個時鐘源

SYSCLKConfig 系統(tǒng)時鐘

USBCLKConfig

WaitForHSEStartUp 等待晶振穩(wěn)定

我們?yōu)榱朔乐咕д駢牧硕鴮?dǎo)致系統(tǒng)直接掛調(diào),可以設(shè)置一個RCC_USEHSI,再一次強調(diào),此時鐘又慢又不準(zhǔn)!

void RCC_USEHSI(void)
{
    GPIO_InitTypeDef X;

    //PD0 PD1分配時鐘
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE );  //對端口D分配APB2高速時鐘,并開啟端口    重映射OSC_IN(PD0) OSC_OUT(PD1)

    //PD0_OSC_IN
    X.GPIO_Pin = GPIO_Pin_0;            //對要使用的端口引腳設(shè)定
    X.GPIO_Mode = GPIO_Mode_Out_PP;     //對要使用的端口引腳模式設(shè)定PP為推挽輸出
    X.GPIO_Speed = GPIO_Speed_50MHz;    //對要使用的端口引腳頻率設(shè)定50MHz
    GPIO_Init(GPIOD, &X);               //初始化GPIOD寄存器
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE );  //對端口D分配APB2高速時鐘,并開啟端口
    
    //PD1_OSC_OUT
    X.GPIO_Pin = GPIO_Pin_1;            //對要使用的端口引腳設(shè)定
    X.GPIO_Mode = GPIO_Mode_Out_PP;     //對要使用的端口引腳模式設(shè)定PP為推挽輸出
    X.GPIO_Speed = GPIO_Speed_50MHz;    //對要使用的端口引腳頻率設(shè)定50MHz
    GPIO_Init(GPIOD, &X);               //初始化GPIOD寄存器

    GPIO_ResetBits(GPIOD, GPIO_Pin_0);      //OSC_IN
    GPIO_ResetBits(GPIOD, GPIO_Pin_1);      //OSC_OUT
        
    GPIO_PinRemapConfig(GPIO_Remap_PD01, ENABLE);           //重映射OSC_IN OSC_OUT

    RCC_DeInit();                       //將外設(shè) RCC寄存器重設(shè)為缺省值 
    RCC_HSICmd(ENABLE);                 //使能或者失能內(nèi)部高速晶振(HSI) 
    while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){}      //HSI 晶振就緒    HSI內(nèi)部晶振 HSE外部晶振
    
    if(1)      //始終執(zhí)行,方便關(guān)閉,內(nèi)部時鐘設(shè)置
    {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);       //使能預(yù)取指緩存
        FLASH_SetLatency(FLASH_Latency_2);          //設(shè)置代碼延時值為2個延時周期 
        RCC_HCLKConfig(RCC_SYSCLK_Div1);            //設(shè)置 AHB 時鐘(HCLK)
        RCC_PCLK1Config(RCC_HCLK_Div2);             //設(shè)置低速 AHB 時鐘(PCLK1)
        RCC_PCLK2Config(RCC_HCLK_Div1);             //設(shè)置高速 AHB 時鐘(PCLK2)
        RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_2);     //設(shè)置 PLL 時鐘源及倍頻系數(shù)
        RCC_PLLCmd(ENABLE);//如果PLL被用于系統(tǒng)時鐘,那么它不能被失能    //使能或者失能 PLL,這個參數(shù)可以取:ENABLE或者DISABLE
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}     //等待指定的 RCC 標(biāo)志位設(shè)置成功 等待PLL初始化成功
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  //設(shè)置系統(tǒng)時鐘(SYSCLK)設(shè)置PLL為系統(tǒng)時鐘源
        while(RCC_GetSYSCLKSource() != 0x08){}      //等待PLL成功用作于系統(tǒng)時鐘的時鐘源
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容