<center id="qkqgy"><optgroup id="qkqgy"></optgroup></center>
  • <menu id="qkqgy"></menu>
    <nav id="qkqgy"></nav>
    <xmp id="qkqgy"><nav id="qkqgy"></nav>
  • <xmp id="qkqgy"><menu id="qkqgy"></menu>
    <menu id="qkqgy"><menu id="qkqgy"></menu></menu>
    <tt id="qkqgy"><tt id="qkqgy"></tt></tt>

  • ? ? ? ? 1.時鐘樹

    ????????

    STM32的時鐘樹大致可分為3部分:

    * ?陶瓷晶振輸入,進入預分頻器
    * 預分頻器輸出信號給到PLL倍頻器
    * 最終AHB橋總線速度,以及各總線的速度
    ? ? ? ?
    晶振信號輸入到芯片后有兩條支路可以走,第一條是直接以原始頻率不經過PLL倍頻器,直接作為系統時鐘(SYSCLK)。第二條是從預分頻器流入,隨后將輸出信號輸入PLL倍頻器,
    最終得到X*HSE的SYSCLK(X為倍頻倍率)。假如輸入為8MHz,那么X為9時才能達到最大頻率72MHz。

    ? ? ? ? 1.1?PLLXTPRE? ?

    ????????PLLXTPRE(預分頻器)的作用是為了將大于16Mhz的信號進行"/2"操作,因為在STM32中晶振的輸入頻率最大不超過16MHz
    ,所以當大于16MHz時需要進行分頻操作。在市面上可以有些最小系統板用的是24MHz晶振,這是因為他們為了從成本考慮,24MHz的晶振比常用8MHz要便宜。當使用24MHz時,經過的路徑是這樣的,所以信號進過預分頻器最終輸出頻率是
    12MHz。

    ?

    ????????8MHz時路徑是這樣的,所以信號進過預分頻器最終輸出頻率是8MHz。

    ? ? ? ? 1.2?PLLSRC? ? ? ? ?

    ????????PLLSRC
    的作用是選擇系統時鐘源,從圖中可以看到有兩條輸入支路,一條是HSI經過"/2"的預分頻后信號輸入PLLSRC,一條是HSE經過預分頻后輸出的信號。

    ????????

    ? ? ? ? 1.3?PLLMUL? ? ? ?

    ????????PLLMUL?的作用是將PLLSRC的輸出信號進行x倍的倍頻,x可以為1-16。

    ? ? ? ? 經過被倍頻的信號仍未作為SYSCLK,它還需要進過一個選擇器,該選擇器從圖中可以看到有多條輸入支路

    ? ? ? ? 一條是HSI(8MHz)原始信號直接輸入作為SYSCLK,HSI擁有一個很大的缺陷,那就是無論進過如何校準信號質量依然很差。

    ? ? ? ? 一條是HSE原始信號直接輸入作為SYSCLK,HSE信號一般都為陶瓷晶振信號。

    ? ? ? ? 一條是PLLMUL倍頻后信號作為SYSCLK。

    ? ? ? ?
    除卻上文所說的三條輸入支路,還有兩個旁路,一個SW,一個是CSS。其中前者的作用是開關,意義就在于選擇SYSCLK的最終信號源。后者的作用是時鐘安全系統,作用是當HSE時鐘源出現問題后,強制將SYSCLK的信號源切換為HSI。

    ? ? ? ? 1.4 總線橋? ? ? ?

    ????????

    ? ? ? ?
    只要理解了SYSCLK的時鐘頻率是如何產生的,那么關于總線橋的頻率就不難理解了。STM32F103的常用頻率是72MHz,所以這里就以72MHz為例。在得到SYSCLK信號后會優先經過AHB橋進行預分頻,此處默認為1,即不分頻,隨后流入APB橋、滴答定時器(SYSTICK)以及DMA總線。APB橋又分為APB1和APB2,同時還可以進行一個預分頻。APB1在32中的定義是
    低速總線橋,從圖中可以看到它的最大支持頻率是36MHz,所以在流入APB1時需要進行一個"/2"
    的預分頻。在APB1橋下控制著TIM2,3,4子對象。APB2在32中的定義是高速總線橋,從圖中可以看到它的最大支持頻率是72MHz,所以在流入APB2時不需要進行預分頻,即分頻系數為1。在其下面擁有TIM1以及ADC子對象,也就是這兩者的最大速度為72MHz。

    ? ? ? ? 除卻各總線橋預分頻器,圖中還有多個與門,與門的作用就是是否輸出該總線的信號。

    ? ? ? ? 2. 系統時鐘配置

    ????????2.1 直接上代碼
    void SystemInit (void) { /* 啟動HSI時鐘 */ RCC->CR |= (uint32_t)0x00000001; /* 復位
    SW, AHB, APB1, APB2, ADCPRE and MCO bits */ RCC->CFGR &= (uint32_t)0xF8FF0000;
    /* 復位 HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* 復位
    HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* 復位 PLLSRC, PLLXTPRE, PLLMUL
    and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (uint32_t)0xFF80FFFF; /* 清除所有時鐘中斷標志位
    */ RCC->CIR = 0x009F0000; /* 配置系統時鐘頻率、AHB、APB2和APB1預分頻器 */ /* 配置閃存延遲周期并啟用預取緩沖區
    */ SetSysClockTo72(); } static void SetSysClockTo72(void) { uint32_t
    StartUpCounter = 0, HSEStatus = 0; /* 配置 SYSCLK, HCLK, PCLK2 and PCLK1
    ---------------------------*/ /* 使能 HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
    /* 等待HSE晶振就緒 */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY; //讀CR寄存器中就緒位
    StartUpCounter++; //超時計數 } while((HSEStatus == 0) && (StartUpCounter !=
    0x0500)); //等待超時,以及標志位置位 if ((RCC->CR & RCC_CR_HSERDY) != RESET)
    //此處語句的作用是檢測HSE是否就緒 { HSEStatus = (uint32_t)0x01; //就緒標志 1 } else { HSEStatus =
    (uint32_t)0x00; //不就緒標志 0 } if (HSEStatus == (uint32_t)0x01) //HSE就緒 { /*
    SYSCLK預分頻系數為1,即不分頻 */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /*
    APB2預分頻系數為1,即不分頻 =SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; /*
    APB1預分頻系數為2,即 APB2 = SYSCLK/2 */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; /*
    初始化HSE預分頻器,時鐘源選擇器,PLL倍頻器 */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC
    | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); /*時鐘源選擇為 HSE,進行9倍頻 SYSCLK = HSE*9 =
    8MHz*9 = 72MHz */ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE |
    RCC_CFGR_PLLMULL9); /* 使能PLL倍頻器 */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is
    ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) //等待PLL倍頻器就緒 { } /*
    復位時鐘源選擇,并將時鐘源選擇為PLL */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* 等待時鐘源選擇完成置位 */ while ((RCC->CFGR &
    (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } }
    ? ? ? ? 2.2 代碼解析

    ????????RCC->CR |= (uint32_t)0x00000001

    ? ? ? ? ?此處代碼的作用是啟動芯片內置HSI時鐘源,確保芯片能正常運行,以及觸發CSS時鐘安全警報后能正常切換。

    ????????RCC->CFGR &= (uint32_t)0xF8FF0000

    ? ? ? ? 將RCC->CFGR寄存器內的值復位為初始狀態,即復位

    SW:系統時鐘切換 -> HSI作為系統時鐘
    HPRE:?AHB 預分頻 -> SYSCLK不分頻 PPRE1:低速 APB1預分頻 ->?HCLK 不分頻 PPRE2:高速 APB2預分頻 ->
    HCLK不分頻 ADCPRE:ADC 預分頻 -> PCLK2 2分頻后作為 ADC 時鐘 MCO 微控制器時鐘輸出:沒有時鐘輸出
    ????????RCC->CR &= (uint32_t)0xFEF6FFFF

    ???????將 HSEON, CSSON and PLLON 復位為初始狀態,即
    HSEON :外部高速時鐘使能 -> HSE振蕩器關閉 CSSON:時鐘安全系統使能 -> 時鐘監測器關閉 PLLON:PLL 使能 -> PLL關閉
    ????????RCC->CR &= (uint32_t)0xFFFBFFFF;

    ????????復位 HSEBYP 狀態。為什么這里是復位不與上面的復位一次進行呢,是因為在官方文檔中寫明了,在復位HSEBYP前需要先只有在外部1-
    25MHz振蕩器關閉的情況下,該位才可以寫入。在上文我們將HSE時鐘關閉了。此處復位是為了告訴芯片外部1-25MHz振蕩器沒有旁路。
    所謂HSE旁路模式,是指無需陶瓷晶振作為系統時鐘,直接從外界導入時鐘信號。猶如芯片內部的驅動組件被旁路了。

    ????????RCC->CFGR &= (uint32_t)0xFF80FFFF

    ? ? ? ??復位 PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE 狀態
    PLLSRC:PLL輸入時鐘源 ->?HSI 時鐘 2 分頻后作為 PLL 輸入時鐘 PLLXTPRE: HSE 分頻器作為 PLL輸入 ->?HSE
    不分頻 PLLMUL: PLL倍頻系數 ->?PLL 2 倍頻輸出 USBPRE: USB預分頻 ->?PLL 時鐘 1.5 倍分頻作為 USB 時鐘
    ? ? ? ? 此處的復位配置為什么不能與?RCC->CFGR &= (uint32_t)0xF8FF0000?
    一起寫入寄存器呢,同樣的此處復位的值在寫入對應寄存器之前必須要先關閉PLL倍頻器,在復位CR寄存器是我們才將PLL關閉。

    ????????RCC->CIR = 0x009F0000

    ????????此處語句的作用就單純的是復位所有中斷標志位。從寄存器名字也可以體現出"IR",全英文不就是interrupt
    。為什么要清除中斷標志位,是因為在RCC系統時鐘初始化時都會產生大量的中斷,例如
    HSE就緒就會將對應標志位置1,PLL就緒也同樣,想要清楚就緒標志位,就只能通過該寄存器清除。

    ????????RCC->CR |= ((uint32_t)RCC_CR_HSEON)

    ????????使能HSE外部時鐘源,這里的使能作用就跟配置GPIO一樣,在配置每一個外設時應當先將其使能。

    ??do

    ? {

    ? ? HSEStatus = RCC->CR & RCC_CR_HSERDY; ? ?//讀CR寄存器中就緒位

    ? ? StartUpCounter++; ? ? ? ? ? ? ? ? ? ? ? //超時計數

    ? } while((HSEStatus == 0) && (StartUpCounter != 0x0500)); ? ? //等待超時,以及標志位置位

    ????????此處代碼的作用就是等待HSE就緒,?StartUpCounter++這里能夠完成自增的原因就是最前面?RCC->CR |=
    (uint32_t)0x00000001?
    使能了HSI時鐘,保證了系統能正常運作,如果前面沒有使能HSI則此處不能完成自增操作。如果遲遲都等不到HSE就緒,那么系統就會以HSI時鐘作為SYSCLK運作。

    ????????RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1

    ? ? ? ? 此處就是配置AHB橋預分頻器,此處不分頻

    ????????RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1

    ????????此處就是配置APB2橋預分頻器,此處不分頻

    ????????RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2

    ????????
    此處就是配置APB1橋預分頻器,此處2分頻,在官方文檔的時鐘樹中標明了該APB1總線最高只支持到36MHZ,而我們的AHB橋有72MHz,所以要達到官方限制需進行2分頻。

    ????????

    ????????RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC |
    RCC_CFGR_PLLXTPRE |?RCC_CFGR_PLLMULL))

    ? ? ? ? 此處語句初始化PLL時鐘源選擇器,HSE預分頻器,PLL倍頻器

    PLLSRC:PLL輸入時鐘源 ->?HSI時鐘2分頻后作為PLL輸入時鐘

    PLLXTPRE:HSE分頻器作為PLL輸入 -> HSE不分頻

    PLLMUL:PLL倍頻系數 ->?PLL 2倍頻輸出

    ????????RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9)?

    ? ? ? ? 此處語句將時鐘源選擇為 HSE,進行9倍頻 SYSCLK = HSE*9 = 8MHz*9 = 72MHz

    ????????RCC->CR |= RCC_CR_PLLON

    ? ? ? ??使能PLL倍頻器。

    ????????RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW))

    ????????RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL

    ????????此處兩個語句是為了先復位系統時鐘源并將系統時鐘源選擇為PLL。

    ? ? ? ? 剩下的兩個 while() 都是為了檢測對應配置是否配置完成,如果配置完成硬件會將對應為置1。

    ?

    技術
    下載桌面版
    GitHub
    百度網盤(提取碼:draw)
    Gitee
    云服務器優惠
    阿里云優惠券
    騰訊云優惠券
    華為云優惠券
    站點信息
    問題反饋
    郵箱:ixiaoyang8@qq.com
    QQ群:766591547
    關注微信
    巨胸美乳无码人妻视频