目录
一、STM32F103地址和寄存器映射原理
1.寄存器映射
上图是野火关于STM32F103系列中,存储器分区的一个目录图。整个存储器有4GB的容量,被分为了8个部分,而我们LED点灯主要是使用block2,也就是片上外设部分。可以从下图中看到block2的地址范围,一共是512MB。
接下来我们就可以了解寄存器映射了,在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit, 每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到 每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通 过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的 不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个 给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
比如,我们找到
GPIOB
端口的输出数据寄存器
ODR
的地址是
0x4001 0C0C
,ODR
寄存器是
32bit
,低
16bit 有效,对应着 16
个外部
IO
,写
0/1
对应的的
IO
则输出低
/
高电平。现在我们通过
C
语言指 针的操作方式,让 GPIOB
的
16
个
IO
都输出高电平,具体见代码 :
// GPIOB 端口全部输出 高电平
*(unsigned int*)(0x4001 0C0C) = 0xFFFF;
0x4001 0C0C
在我们看来是
GPIOB
端口
ODR
的地址,但是在编译器看来,这只是一个 普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把 它转换成指针,即(unsigned int *)0x4001 0C0C
,然后再对这个指针进行
*
操作。 刚刚我们说了,通过绝对地址访问内存单元不好记忆且容易出错,我们可以通过寄存 器的方式来操作,具体见代码:
// GPIOB 端口全部输出 高电平
#define GPIOB_ODR (unsigned int*)(GPIOB_BASE+0x0C)
* GPIOB_ODR = 0xFF;
为了方便操作,我们干脆把指针操作“
*
”也定义到寄存器别名里面,具体见代码:
// GPIOB 端口全部输出 高电平
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C)
GPIOB_ODR = 0xFF;
以上是一些对寄存器映射的简单赘述和运用,可以在以后的实验中用上。
2.地址映射
接下来我们来了解地址映射。
①总线基地址
片上外设区分为三条总线,根据外设速度的不同,不同总线挂载着不同的外设,
APB1 挂载低速外设,APB2
和
AHB
挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。其中 APB1
总线的地址最低,片上外设从这里开始,也叫外设基地址。
②外设基地址
总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为 “XX
外设基地址”,也叫