STM32儲存器對映和暫存器對映

2022-07-15 05:48:12 字數 2626 閱讀 6002

對於cortex-m3來講,有一塊4g大小的儲存器空間。儲存器對映指的是晶元廠商為這個空間分配位址的操作。這4g空間被均勻地劃分為8個大小為512mb的儲存塊(block),並且每個塊都各具特色。下面主要介紹block1~block2。

flash:起始位址為0x0800_0000,存放使用者程式和掉電儲存資料。flash容量從16k到512k不等,以stm32f10x8系列為例,8代表flash容量為64k,所以結束位址就為0x0801_ffff。

option bytes:選項位元組,可以配置讀寫保護、看門狗等。

這裡簡單說一下位址分配。整塊4g儲存器開始位址標為0x0000_0000,結束位址為0xffff_ffff,位址表示採用了十六進製制,一共8*4=32bit,而2^32剛好就是4g。儲存器的基本單元是乙個位元組,每個位址都對應這樣乙個單元,因此用32位位址來表示,其容量剛好就是4gb。同理,根據block0的起止位址,也可以計算得到其容量為512mb。

block1的位址範圍為0x2000_0000~0x3fff_ffff。其中0x2000_0000~0x2000_ffff被劃為sram,主要是用於程式執行的堆疊開銷。

block2的位址範圍為0x4000_0000~0x5fff_ffff。這塊空間被充分用作外設暫存器。根據匯流排不同,將外設分為三大塊,第一塊是apb1匯流排外設,起始位址為0x4000_0000;第二塊是apb2匯流排外設,起始位址為0x4001_0000;最後一塊為ahb匯流排外設,起始位址為0x4001_8000。

暫存器對映主要針對於block2。這種對映不同於儲存器對映的分配位址操作,而是在程式中對具有特定功能的記憶體單元進行命名的過程,每個記憶體單元都是四個位元組,稱作暫存器。例如gpioa外設有個暫存器位址範圍為0x4001_0800~0x4001_0803,該暫存器是用來配置gpioa部分埠工作模式的,因此被對映為gpioa_crl。由此可知,這種對映方便了對暫存器的訪問操作,因為如果每次訪問暫存器都要查位址範圍的話是很痛苦的。

如何實現這種對映的呢?以gpioa_crl為例,其對映位址 = 外設總基位址(塊基位址)+ 匯流排相對於外設總基位址的偏移 + 具體外設基位址相對於匯流排基位址的偏移 + 暫存器相對於具體外設基位址的偏移。

外設總基位址恰好就是block2的起始位址0x4000_0000;

gpio屬於apb2匯流排外設,因此查閱晶元手冊如下圖所示,我們其實直接可以得到apb2起始位址和gpioa的起始位址,但是程式中一般不這麼做,而是以偏移量來表示層次關係。從圖中可計算到匯流排相對於外設總基位址的偏移為0x1_0000,gpioa相對於apb2基位址的偏移為0x800。

再查閱gpio的暫存器組,如下圖所示。可以得到crl暫存器相對於gpio基位址偏移為0x00。綜上gpioa_crl的基位址為:0x4000_0000+0x1_0000+0x800+0x00。

stm32韌體庫中,有個頭檔案叫stm32f10x.h,其中就定義了暫存器的對映,部分**如下:

#define periph_base           ((uint32_t)0x40000000)

#define apb1periph_base       periph_base

#define apb2periph_base (periph_base + 0x10000)

#define ahbperiph_base (periph_base + 0x20000)

#define gpioa_base            (apb2periph_base + 0x0800)

#define gpiob_base (apb2periph_base + 0x0c00)

#define gpioc_base (apb2periph_base + 0x1000)

#define gpiod_base (apb2periph_base + 0x1400)

#define gpioe_base (apb2periph_base + 0x1800)

#define gpiof_base (apb2periph_base + 0x1c00)

#define gpiog_base (apb2periph_base + 0x2000)

定義gpio外設結構體,因為結構體成員在記憶體中是連續的,這種形式與暫存器組非常類似,所以用結構體能夠很好的管理暫存器:

typedef struct

gpio_typedef;

#define gpioa               ((gpio_typedef *) gpioa_base)
訪問暫存器方式的對比,對映訪問明顯更為直觀:

//

直接的位址訪問

*(unsigned int *)(0x4001_0800)|= 0x0001;//

對映訪問

gpioa->crl |= 0x0001;

STM32暫存器對映

1.對映即將記憶體的某段位址與某一暫存器對應,微控制器對函式的操作底層是操作暫存器,而暫存器最終是操作記憶體上對應的單元,2.各個暫存器對應的位址都是在st定義的起始位址上層層偏移得到 3.想要實現某功能可直接對此段記憶體寫進相應的值,即可賦予某一功能 4.stm32底層實際是先定義出外設基位址,然...

筆記 STM32暫存器位址對映

例如 struct student p p可以指向struct student 型別的變數或陣列元素 例題 main stu1 pstu stu1 讀取結構體成員的值 printf s的學號是 d,年齡是 d,在 c組,今年的成績是 1f!n pstu name,pstu num,pstu age,...

STM32蜂鳴器 暫存器

這次實驗犯了個笑話,竟然在巨集定義後面加分號.就像這樣 define 大家千萬不要學我,結果報錯expected expression,還苦惱半天,想為啥操作不了暫存器了?我真愚蠢!剛開始我也不會寫這些東西,其實摸清套路就好,rcc時鐘使能 gpio初始化 相關暫存器初始化 延時函式 串列埠等初始化...