<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          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://www.ex-cimer.com/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)文件。因?yàn)榍度胧絣inux開發(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實(shí)際上等價于 ((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)體封裝寄存器方式訪問寄存器的實(shí)質(zhì)仍然是直接對寄存器所在的物理地址操作??!

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

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



          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();