文章目录[隐藏]
目录
STM32芯片里面有什么
我们看到的STM32芯片是已经封装好阿成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的CPU和主板、内存、显卡、硬盘的关系。
STM32F103采用的是Cortex-M3内核,内核即CPU,由ARM公司设计,ARM公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商(SOC)如ST、TI、Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。如GPIO、USART(串口)、I2C、SPI等都叫片上外设。具体见下图STM32芯片架构简图。
芯片(这里指内核,或者叫CPU)和外设之间通过各种总线连接,其中驱动单元4个,被动单元也有4个。为了方便理解,我们都可以把驱动单元理解成是CPU部分,被动单元都理解外设。
一、驱动单元
1、ICode总线
ICode中的I表示Instruction,即指令。我们写好的程序编译之后都是一条条指令,存放在FLASH中,内核要读取这些指令来执行程序就必须通过ICode总线,它几乎每时每刻都需要被使用,它是专门用来取指令的。
2、DCode总线
DCode总线中的D表示Data,即数据,那说明这条总线是用来取数据的。我们在写程序的时候,数据有常量和变量两种,常量就是固定不变的,用C语言中的const来修饰的,是放到FLASH当中的,变量是可变的,不管是全局变量还是局部变量都存放在内部的SRAM中。因为数据可以被DCode总线和DMA总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。
3、系统总线
系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这跟系统总线来完成的。
4、DMA总线
DMA总线也主要是用来,传输数据,这个数据可以是在某个外设的数据寄存器,可以在SRAM,可以在内部的FLASH。因为数据可以被DCode总线和DMA总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。
二、被动单元
1、内部的闪存存储器
内部的闪存存储器即FLASH,我们编写好的程序就放在这个地方。内核通过ICode总线来取里面的指令。
2、内部的SRAM
内部的SRAM,即我们通常常说的RAM,程序的变量,堆栈等的开销都是基于内部的SRAM。内核通过DCode总线来访问它。
3、FSMC
FSMC的英文全称是Flexible static memory controller,叫灵活的静态的存储器控制器,是STM32F10xx中一个很有特色的外设,通过FSMC,我们可以扩展内存,如外部的SRAM、NAND-FLASH和NORFLASH。但我们有一点要注意的是,FSMC只能扩展静态的内存,即名称里面的static,不能是动态的内存,比如SDRAM就不能扩展。
4、AHB到APB的桥
从AHB总线延伸出来的两条APB2和APB1总线,上面挂载着STM32的各种各样的外设。我们经常说的GPIO、串口、I2C、SPI这些外设就挂载在这两条总线上,这个是我们学习STM32的重点,就是要学会编程这些外设的驱动外部的各种设备。
存储器映射
存储器本身具备有地址信息,它的地址是由芯片厂商或由用户分配,给存储器分配地址的过程就称为存储器映射,具体可见下面的存储器映射。如果给存储器再分配一个地址就叫存储器重映射。
存储器区域功能划分
在这4GB地址的空间内,ARM已经粗线条的平均分成了8个块,每块512MB,每个块也都规定了用途,具体分类见表格存储器功能分类。每个块的大小都有512MB,显然这是一块非常大的区域,芯片厂商在每个块的范围内设计各具特色的外设时并不一定用得完,都是只用了其中一部分。
序号 | 用途 | 地址范围 |
Block0 | Code | 0x0000 0000~0x1FFF FFFF(512MB) |
Block1 | SRAM | 0x2000 0000~0x3FFF FFFF(512MB) |
Block2 | 片上外设 | 0x4000 0000~0x5FFF FFFF(512MB) |
Block3 | FSMC的bank1~bank2 | 0x6000 0000~0x7FFF FFFF(512MB) |
Block4 | FSMC的bank3~bank4 | 0x8000 0000~0x9FFF FFFF(512MB) |
Block5 | FSMC寄存器 | 0xA000 0000~0xCFFF FFFF(512MB) |
Block6 | 没有使用 | 0xD000 0000~0xDFFF FFFF(512MB) |
Block7 | Cortex-M3内部外设 | 0xE000 0000~0xFFFF FFFF(512MB) |
在这8个块里面有三个块非常重要,Block0用来设计内部FLASH,Block1用来设计内部RAM,Block2用来设计成片上的外设。
寄存器映射
寄存器映射:给已经分配好地址的具有特定功能的内存单元取别名的过程就叫寄存器映射。
比如,我们先找到GPIOB的端口的输出数据寄存器ODR的地址是0x40010C0C,ODR寄存器是32位的,低16位有效,对应着16个外部IO,写0/1对应的IO输出对应的低/高电平。
//GPIO端口全部输出高电平
*(unsigned int*) (0x40010C0C) = 0xFFFF;
0x40010C0C在我们看来是GPIOB的端口的ODR地址,但是在编译器看来,
这只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,
我们得进行强制类型转换,把它转换成指针,即(unsigned int*)0x40010C0C,
然后对这个地址进行*操作。
通过寄存器别名的方式访问内存单元
//GPIOB端口全部输出高电平
#define GPIOB_ODR (unsigned int*)(GPIOB_BASE + 0x0C)
*GPIOB_ODR = 0xFF;
为了方便操作,直接把指针操作"*"也定义到寄存器别名中。
//GPIOB端口全部输出高电平
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE + 0x0C)
GPIOB_ODR = 0xFF;
三、STM32的外设基地址映射
片上外设区分三条总线,根据外设速度的不同,不同总线挂在着不同的外设,APB1挂载低速外设,APB2和AHB挂载高速外设。相应的总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。其中APB1总线的地址最低,片上外设从这里开始,也叫外设基地址。
1、总线基地址
总线名称 | 总线基地址 | 相对外设基地址的偏移 |
APB1 | 0x4000 0000 | 0x0 |
APB2 | 0x4001 0000 | 0x0001 0000 |
AHB | 0x4001 8000 | 0x0001 8000 |
表格总线基地址的“相对外设基地址偏移”即该总线地址与“片上外设”基地址0x4000 0000的差值。
2、外设基地址
总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的收个地址“称为XX外设基地址”,也叫XX外设的边界地址。具体有关的STM32F10xx外设的边界地址可以参考具体的存储器映射的表。
这里以GPIO这个外设来讲解外设的基地址,GPIO属于高速的外设,挂载到APB2总线上。
外设名称 | 外设基地址 | 相对APB2总线的地址偏移 |
GPIOA | 0x4001 0800 |
0x0000 0800 |
GPIOB | 0x4001 0C00 | 0x0000 0C00 |
GPIOC | 0x4001 1000 | 0x0000 1000 |
GPIOD | 0x4001 1400 | 0x0000 1400 |
GPIOE | 0x4001 1800 | 0x0000 1800 |
GPIOF | 0x4001 1C00 | 0x0000 1C00 |
GPIOG | 0x4001 2000 | 0x0000 2000 |
3、外设寄存器
在XX外设的地址范围内,分布着的就是该外设的寄存器。以GPIO外设为例,GPIO是通用输入输出端口的简称,简单来说就是STM32可控制的引脚,基本功能是控制引脚输出高低电平。
GPIO有很多个寄存器,每一个都有特定的功能。每个寄存器为32bit,占4个字节,在改外设的基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描述。这里我们以GPIOB端口为例,来说明GPIO都有哪些寄存器,具体见表格GPIOB端口的寄存器地址列表。
寄存器名称 | 寄存器地址 | 相对GPIOB基址的偏移 |
GPIOB_CRL | 0x4001 0C00 | 0x00 |
GPIOB_CRH | 0x4001 0C04 | 0x04 |
GPIOB_IDR | 0x4001 0C08 | 0x08 |
GPIOB_ODR | 0x4001 0C0C | 0x0C |
GPIOB_BSRR | 0x4001 0C10 | 0x10 |
GPIOB_BRR | 0x4001 0C14 | 0x14 |
GPIOB_LCKR | 0x4001 0C18 | 0x18 |
这里我们以“GPIO端口置位/复位寄存器为例”,教大家如何理解寄存器的说明,具体见GPIO端口置位_复位寄存器说明。
1、名称
寄存器说明中首先列出了该寄存器中的名称,“(GPIOx_BSRR)(x=A...E)”这段的意思是该寄存器名为”GPIOx_BSRR“其中的x可以为”A...E“,也就是说这个寄存器说明适用于GPIOA、GPIOB至GPIOE,这些端口都有这样一个寄存器。
2、偏移地址
偏移地址是指本寄存器相对于这个外设的基地址的偏移。本寄存器的偏移地址是0x10,从手册可以查到GPIOA这个外设的基地址为0x4001 0800,我们就可以算出GPIOA这个GPIOA_BSRR寄存器地址为:0x4001 0800+0x10。
3、寄存器位表
紧接着的就是本寄存器的位表,表中列出了0-31位的名称及权限。表上方的数字为位编号,中间为位名称,最下方为读写权限,其中w表示只写,r表示只读,rw表示可读写。本寄存器中的位权限都是w,所以只能写,如果读本寄存器,是无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于STM32外设的某种工作状态的,由STM32硬件自动生效,程序通过读取那些寄存器位来判断外设的工作状态。
4、位功能说明
位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。这里不再详细讲解。
版权声明:本文为CSDN博主「~Old」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43460068/article/details/122167875
暂无评论