新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 寄存器物理地址映射到結(jié)構(gòu)體封裝的寄存器的過程

寄存器物理地址映射到結(jié)構(gòu)體封裝的寄存器的過程

作者: 時間:2016-11-26 來源:網(wǎng)絡(luò) 收藏
一、 STM32頭文件中 結(jié)構(gòu)體封裝寄存器的方式

typedef struct
{
vu32 CR;
vu32 CFGR;
vu32 CIR;
vu32 APB2RSTR;
vu32 APB1RSTR;
vu32 AHBENR;
vu32 APB2ENR;
vu32 APB1ENR;
vu32 BDCR;
vu32 CSR;
} RCC_TypeDef;

本文引用地址:http://butianyuan.cn/article/201611/321901.htm

#define PERIPH_BASE((u32)0x40000000)

#define AHBPERIPH_BASE(PERIPH_BASE + 0x20000)

#define RCC_BASE(AHBPERIPH_BASE + 0x1000)

#define RCC((RCC_TypeDef *) RCC_BASE)

在頭文件中這樣定義后,就可以在程序中以

RCC->CR|=0x00010000;來直接操作某一寄存器了。

二、對這一方式的分析與總結(jié)也就是關(guān)于單片機(jī)寄存器封裝問題:

最近在學(xué)習(xí)嵌入式linux過程中,看到 DM368寄存器地址映射到結(jié)構(gòu)體封裝的寄存器的系統(tǒng)文件。因為嵌入式linux開發(fā)沒有像單片機(jī)一樣的編譯軟件,系統(tǒng)文件不是編譯軟件本身自帶的。嵌入式編程需要自己找到需要用的模塊的頭文件,來操作相應(yīng)的寄存器,編寫相應(yīng)的驅(qū)動。于是乎,在看別人的程序時,迷迷糊糊的就從主程序看到了驅(qū)動程序,又看到了底層操作寄存器的程。為了徹底搞懂嵌入式程序,終于注意到了以前單片機(jī)編程時沒怎么注意過的結(jié)構(gòu)體封裝寄存器,映射物理地址。看了好半天也沒有看明白 宏定義是如何映射地址的,關(guān)鍵是這樣語法的一句話:

#define RCC((RCC_TypeDef *) RCC_BASE)

RCC_BASE的定義是 #define RCC_BASE(AHBPERIPH_BASE + 0x1000)  是物理地址經(jīng)過代換(AHBPERIPH_BASE + 0x1000)=0x40021000

經(jīng)過思索和討教,對這種封裝寄存器的來龍去脈終于恍然大悟。

首先,碰到#define一定要牢記C語言老師的教誨--‘僅僅是替換’。因此在使用結(jié)構(gòu)體封裝的寄存器來操作寄存器時,如RCC->CR =0x00實際上等價于 ((RCC_TypeDef *) RCC_BASE)->CR=0x00。 進(jìn)一步,將RCC_BASE替換為 (AHBPERIPH_BASE + 0x1000) ,這里AHBPERIPH_BASE是地址,也是常量。于是整句話就被還原為 ((RCC_TypeDef *)0x40021000)->CR=0x00 。

也就是 先對地址常量 (AHBPERIPH_BASE + 0x1000) 進(jìn)行強(qiáng)制類型轉(zhuǎn)換為 (RCC_TypeDef )類型的結(jié)構(gòu)體指針。由結(jié)構(gòu)體指針的相關(guān)知識可知,將一個地址指向結(jié)構(gòu)體,那么該地址后面的地址會自動按結(jié)構(gòu)體中定義的結(jié)構(gòu)體成員來劃分。所以 ,作為該結(jié)構(gòu)體的第一個成員CR,((RCC_TypeDef *)0x40021000)->CR也就是代表 (AHBPERIPH_BASE + 0x1000) 。 以此類推 ,,((RCC_TypeDef *)0x40021000)->CFGR 則代表

RCC_BASE(0x40021000)的下一段地址 即0x40021004 (手冊中 RCC_CFGR寄存器的地址)。

可以看到這種結(jié)構(gòu)體封裝寄存器方式訪問寄存器的實質(zhì)仍然是直接對寄存器所在的物理地址操作?。?/p>

至于為什么用這種方式來封裝結(jié)構(gòu)體。可以參考51單片機(jī)寄存器的定義方式。keil中51單片機(jī)每一個寄存器是直接給出對應(yīng)的存儲器地址,而沒有用這種結(jié)構(gòu)體方式封裝。因為操作寄存器的實質(zhì)永遠(yuǎn)都是對寄存器所在的地址操作。 STM32 中寄存器很多,如果像51一樣 對每一個寄存器地址給定一個寄存器名稱,太繁雜而且沒有直觀性。結(jié)構(gòu)體封裝,可以直觀的看出每個模塊中有哪些寄存器,方便編程。

圖:keil中51寄存器的定義方式



評論


技術(shù)專區(qū)

關(guān)閉