07.09 stm32標準庫對寄存器地址的封裝

stm32標準庫對寄存器地址的封裝

APB1總線掛載外設 及地址

stm32標準庫對寄存器地址的封裝

APB2總線掛載外設及地址

stm32標準庫對寄存器地址的封裝

AHB1掛載外設及地址

stm32標準庫對寄存器地址的封裝

AHB2及AHB3掛載外設及基地址

第一步確定整個外設區域的基地址

#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region

第二步確定不同總線的基地址,因為不同總線的上邊掛載著不同的系統外設

/*!< Peripheral memory map */

#define APB1PERIPH_BASE PERIPH_BASE

#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)

#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)

#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000)

可以發現對應的是對的

第三步我們以AHB1上掛載的GPIO外設的地址封裝為例講解

/*!< AHB1 peripherals */

#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)

#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400)

#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800)

#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)

#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000)

#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400)

#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800)

#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00)

#define GPIOI_BASE (AHB1PERIPH_BASE + 0x2000)

#define GPIOJ_BASE (AHB1PERIPH_BASE + 0x2400)

#define GPIOK_BASE (AHB1PERIPH_BASE + 0x2800)

#define CRC_BASE (AHB1PERIPH_BASE + 0x3000)

#define RCC_BASE (AHB1PERIPH_BASE + 0x3800)

#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x3C00)

#define DMA1_BASE (AHB1PERIPH_BASE + 0x6000)

#define DMA1_Stream0_BASE (DMA1_BASE + 0x010)

#define DMA1_Stream1_BASE (DMA1_BASE + 0x028)

#define DMA1_Stream2_BASE (DMA1_BASE + 0x040)

#define DMA1_Stream3_BASE (DMA1_BASE + 0x058)

#define DMA1_Stream4_BASE (DMA1_BASE + 0x070)

#define DMA1_Stream5_BASE (DMA1_BASE + 0x088)

#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0)

#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8)

#define DMA2_BASE (AHB1PERIPH_BASE + 0x6400)

#define DMA2_Stream0_BASE (DMA2_BASE + 0x010)

#define DMA2_Stream1_BASE (DMA2_BASE + 0x028)

#define DMA2_Stream2_BASE (DMA2_BASE + 0x040)

#define DMA2_Stream3_BASE (DMA2_BASE + 0x058)

#define DMA2_Stream4_BASE (DMA2_BASE + 0x070)

#define DMA2_Stream5_BASE (DMA2_BASE + 0x088)

#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0)

#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8)

#define ETH_BASE (AHB1PERIPH_BASE + 0x8000)

#define ETH_MAC_BASE (ETH_BASE)

#define ETH_MMC_BASE (ETH_BASE + 0x0100)

#define ETH_PTP_BASE (ETH_BASE + 0x0700)

#define ETH_DMA_BASE (ETH_BASE + 0x1000)

#define DMA2D_BASE (AHB1PERIPH_BASE + 0xB000)

可以看出我們已經知道了每個外設的基地址 ,我們有公式

寄存器地址=外設的基地址+外設的偏移地址 利用公式那麼說我們的每個外設內需要操作的寄存器的地址,我們都可以進行訪問了。

第四步 看看庫函數是怎麼幫助我們定義外設的寄存器地址的,是怎麼樣對其進行封裝的?4

#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)

#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)

#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)

#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)

#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)

#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE)

#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE)

#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE)

可以看出以上庫函數神奇的操作是把一堆的32位的無符號的整數 強制轉換成了結構體類型的指針。

並且(GPIO_TypeDef *) 這個指針只能指向GPIO_TypeDef 這個結構體類型

下面我們打開這個結構體

stm32標準庫對寄存器地址的封裝

發現庫函數把我們的GPIO的寄存器類型全都放在了一起 ,因為我們這些具有相同的特徵描述的是同一事物的不同性質,不禁就讓人想到了c語言的結構體,並且C語言的結構體成員變量在我們的sram中存儲的方式是連續的。

第五步看看怎麼用

stm32標準庫對寄存器地址的封裝

這是應用

stm32標準庫對寄存器地址的封裝

這是一個結構體

我們訪問結構體

stm32標準庫對寄存器地址的封裝

stm32標準庫對寄存器地址的封裝

stm32標準庫對寄存器地址的封裝

我們最終訪問到了GPIOA


分享到:


相關文章: