栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

寄存器地址名映射

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

寄存器地址名映射

寄存器地址名映射
  • 描述
  • 映射原理
  • 其他单元
  • 总结

描述

在STM32中有很多功能单元,总线以及各种外设还有很多的寄存器,每一类功能单元,总线,各个外设以及寄存器都有一个地址,它们的地址是由STM32的硬件电路决定的,我们如果在每次使用都使用它的地址,这样就会太过复杂,所以我们把它们的地址映射成一个寄存器地址名,这样在使用起来就会方便很多。

映射原理

以外设为例:

首先来看下STM32的总线结构:

我们以GPIO为例,来找一下它所在的位置。

  1. 我们首先找到的就是矩阵总线。这是STM32的生命线,各种外设以及各种功能单元与CPU的联系几乎都需要通过矩阵总线。
  2. 再往下我们又找到了AHB总线。它是挂靠在矩阵总线上的,当然,AHB总线上也又很多的外设。
  3. 再往下我们找到了APB2总线。这条总线上挂载的都是一些高速外设。
  4. 最后我们找的了GPIO。GPIO都挂靠在APB2总线上。


以图形的方式表示,GPIO的位置就是这样的。
在STM官网提供的标准库函数中,已经将各个外设全部映像好,接下来本喵给大家介绍一下。

  1. 外设基地址:
#define PERIPH_BASE           ((uint32_t)0x40000000)

PERIPH_BASE代表的就是外设基地址,各种外设最终都是在这基地址的基础上加一些偏移量得出来的,其实质是地址0x40000000。

  1. 总线外设基地址
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

APB2PERIPH_BASE代表APB2总线外设基地址,它的实质是在外设基地址的基础上增加一个偏移量后得到的一个新地址,比如APB2的地址就是0x4000000000+0x10000=0x4000010000。

  1. 寄存器组基地址
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)

这里仅列举7组GPIO的映射,其他外设的映射也是如此。GPIO_XBASE就是代表该组GPIO的基地址,其实质就是APB2总线外设基地址加一个偏移量后得到的地址。

  1. GPIO中各个寄存器的地址


通过手册查找到GPIO中各个寄存器的偏移值,加到GPIO基地址上就是各个寄存器的具体地址。
如果这样查找的话,在每次使用的时候都需要进行相应的计算,为了方便使用,对寄存器组进行了如下的处理:
以GPIOA为例:

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

将每组GPIO中的7个寄存器创建成一个结构体。

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

然后将GPIOA的基地址强制类型转化成一个结构体指针变量,这样一来在使用GPIOA的每个寄存器时候只需要直接访问该结构体中的成员就可以。
例如使用GPIOA_CRL寄存器:

GPIOA->CRL=0x00000000;

不用每次都在GPIOA基地址的基础上加一个偏移值,这样一来就方便了很多。
对于寄存器组中的其他寄存器也是这样来使用的。

其他单元
#define FLASH_BASE            ((uint32_t)0x08000000) 
#define SRAM_BASE             ((uint32_t)0x20000000) 
#define SRAM_BB_BASE          ((uint32_t)0x22000000)
#define PERIPH_BB_BASE        ((uint32_t)0x42000000) 
#define FSMC_R_BASE           ((uint32_t)0xA0000000)

这是其他功能单元的基地址,例如FLASH,SRAM等等。

#define APB1PERIPH_BASE       PERIPH_BASE
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)

这是其他总线外设基地址,APB1PERIPH_BASE,AHBPERIPH_BASE分别代表APB1外设总线的基地址,AHB外设总线的基地址。

#define TIM2_BASE             (APB1PERIPH_BASE + 0x0000)
#define TIM3_BASE             (APB1PERIPH_BASE + 0x0400)
#define TIM4_BASE             (APB1PERIPH_BASE + 0x0800)
#define TIM5_BASE             (APB1PERIPH_BASE + 0x0C00)
#define TIM6_BASE             (APB1PERIPH_BASE + 0x1000)
#define TIM7_BASE             (APB1PERIPH_BASE + 0x1400)
#define TIM12_BASE            (APB1PERIPH_BASE + 0x1800)
#define TIM13_BASE            (APB1PERIPH_BASE + 0x1C00)
#define TIM14_BASE            (APB1PERIPH_BASE + 0x2000)
#define RTC_BASE              (APB1PERIPH_BASE + 0x2800)
#define WWDG_BASE             (APB1PERIPH_BASE + 0x2C00)
#define IWDG_BASE             (APB1PERIPH_BASE + 0x3000)
#define SPI2_BASE             (APB1PERIPH_BASE + 0x3800)
#define SPI3_BASE             (APB1PERIPH_BASE + 0x3C00)
#define USART2_BASE           (APB1PERIPH_BASE + 0x4400)
#define USART3_BASE           (APB1PERIPH_BASE + 0x4800)
#define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)
#define UART5_BASE            (APB1PERIPH_BASE + 0x5000)

这是其他寄存器组的基地址,只是列举了一部分,还有很多没有列举,但都是这样的映射方法。

总结

寄存器地址名的映射就是为了使用各种寄存器的时候更加方便,每一个寄存器名字的实质其实就是一个地址,操作寄存器名比操作地址更加方便直观。
如果以上内容对您有帮助,麻烦给本喵一键三连支持一下。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/928028.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号