分享

stm32标准库对寄存器地址的封装

 岐岐feng 2018-07-09

stm32标准库对寄存器地址的封装

APB1总线挂载外设 及地址

stm32标准库对寄存器地址的封装

APB2总线挂载外设及地址

stm32标准库对寄存器地址的封装

AHB1挂载外设及地址

stm32标准库对寄存器地址的封装

AHB2及AHB3挂载外设及基地址

第一步确定整个外设区域的基地址

#define PERIPH_BASE ((uint32_t)0x40000000) /*!< peripheral="" base="" address="" in="" the="" alias="">

第二步确定不同总线的基地址,因为不同总线的上边挂载着不同的系统外设

/*!< 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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多