STM32F103 采用的是 Cortex-M3 内核,内核之外的部件被称为核外外设或片上外设。
如
GPIO
、
USART
(串口)、
I2C
、
SPI
等都叫做片上外设。内核和外设之间通过各种总线连接,其中驱动单元有
4 个,被动单元也有 4
个,
1 ICode 总线
内核通过ICode 总线从FLASH中取指
2 驱动单元
2.1 DCode 总线
D为DATA,数据分为常量和变量,常量是固定不变的,放到内部的 FLASH 当中,变量是可变的,不管是全局变量还是局部变量都放在内部的SRAM。数据可被 Dcode 总线和 DMA 总线访问,为避免访问冲突,在取数时需经过总线矩阵来仲裁,决定哪个总线在取数。
2.2 系统总线
系统总线主要是访问外设的寄存器,读写寄存器都是通过系统总线来完成。
2.3 DMA 总线
DMA
总线主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在
SRAM
,可以在内部的
FLASH
。
3 被动单元
3.1 内部的闪存存储器
即FLASH,存放编写好的程序。
3.2 内部的 SRAM
程序的变量,堆栈等的开销都是基于内部的 SRAM,内核通过
DCode
总线来访问它。
3.3 FSMC
FSMC
的英文全称是
Flexible static memory controller,叫灵活的静态的存储器控制器,通过
FSMC, 只能扩展静态的内存。
3.4 AHB 到 APB 的桥
从
AHB
总线延伸出来的两条
APB2
和
APB1
总线,上面挂载着
STM32
各种各样的特
色外设。我们经常说的
GPIO
、串口、
I2C
、
SPI
这些外设就挂载在这两条总线上。
4 存储器映射
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,
如果给存储器再分配一个地址就叫存储器重映射。
4.1 存储器区域功能划分
被控单元的
FLASH
,
RAM
,
FSMC
和
AHB
到
APB
的桥(即片上外设), 这些功能部件共同排列在一个 4GB 的地址空间内。ARM 将其
平均分成了
8
个块,每块
512MB
,
Block0
用来设计成内部 FLASH;
Block1
用来设计成内部
RAM;
Block2
用来设计成片上的外设。
5 寄存器映射
片上外设,以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
0x4001 0C0C
在我们看来是
GPIOB
端口
ODR
的地址,但是在编译器看来,这只是一个
普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把
它转换成指针,即
(unsigned int *)0x4001 0C0C
,然后再对这个指针进行
*
操作。
6 STM32 的外设地址映射
APB1挂载低速外设,APB2
和
AHB
挂载高速外设。
6.1
总线基地址
6.2
外设基地址
GPIO
属于高速外设 ,挂载到 APB2 总线上。
6.3
外设寄存器
GPIO 是通用输入输出端口的简称
GPIO
有很多个寄存器,每个都有特定的功能。每个寄存器为
32bit,占四个字节,以
GPIOB
端口为例
7
C
语言对寄存器的封装
7.1
封装总线和外设基地址
使用指针控制
BSRR
寄存器
该代码使用
(unsigned int *)
把
GPIOB_BSRR
宏的数值强制转换成了地址,然后再用“
*
”
号做取指针操作,对该地址的赋值,从而实现了写寄存器的功能。
6.2
封装寄存器列表
为了更方便地访问寄存器,引入
C
语言中的结构体 语法对寄存器进行封装。
用
typedef
关键字声明了名为
GPIO_TypeDef
的结构体类型,
C
语言的语法规定,结构体内变量的存储空间是连续的,其中 32
位的变量占用
4
个字节,
16
位的变量占用
2
个字节。
CRL 的地址为0x40010C00,
CRH(图错误为ORH)
的地址为0x40010C00+0x04。
通过结构体指针访问寄存器
这段代码先用
GPIO_TypeDef
类型定义一个结构体指针
GPIOx
,并让指针指向地址
GPIOB_BASE(0x4001 0C00)
,使用地址确定下来,然后根据
C
语言访问结构体的语法,用
GPIOx->ODR
及
GPIOx->IDR
等方式读写寄存器。