寄存器基本概念
寄存器是中央处理器(CPU)内的组成部件,是有限存贮容量的高速存贮部件。它们就像一些临时的小仓库,用来暂存指令、数据和地址等信息,以供CPU快速访问和处理。
在STM32F1系列芯片中,除了CPU内部的通用寄存器、程序计数器等,还有大量的外设寄存器。这些外设寄存器用于控制和配置芯片上的各种外设模块,如GPIO(通用输入输出)、USART(通用同步异步收发器)、ADC(模拟到数字转换器)等。通过读写这些外设寄存器,开发人员可以设置外设的工作模式、读取外设的状态信息,从而实现对外部设备的控制和数据交互。
寄存器映射
寄存器是特殊的存储器,给寄存器地址命名的过程,就叫作寄存器映射。
例如:门牌号 1208 -- 老李家,门牌号 1209 -- 老王家
寄存器地址:0x4001080C -- 寄存器名字:GPIOx_ODA
如何进行外设地址映射?
总线基地址+外设相对于总结基地址偏移量+寄存器相对于外设基地址偏移量
例如:有个小区叫追西西,里面分成三个区:A 区、B 区、C 区,每区有 10 栋楼,每栋楼有 20 户人家。
相应每户人家门牌号类似于:A 区 5 栋 1209 户。
总线基地址:
外设 GPIO 基地址:
GPIOA 寄存器地址:
源码分析
我们以GPIOB为例,分析他在源码中的定义:
#define LED_GPIO GPIOB
#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x00000C00UL)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
#define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */
从代码中可以看出,源码中定义的GPIOB也是将其映射到了内存中,通过PERIPH_BASE总线基地址+偏移量得到APB2的基地址,在APB2的基地址+偏移量得到GPIOB的基地址
通过GPIO_TypeDef结构体定义了GPIOB口,结构体中包含了GPIO的通用寄存器,为了简化寄存器的数量,将同一类型的外设设置通用的寄存器,并以结构体的形式进行定义,方便操作与管理。GPIO通用寄存器结构体定义如下:
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;
同样的其他外设也有对应的寄存器结构体,比如:
/**
* @brief Serial Peripheral Interface
*/
typedef struct
{
__IO uint32_t CR1;
__IO uint32_t CR2;
__IO uint32_t SR;
__IO uint32_t DR;
__IO uint32_t CRCPR;
__IO uint32_t RXCRCR;
__IO uint32_t TXCRCR;
__IO uint32_t I2SCFGR;
} SPI_TypeDef;
/**
* @brief TIM Timers
*/
typedef struct
{
__IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
__IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
__IO uint32_t SMCR; /*!< TIM slave Mode Control register, Address offset: 0x08 */
__IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
__IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
__IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
__IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
__IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
__IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
__IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */
__IO uint32_t PSC; /*!< TIM prescaler register, Address offset: 0x28 */
__IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */
__IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */
__IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */
__IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */
__IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */
__IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */
__IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */
__IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */
__IO uint32_t DMAR; /*!< TIM DMA address for full transfer register, Address offset: 0x4C */
__IO uint32_t OR; /*!< TIM option register, Address offset: 0x50 */
}TIM_TypeDef;
/**
* @brief Universal Synchronous Asynchronous Receiver Transmitter
*/
typedef struct
{
__IO uint32_t SR; /*!< USART Status register, Address offset: 0x00 */
__IO uint32_t DR; /*!< USART Data register, Address offset: 0x04 */
__IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */
__IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x0C */
__IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x10 */
__IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x14 */
__IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */
} USART_TypeDef;
/**
* @brief Universal Serial Bus Full Speed Device
*/
typedef struct
{
__IO uint16_t EP0R; /*!< USB Endpoint 0 register, Address offset: 0x00 */
__IO uint16_t RESERVED0; /*!< Reserved */
__IO uint16_t EP1R; /*!< USB Endpoint 1 register, Address offset: 0x04 */
__IO uint16_t RESERVED1; /*!< Reserved */
__IO uint16_t EP2R; /*!< USB Endpoint 2 register, Address offset: 0x08 */
__IO uint16_t RESERVED2; /*!< Reserved */
__IO uint16_t EP3R; /*!< USB Endpoint 3 register, Address offset: 0x0C */
__IO uint16_t RESERVED3; /*!< Reserved */
__IO uint16_t EP4R; /*!< USB Endpoint 4 register, Address offset: 0x10 */
__IO uint16_t RESERVED4; /*!< Reserved */
__IO uint16_t EP5R; /*!< USB Endpoint 5 register, Address offset: 0x14 */
__IO uint16_t RESERVED5; /*!< Reserved */
__IO uint16_t EP6R; /*!< USB Endpoint 6 register, Address offset: 0x18 */
__IO uint16_t RESERVED6; /*!< Reserved */
__IO uint16_t EP7R; /*!< USB Endpoint 7 register, Address offset: 0x1C */
__IO uint16_t RESERVED7[17]; /*!< Reserved */
__IO uint16_t CNTR; /*!< Control register, Address offset: 0x40 */
__IO uint16_t RESERVED8; /*!< Reserved */
__IO uint16_t ISTR; /*!< Interrupt status register, Address offset: 0x44 */
__IO uint16_t RESERVED9; /*!< Reserved */
__IO uint16_t FNR; /*!< Frame number register, Address offset: 0x48 */
__IO uint16_t RESERVEDA; /*!< Reserved */
__IO uint16_t DADDR; /*!< Device address register, Address offset: 0x4C */
__IO uint16_t RESERVEDB; /*!< Reserved */
__IO uint16_t BTABLE; /*!< Buffer Table address register, Address offset: 0x50 */
__IO uint16_t RESERVEDC; /*!< Reserved */
} USB_TypeDef;
寄存器组起始地址
为什么要使用寄存器映射
直接硬件控制:寄存器映射允许程序员直接访问和控制芯片的硬件资源。就像在智能家居系统中,我们可以直接通过给定的“地址”(寄存器地址)去控制特定的灯光开关(外设功能),而无需经过复杂的中间层。例如,通过设置GPIO的配置寄存器,我们可以精确地设置引脚的输入输出模式、输出速度等参数,实现对外部设备的精准控制。
高效性:直接操作寄存器可以避免通过库函数等多层调用带来的额外开销。在实时性要求较高的应用中,如工业控制、机器人运动控制等,快速地访问和操作硬件寄存器能够确保系统及时响应外部事件。就像在智能家居中,当我们按下灯光开关的瞬间,系统能够立即做出反应,而不会因为中间处理过程产生明显的延迟。
灵活性:寄存器映射提供了对硬件的底层访问能力,使得程序员可以根据具体需求灵活地配置和使用芯片的功能。不同的应用场景可能需要不同的硬件配置,通过直接操作寄存器,我们可以根据实际需求对芯片进行个性化的设置。
寄存器映射和存储器映射的关系和区别
关系
寄存器映射是存储器映射的一部分。存储器映射定义了整个芯片存储器空间的地址分配,包括Flash存储器、SRAM、外设寄存器等。寄存器映射则是将外设寄存器具体地映射到存储器地址空间中的特定位置。例如,在STM32F1系列芯片的存储器映射中,外设寄存器区域包含了各个外设(如GPIO、USART等)的寄存器地址,寄存器映射就是明确每个外设寄存器在这个区域中的具体地址。
区别
范围:存储器映射涵盖了芯片的整个存储器空间,包括各种类型的存储器和外设寄存器所占用的地址范围。而寄存器映射只关注外设寄存器在存储器地址空间中的映射关系。
目的:存储器映射的主要目的是为芯片的存储器资源提供一个统一的地址规划,方便CPU对不同存储区域进行访问。寄存器映射的目的则是为了使程序员能够方便地通过内存地址直接访问和控制外设寄存器,实现对硬件外设的操作。
————————————————
版权声明:本文为CSDN博主「hardStudy_h」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45720999/article/details/151106802
|
|