2019-11-05-STM32時(shí)鐘設(shè)置

了解一下SystemInit()函數(shù)

這個(gè)函數(shù)是我們進(jìn)行系統(tǒng)初始化時(shí)會(huì)使用到的一個(gè)函數(shù)。它出現(xiàn)在main函數(shù)的第一行??梢?jiàn)其重要性。

庫(kù)函數(shù)的工程初始化過(guò)程中調(diào)用的函數(shù)及其順序?yàn)椋簊tartup_stm32f10x_hd.s->SystemInit()->SetSysClock()->SetSysClockTo72()

那么SystemInit()函數(shù)進(jìn)行了什么操作呢?——答案是初始化內(nèi)部Flash以及系統(tǒng)時(shí)鐘。在我們默認(rèn)使用該函數(shù)時(shí)系統(tǒng)時(shí)鐘被定為72MHz。系統(tǒng)時(shí)鐘是整個(gè)單片機(jī)時(shí)鐘的核心,各種外設(shè)的時(shí)鐘都依托這個(gè)系統(tǒng)時(shí)鐘,我們可以通過(guò)一張圖看到系統(tǒng)時(shí)鐘的來(lái)源和去向:

image.png

系統(tǒng)時(shí)鐘的來(lái)源為外部晶振,一個(gè)是頻率為8MHz的橢圓形晶振,還有一個(gè)頻率為12MHz的小圓柱形晶振,還有內(nèi)部的兩個(gè)震蕩源。我們可以看到?jīng)Q定系統(tǒng)時(shí)鐘的幾個(gè)時(shí)鐘都連接到PLL,左半邊是各個(gè)時(shí)鐘源經(jīng)過(guò)各種分頻之后連接到PLL,右邊是各種外設(shè)時(shí)鐘使用不同的分頻比例。其中AHB有1-512等多種分頻方式(2的倍數(shù)),APB1頻率是系統(tǒng)時(shí)鐘的一半,APB2頻率是系統(tǒng)時(shí)鐘。

平時(shí)使用時(shí)只需要了解這個(gè)時(shí)鐘的頻率,我們通常情況下會(huì)直接調(diào)用該函數(shù),將系統(tǒng)時(shí)鐘頻率設(shè)置成72MHz,APB1的頻率為36MHz,需要修改工作頻率的時(shí)候,可以通過(guò)使用HSE和HSI來(lái)配置系統(tǒng)時(shí)鐘,相關(guān)代碼可見(jiàn)野火的書(shū)P143。

32的位帶操作

32有一個(gè)很特別的東西——位帶操作。我們知道在51的使用中,關(guān)于某個(gè)特定端口的輸出輸入我們有時(shí)會(huì)這么寫(xiě):用P0.7專門(mén)指定一個(gè)引腳,輸出高就setb,輸出低就clr。這種使用方法在32里就不通用了,我們?cè)贗O操作那一節(jié)就可以看到,我們想要指定一個(gè)引腳,必須設(shè)置好一個(gè)完整的GPIO的結(jié)構(gòu)體指明引腳號(hào)啊輸入還是輸出啊之類的相關(guān)信息,非常繁瑣。想要更方便操作,可以使用32的位帶操作。

位帶操作可以簡(jiǎn)單理解成擴(kuò)展位或者膨脹

我們知道,單片機(jī)的一切外設(shè)都由在它片內(nèi)的某個(gè)特殊寄存器設(shè)置及控制,想要控制某個(gè)外設(shè)只需要將相關(guān)的寄存器配置好就可以了。32提供了大小為1M的外設(shè)位帶區(qū),包含了片上外設(shè)的全部寄存器,全部寄存器都可以通過(guò)訪問(wèn)位帶別名區(qū)的方式來(lái)達(dá)到訪問(wèn)原始寄存器的效果(膨脹后映射等效直接連接,大大降低代碼的繁瑣程度)。

通過(guò)這一原理我們可以將“位帶地址+位序號(hào)”轉(zhuǎn)換成別名地址定義成一個(gè)宏。

// 把一個(gè)地址轉(zhuǎn)換成一個(gè)指針 #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

// 把位帶別名區(qū)地址轉(zhuǎn)換成指針 #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

GPIO位帶操作,實(shí)現(xiàn)兩個(gè)寄存器的地址映射后,

1 // GPIO ODR 和 IDR 寄存器地址映射 2 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C 3 #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C 4 #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C 5 #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C 6 #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C 7 #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C 8 #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C 9 10 #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 11 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 12 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 13 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 14 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 15 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 16 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08

就可以通過(guò)位操作的方法來(lái)控制GPIO的輸入和輸出了,宏參數(shù)n表示某個(gè)IO端口。

在通過(guò)宏定義置位函數(shù),可以將輸入輸出變成更加簡(jiǎn)單易懂的寫(xiě)法。

1 // 單獨(dú)操作 GPIO 的某一個(gè)IO 口,n(0,1,2...16),n 表示具體是哪一個(gè)IO 口 2 #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //輸出 3 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //輸入 4 5 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //輸出 6 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //輸入 7 8 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //輸出 9 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //輸入 10 11 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //輸出 12 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //輸入 13 14 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //輸出 15 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //輸入 16 17 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //輸出 18 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //輸入 19 20 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //輸出 21 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //輸入

位帶操作是一個(gè)很有意義的操作,它大大降低了代碼編寫(xiě)的難度,使得原先冗長(zhǎng)的代碼塊可以用更加簡(jiǎn)單易懂的方式替代,使用方法也很簡(jiǎn)單,在寫(xiě)好頭文件后添加即可,頭文件有現(xiàn)成的代碼集我們這里可以直接用,之后的代碼可能都會(huì)用位帶操作來(lái)減少工作量。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 支持了位帶操作后,可以使用普通的加載/存儲(chǔ)指令來(lái)對(duì)單一的比特進(jìn)行讀寫(xiě)。在 CM3 中,有兩個(gè)區(qū)中實(shí)現(xiàn)了位帶。其中一...
    醞錦閱讀 747評(píng)論 0 0
  • 此文用于記錄學(xué)習(xí)STM32中所學(xué)習(xí)或者鞏固的知識(shí),主要圍繞但并不局限于STM32。 本次學(xué)習(xí)并非為了深入了解使用S...
    yhhk閱讀 2,278評(píng)論 0 11
  • 計(jì)算機(jī)系統(tǒng)漫游 代碼從文本到可執(zhí)行文件的過(guò)程(c語(yǔ)言示例):預(yù)處理階段,處理 #inlcude , #defin...
    willdimagine閱讀 3,835評(píng)論 0 5
  • 其實(shí)這篇文章主要是介紹自己為其寫(xiě)的GPIO庫(kù),自己借鑒了原子寫(xiě)的STM32,野火寫(xiě)的K60,還有LPC官方庫(kù),然后...
    楊奉武閱讀 1,019評(píng)論 0 0
  • 敬愛(ài)的李老師,智慧的班主任,親愛(ài)的躍友們: 大家好!我是來(lái)自臨沂安地地板的黃從偉。 今天是我的日精...
    黃從偉閱讀 143評(píng)論 0 0

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