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);
}