stm32地址映射

stm32地址映射

一、#define定义的基地址

在这里插入图片描述

二、结构体位移

对于寄存器,ST公司由更好的操作就是结构体指针,例如把GPIO的所有寄存器保存在结构体GPIO_TypeDef里,将GPIOA的基地址强制类型转换成GPIO_TypeDef类型指针,将基地址之后的内容设置为GPIO_TypeDef类型,每个寄存器的偏移量和结构体里设置变量的偏移量相同,就可以通过结构体指针的方式直接访问GPIOA口任一配套的寄存器。例如:GPIOA->ODR。

三、位带操作

1、数据手册中的介绍

在这里插入图片描述
在这里插入图片描述

2、个人理解

位带是一段实际存储数据的部分,位带中的每一位(bit)都可以由位带别名区对应的区域赋值从而实现位更改(硬件实现)。位带中的1位(bit)被膨胀成32位(bit)即4字节,因此对位带别名区赋值的时候只有最低位有效(LSB)。位带中的1字节(Byte)在位带别名区中对应着32字节,位带中的1位(bit)在位带别名区中对应着4字节,所以在样例中每字节的偏移量需要乘32,每位的偏移量需要乘4。

例如:GPIOA的ODR寄存器的位带别名区中的地址就是0x2200 0000 + (&(GPIOA->ODR) - 0x20000000)) + 位偏移。

SRAM区:AliasAddr = 0x22000000 + (A - 0x20000000) * 32 + n * 4
片上外设区:AliasAddr = 0x42000000 + (A - 0x40000000)* 32 + n * 4

3、演示程序

#include "stm32f10x.h"

#define BITBAND_SRAM(address, bit)    ((*(volatile uint32_t *) (0x22000000 + (((uint32_t)address) - 0x20000000) * 32 + (bit) * 4)))
#define PA5_BITBAND                   BITBAND_SRAM(&(GPIOA->ODR), 5)

int main(void)
{
    // 启用 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 PA5 引脚为推挽输出模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 通过位带操作设置 PA5 输出高电平
    PA5_BITBAND = 1;

    while(1)}


### STM32地址映射实现方法 在STM32中,地址映射是通过使用存储器映射表来完成的。该表格定义了不同类型存储器资源的位置和大小于地址空间之中[^3]。 对于具体实现而言,在编程层面,操作硬件即意味着操作寄存器。为了简化这一过程并减少错误发生率,开发人员会基于各个单元的功能赋予其别名——也就是所谓的寄存器名字。这种做法被称为寄存器映射,它使得原本难以记住的具体物理地址转换成易于理解和使用的逻辑名称[^4]。 #### 寄存器映射实例展示 当涉及到实际编写代码来进行寄存器访问时,可以利用结构体联合指针技术来创建友好的接口: ```c // 定义一个代表定时器控制寄存器的数据结构 typedef struct { volatile uint32_t CR1; volatile uint32_t CR2; } TIM_TypeDef; #define PERIPH_BASE (0x40000000UL) /* Peripheral base address */ #define APB1PERIPH_BASE (PERIPH_BASE + 0x0000) #define TIM2_BASE (APB1PERIPH_BASE + 0x0000) #define TIM2 ((TIM_TypeDef *) TIM2_BASE) ``` 上述代码片段展示了如何为`TIM2`定时器建立方便调用的宏定义。这里先声明了一个描述定时器特性的结构体`TIM_TypeDef`,接着设置了外设基础地址常量,并最终将这些组合起来形成可以直接用于程序内的对象表示形式。 一旦完成了这样的设定之后,便可以在应用程序里轻松地读写相应寄存器而无需关心底层复杂的地址细节。例如要启用或禁用某个特性只需简单地修改对应的位即可: ```c // 启动TIM2计数器 TIM2->CR1 |= (1 << 0); // 设置CEN位使能计数器 ``` 这种方法不仅提高了代码可维护性和移植性,同时也降低了因手动计算偏移而导致潜在风险的可能性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值