存储器与寄存器介绍


1.什么是存储器映射

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程称为存储器映射,如果再分配一个地址就叫重映射(具体地址分配参考芯片数据手册及中文参考手册)

stm32学习之路---存储器与寄存器介绍

比如分组block2里面的外设(block2往上的分组都是外设),就随便拿个举例TIM3,我们不可能拿这个外设的地址来操作外设,这样太麻烦,所以我们就弄个寄存器,这个名字就是寄存器。对这个名字的操作就是对这个相印外设的操作。给已经分配好地址的有特定功能的内存单元起别名的过程就叫寄存器映射(也就是名字映射到这个外设的地址)

STM32F103Z把4GB的内存空间分为8各部分,每一个部分都是是512MB。每个部分都有自己的功能。
比如我们单片机里的Flash存储器在分组block0里面,单片机里的SRAM存储器在分组Block1里面(64KB)

stm32学习之路---存储器与寄存器介绍


2.如何访问STM32寄存器内容

寄存器就是一些有特定功能的内存单元,所以我们访问stm32寄存器就是操作stm32的内存单元。我们可以用C语言的指针来stm32的内存单元。

stm32学习之路---存储器与寄存器介绍

上面是stm32里面的3根总线,总线基地址是总线的初地址,相对外设基地址的偏移是当前总线距离上一根总线的距离地址大小也就是上跟总线所占的地址的大小。

所以我们可以用C语言来外设基地址:
#define APB1_base ((unsigned int)0x4000 0000)
#define APB2_base (APB1_base + 0x0001 0000)

stm32学习之路---存储器与寄存器介绍
stm32学习之路---存储器与寄存器介绍

那么我们如何用C语言来控制这些外设呢?我们举个GPIOC的例子:
#define GPIOC_BASE (APB2_base+0x1000)

我们知道了GPIOC的外设端口地址,那我们如何控制外设端口里面的寄存器地址呢?

stm32学习之路---存储器与寄存器介绍
同样使用C语言宏定义其端口寄存器地址:

同样使用C语言宏定义其端口寄存器地址:
#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)

stm32学习之路---存储器与寄存器介绍

这是个一个端口位设置/清除寄存器,知道它的地址偏移就相当于知道它的地址,GOPIO内每个寄存器是4字节也就是32位,这里把它分成了两组,一组是清0端就是让端口输出低电平,一个使其输出高电平。每组16位对应着16个引脚(GPIOC就是引脚分组里面的其中一个分组,每组16引脚),哪位写1对应的引脚就是低电平。

比如这个寄存器,高16位对应这16引脚,想让哪个引脚输出高电平就写1。低16位哪位写1对应的位就输出高电平

控制 GPIOC 引脚 0 输出低电平(即通过BSRR 寄存器的 BR0 置 1) 
GPIOC_BSRR = (0x01<<(16+0)); //把1移到高16位的第一位了

控制 GPIOC 引脚 0 输出高电平(即通过BSRR 寄存器的 BS0 置 1) 
GPIOC_BSRR = 0x01<<0;   //低16位的第一位

读取GPIOC端口所有引脚的电平(读 IDR 寄存器)
unsigned int temp;
temp = GPIOC_IDR;

我们这里仅仅以GPIO这个外设为例,给大家讲解了如何使用C语言对寄存器封装的,对于其他的外设也是使用同样方法。其实到了后面的实验程序的编写时,我们都是使用ST公司提供的固件库,他把STM32所有外设都已经封装好了,我们这里分析这个封装过程只是想让大家更加清楚理解如何使用C来封装寄存器的。

相关文章: