三、存储器和寄存器

存储器和寄存器

1、程序存储器

1.1 存储器映射

程序存储器、数据存储器、寄存器和 I/O 端口排列在同一顺序的 4 GB 地址空间内。
存储器本身不具有地址信息,其地址由芯片厂商或用户分配,给存储器分配地址的过程称为存储器映射,若再分配一个地址就叫重映射。

2、存储器空间

在这里插入图片描述
ARM将这4GB存储器空间,平均分成8块区域,每块区域大小512MB。

在这里插入图片描述

2.1 Block0

Block0 主要用于设计片内FLASH,STM32F103系列芯片内部FLASH最大
512KB
0x0000 0000-0x0007 FFFF:取决于BOOT引脚,是FLASH、系统存储器、SRAM的别名
0x0008 0000-0x07FF FFFF:预留
0x0800 0000-0x0807 FFFF:片内FLASH,编写的程序就放在这一区域(512KB)
0x0808 0000-0x1FFF EFFF:预留
0x1FFF F000-0x1FFF F7FF:系统存储器,里面存放的是 ST 出厂时烧写好的isp 自举程序,用户无法改动。使用串口下载的时候需要用到这部分程序。
0x1FFF F800-0x1FFF F80F:选项字节,用于配置读写保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。当芯片不小心被锁住后,可以从 RAM 里面启动来修改这部分相应的寄存器位。
0x1FFF F810-0x1FFF FFFF:预留。

2.2 Block1

Block1用于设计片内SRAM,STM32F103ZET6的SRAM是64KB
0x2000 0000-0x2000 FFFF:SRAM,容量为64KB
0x2001 0000-0x3FFF FFFF:预留

2.3 Block2

Block2用于设计片内外设,根据外设总线速度的不同,Block2划分为AHB和APB 两部分,APB又分成APB1和APB2总线。
0x4000 0000-0x4000 77FF:APB1总线外设
0x4000 7800-0x4000 FFFF:预留
0x4001 0000-0x4001 3FFF:APB2总线外设
0x4001 4000-0x4001 7FFF:预留
0x4001 8000-0x4002 33FF:AHB总线外设
0x4002 4400-0x5FFF FFFF:预留
在 Block3/4/5 中还包含了 FSMC 扩展区域,这 3 个块可用于扩展外部存储器,如 SRAM,NORFLASH 和 NANDFLASH 等。

3、寄存器

Cortex-M3内核是32位的,所以其存储器内部是以四个字节为一个单元,每个单元对应一个地址,也对应着不同的功能,因此通过对应的地址控制这些单元也就可以控制外设。
寄存器:给特定功能的内存单元取一个别名,可用指针来操作内存单元。
寄存器映射:给已经分配好地址的有特定功能的内存单元取别名的过程。

4、STM32 外设地址映射

片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设, APB1挂载低速外设,APB2 和 AHB 挂载高速外设。
每条总线的最低地址称为该总线基地址,同时也是挂载在该总线上首个外设地址。
APB1总线的地址最低,因此片上外设就从这这个地址开始,也称外设基地址。

4.1 总线基地址

存储器映射的Block2 分为4块,每块有一个起始地址,称为基地址。总线基地址与片上外设基地址的偏差,叫做相对基地址的偏移量。
在这里插入图片描述

4.2 外设基地址

在这里插入图片描述
外设GPIOx都是挂接在APB2总线上,属于高速的外设,而APB2总线的基地址是0x4001 0000,故GPIOA的相对APB2总线的地址偏移是 800。

4.3 外设寄存器地址

GPIO是通用输入输出端口的简称,GPIO有很多个寄存器,每一个都有特定的功能。每个寄存器32bit,占四个字节,这些寄存器都是按顺序依次排列在外设的基地址上。寄存器的位置都以相对该外设基地址的偏移地址来描述。
在这里插入图片描述
寄存器位功能说明:
两种寄存器位,分别为BRy 及 BSy,其中的y数值表示的是管脚号,可以是 0-15。如BR0、BS0用于控制 GPIOx 的第0个引脚,若x表示GPIOC,就是控制 GPIOC 的第0引脚,而BR1、BS1就是控制GPIOC第1个引脚。
其中BRy引脚的说明:
0:不会对相应的 ODRx 位执行任何操作;
1:对相应 ODRx 位进行复位。

4.4 C语言封装寄存器

//定义外设基地址
#define PERIPH_BASE      ((unsigned int)0x40000000)
//定义APB2总线基地址
#define APB2PERIPH_BASE  (PERIPH_BASE + 0x00010000)
//定义GPIOC外设基地址
#define GPIOC_BASE       (AHB1PERIPH_BASE + 0x0800)
//定义寄存器基地址 以GPIOC为例
#define GPIOC_CRL   *(unsigned int*)(GPIOC_BASE+0x00)
#define GPIOC_CRH   *(unsigned int*)(GPIOC_BASE+0x04)
#define GPIOC_IDR   *(unsigned int*)(GPIOC_BASE+0x08)
#define GPIOC_ODR   *(unsigned int*)(GPIOC_BASE+0x0C)
#define GPIOC_BSRR  *(unsigned int*)(GPIOC_BASE+0x10)
#define GPIOC_BRR   *(unsigned int*)(GPIOC_BASE+0x14)
#define GPIOC_LCKR  *(unsigned int*)(GPIOC_BASE+0x18)

GPIOC_BSRR 的值是这个寄存器的地址,但编译器不知道它是地址,而把它当做立即数,所以要强制转换为(unsigned int * )指针类型才可以对其操作。然后再在前面加上一个“ * ”作取指针操作,表示对该地址内内容进行写,读操作也同样使用“ * ”取指针操作。

unsigned int temp;
temp =GPIOC_IDR;
C 语言中的结构体对寄存器进行封装,具体代码如下:

typedef unsigned int uint32_t; //无符号 32 位变量
typedef unsigned short int uint16_t; //无符号 16 位变量
// GPIO 寄存器列表
typedef struct
{
	uint32_t CRL;   //GPIO 端口配置低寄存器   地址偏移: 0x00
	uint32_t CRH;   //GPIO 端口配置高寄存器   地址偏移: 0x04
	uint32_t IDR;   //GPIO 数据输入寄存器     地址偏移: 0x08
	uint32_t ODR;   //GPIO 数据输出寄存器     地址偏移: 0x0C
	uint32_t BSRR;  //GPIO 位设置/清除寄存器  地址偏移: 0x10
	uint32_t BRR;   //GPIO 端口位清除寄存器   地址偏移: 0x14
	uint16_t LCKR;  //GPIO 端口配置锁定寄存器 地址偏移: 0x18
}GPIO_TypeDef;

C 语言的语法规定,结构体内变量的存储空间是连续的,其中 32 位的变量占用 4 个字节,16 位的变量占用 2 个字节。
地址偏移与STM32 GPIO外设定义的寄存器地址偏移一一对应,只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。

#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)

GPIO_TypeDef * GPIOx; //定义GPIO_TypeDef 型结构体指针GPIOx
GPIOx = GPIOC_BASE; //把指针地址设置为宏 GPIOC_BASE 地址
GPIOx->BSRR = (1 << (16 + 0)); //通过指针访问修改GPIOC_BSRR寄存器

编辑 2023.03.21 23:38 首次编辑

注:本文旨于自己的学习笔记,禁止转载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值