MDK寄存器地址映射分析
在51單片機中:
首先我們看看 51 中是怎么做的。51 單片機開發中經常會引用一個 reg51.h 的頭文件,下面我們看看他是怎么把名字和寄存器聯系起來的:
sfr 也是一種擴充數據類型,點用一個內存單元,值域為 0~255。利用它可以訪問 51 單片
機內部的所有特殊功能寄存器。如用 sfr P1 = 0x90 這一句定義 P1 為 P1 端口在片內的寄存
器。然后我們往地址為 0x80 的寄存器設值的方法是:P0=value;
在STM32中:
在 STM32 中,同樣也可以這樣做,但是 STM32 因為寄存器太多太多,如果以這樣的方式一一列出來,那要好大的篇幅,既不方便開發,也顯得太雜亂無序的感覺。所以 MDK 采用的方式是通過結構體來將寄存器組織在一起。下面我們就講解 MDK 是怎么把結構體和地址對應起來的,為什么我們修改結構體成員變量的值就可以達到操作對應寄存器的值。這些事情都是在stm32f10x.h文件中完成的。我們通過 GPIOA 的幾個寄存器的地址來講解。
(1)寄存器地址映射表
從這個表我們可以看出,GPIOA 的 7 個寄存器都是 32 位的,所以每個寄存器占有 4個地址,一共占用 28 個地址,地址偏移范圍為(000h~01Bh)。這個地址偏移是相對 GPIOA的基地址而言的。GPIOA 的基地址是怎么算出來的呢?因為 GPIO 都是掛載在 APB2 總線之上,所以它的基地址是由 APB2 總線的基地址+GPIOA 在 APB2 總線上的偏移地址決定的。同理依次類推,我們便可以算出 GPIOA 基地址了。下面我們打開 stm32f10x.h 定位到 GPIO_TypeDef 定義處:
然后定義到:
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)GPIOA 是將 GPIOA_BASE 強制轉換為 GPIO_TypeDef 指針,這句話的意思是,GPIOA 指向地址GPIOA_BASE,GPIOA_BASE 存放的數據類型為 GPIO_TypeDef。
然后查看 GPIOA_BASE的宏定義:
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)可知GPIOA 的基地址是 APB2 總線的基地址+GPIOA 在 APB2 總線上的偏移地址
依次類推,可以找到最頂層:
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define PERIPH_BASE ((uint32_t)0x40000000)所以我們便可以算出 GPIOA 的基地址位:
GPIOA_BASE= 0x40000000+0x10000+0x0800=0x40010800(2)GPIOA 的 7 個寄存器的地址如何計算:
GPIOA 的寄存器的地址=GPIOA 基地址+寄存器相對 GPIOA 基地址的偏移值這個偏移值在上面的寄存器地址映像表中可以查到。
(3)結構體里面這些寄存器又是怎么與地址一一對應的:
這里就涉及到結構體的一個特征,那就是結構體存儲的成員他們的地址是連續的。上面講到 GPIOA 是指向GPIO_TypeDef 類型的指針,又由于 GPIO_TypeDef 是結構體,所以自然而然我們就可以算出 GPIOA 指向的結構體成員變量對應地址了。
我們可以把 GPIO_TypeDef 的定義中的成員變量的順序和 GPIOx 寄存器地址映像對比可以發現,他們的順序是一致的,如果不一致,就會導致地址混亂了。這就是為什么固件庫里面:GPIOA->BRR=value;就是設置地址為 0x40010800+0x014(BRR 偏移量)=0x40010814 的寄存器 BRR 的值了。它和 51 里面 P0=value 是設置地址為 0x80 的 P0 寄存器的值是一樣的道理。
總結
以上是生活随笔為你收集整理的MDK寄存器地址映射分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmd ntsd命令
- 下一篇: 33tomcat目录结构