前言
有过51单片机开发经历的朋友应该都对51的IO口或一些特殊寄存器可以直接按位操作的方式不陌生吧,那么在stm32中有没有类似的操作呢,答案是肯定的,本节将给大家介绍如何在STM32中实现位带操作。
在《ARM Cortex-M3权为指南》中的第87页对位带操作如下描述:
位带操作
支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在 CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。
位带区与位带别名区的膨胀关系图 A
位带区与位带别名区的膨胀对应关系图 B
示例详解
基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。
本示例所用的最小系统板原理图:
位带操作的概念其实30年前就有了,那还是8051 单片机开创的先河。如今,CM3 将此能力进化,这里的位带操作是 8051 位寻址区的威力大幅加强版。
CM3 使用如下术语来表示位带存储的相关地址
z 位带区: 支持位带操作的地址区
z 位带别名: 对别名地址的访问最终作用到位带区的访问上(注意:这中途有一个对
地址映射过程)
在位带区中,每个比特都映射到别名地址区的一个字——这是只有 LSB 有效的字。当一个别名地址被访问时,会先把该地址变换成位带地址。对于读操作,读取位带地址中的一个字,再把需要的位右移到 LSB,并把 LSB 返回。对于写操作,把需要写的位左移至对应的位序号处,然后执行一个原子的“读-改-写”过程。
支持位带操作的两个内存区的范围是:
0x2000_0000‐0x200F_FFFF(SRAM 区中的最低 1MB)
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)
对于 SRAM 位带区的某个比特,记它所在字节地址为 A, 位序号为 n(0<=n<=7),则该比特在别名区的地址为:
AliasAddr= 0x22000000+((A‐0x20000000)*8+n)*4 =0x22000000+ (A‐0x20000000)*32 + n*4
对于片上外设位带区的某个比特,记它所在字节的地址为 A,位序号为 n(0<=n<=7),则该比特在别名区的地址为:
AliasAddr= 0x42000000+((A‐0x40000000)*8+n)*4 =0x42000000+ (A‐0x40000000)*32 + n*4
上式中,“*4”表示一个字为 4 个字节,“*8”表示一个字节中有 8 个比特。
对于 SRAM 内存区,位带别名的重映射如表 5.2 所示:
表 5.2 SRAM 区中的位带地址映射
位带区 等效的别名地址
0x20000000.0 0x22000000.0
0x20000000.1 0x22000004.0
0x20000000.2 0x22000008.0
…
0x20000000.31 0x2200007C.0
0x20000004.0 0x22000080.0
0x20000004.1 0x22000084.0
0x20000004.2 0x22000088.0
…
0x200FFFFC.31 0x23FFFFFC.0
对于片上外设,映射关系如下表所示:
表 5.3 SRAM 区中的位带地址映射
位带区 等效的别名地址
0x40000000.0 0x42000000.0
0x40000000.1 0x42000004.0
0x40000000.2 0x42000008.0
…
0x40000000.31 0x4200007C.0
0x40000004.0 0x42000080.0
0x40000004.1 0x42000084.0
0x40000004.2 0x42000088.0
…
0x400FFFFC.31 0x43FFFFFC.0
通过上面的实例,我们成功地通过使用位带别名地址实现对寄存器中位的操作程,成功控制PC13引脚来控制LED的亮灭。是不是很简单,对于在SRAMSRAM 内存区,通过位带别名同样可以轻易实现对位操作,有兴趣的同学可以自行实险一下。
OK,本期实验完成!下期见!同时如果大家有什么疑问或是有想了解的其它内容,也欢迎大家留言!!最后喜欢这个公众号的同学们记得加关注了,会有不定期技术干货推出!!
文中源码资料下载,在公众号里给十三发消息:
下载|STM32进阶教程 8
关注十三公众号