STM32 M3内核的位带操作原理及步骤

一、位带操作有什么用?什么是位带操作

位带操作的作用:可以实现对某一GPIO口寄存器(或SRAM内存中)的某一bit位直接写0或1,达到控制GPIO口输出(或改变SRAM中这一bit位的值);就如同51单片机控制GPIO口一样的方便。比如:

51:P1^0=1;  //把P1口的第一个引脚设置为高电平

STM32:PAout(0)=1;   //把PA口的第一个引脚设置成高电平

位带操作的原理:在 CM3 中,有两个区中实现了位带,如下图,其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB范围。

这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特(1bit)膨胀成一个 32 位(4个字节)。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。1MB位带区对应32MB位带别名区(1byte=8bit映射成8*4byte=32byte)。

位带区和位带别名区的映射如下图:

位带区:支持位带操作的地址区

位带别名:对别名地址的访问最终作用到位带区的访问上(这中途有一个地址映射过程)

映射过程举例如下:

要设置0x2000 0000这个字节的第二个位bit2为1,使用位带操作的步骤有:1、将1写入位    带别名区对应的映射地址(即0x22000008,因为1bit对应4个byte);2、将0x2000 0000的值    读取到内部的缓冲区(这一步骤是内核完成的,属于原子操作,不需要用户操作);3、将bit2    置1,再把值写 回到0x2000 0000(属于原子操作,不需要用户操作)。

映射过程总结:在位带区中,每个比特都映射到别名地址区的4个字节——且4个字节只有最低位有效。当一个别名地址被访问时,会先把该地址变换成位带地址。对于读操作,读取位带地址中的4个字节(因为数据总线是32位的,寄存器也是32位的,所以是读4个字节),再把需要的位右移到最低有效位,并把最低有效位返回(相当于将位带区的值右移再做与操作)。对于写操作,把需要写的位左移至对应的位序号处(相当于把1(或0)左移n(n为该bit位所在的位置)位再和位带区的值做与操作),然后执行一个原子的“读-改-写”过程。

位带操作的优点:1、操作简单;2、因为进行的是原子操作,可以防止对寄存器的脏写。

二、位带操作的代码实现解析

这部分内容参考《STM32F3与F4系列Cortex M4内核编程手册》,先贴原文:

A word access to the SRAM or peripheral bit-band alias regions map to a single bit in the SRAM or peripheral bit-band region.

Bit band accesses can use byte, halfword, or word transfers. The bit band transfer size matches the transfer size of the instruction making the bit band access.

The following formula shows how the alias region maps onto the bit-band region:

bit_word_offset = (byte_offset x 32) + (bit_number x 4)

bit_word_addr = bit_band_base + bit_word_offset

Where:

  • Bit_word_offset is the position of the target bit in the bit-band memory region.

•      Bit_word_addr is the address of the word in the alias memory region that maps to the

targeted bit.

•      Bit_band_base is the starting address of the alias region.

•      Byte_offset is the number of the byte in the bit-band region that contains the targeted

bit.

  • Bit_number is the bit position, 0-7, of the targeted bit.

这段英文介绍了位带区和位带别名区的地址映射关系。要获得某个位带区地址在位带别名区的映射地址,按照上面的公式即可求出。下面一一解释:

bit_word_offset:基于位带别名区起始地址的偏移;

bit_word_addr:映射在位带别名区的地址(即为所求的地址);

Bit_band_base:位带别名区的起始地址,如下图中编号3所示;

Byte_offset:该字节(或32位字)相对于位带区起始地址的偏移;

Bit_number:该bit位在所在字节(或32位字)中的位置,范围0~7(0~31),如下图中编号1所示;

bit_number x 4:4表示一bit位在位带别名区占4个字节的地址空间

下面用实例来进行叙述:

参考资料中的实例:

1、位带区起始地址在位带别名区的地址映射:

The alias word at 0x2200001C maps to bit[7] of the bit-band byte at 0x20000000:

0x2200001C = 0x22000000+ (0*32) + (7*4)

2、位带区结束地址在位带别名区的地址映射:

The alias word at 0x23FFFFED maps to bit[0] of the bit-band byte at 0x200FFFFF:

0x23FFFFED = 0x22000000 + (0xFFFFF*32) + (0*4)

下面解释一下,0x00000~0xFFFFF为1MB的地址;0~7表示一个字节中某一bit位的位置;0x2200 0000表         示位带别名区的起始地址;0xFFFFF*32=0xFFFFF*8*4,表示0xFFFFF*8个bit位在位带别名区所占的地址空间。

代码中的实例分析:

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出

#define GPIOA_ODR_Addr    (GPIOA_BASE+20)  //0x40020014表示GPIOA->ODR寄存器的地址

#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))

#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))

上面的宏定义合成一条:

#define   PAout(n) \

*((volatile unsigned long *)(( GPIOA_ODR_Addr & 0xF0000000)+0x2000000+(( GPIOA_ODR_Addr &0xFFFFF)<<5)+(n<<2))

其中:

GPIOA_ODR_Addr & 0xF0000000=0x4000 0000

(GPIOA_ODR_Addr &0xFFFFF)<<5=0x0002 0014*32

n<<2=n*4

即:PAout(n)= 0x4000 0000+0x2000000+0x0002 0014*32+ n*4

=0x4200 0000+0x0002 0014*32+ n*4

看到这里应该就能看出,这个公式和参考手册中的公式是一样的,是不是很简单!

接下来说下位带操作编程步骤,拿GPIO口举例:

一、宏定义GPIO口输入输出寄存器地址

二、找到位带区起始地址和位带别名区起始地址

三、根据公式做地址换算

四、宏定义PA(n)~PI(n)

STM32 M3内核的位带操作原理及步骤的更多相关文章

  1. STM32之GPIO端口位带操作

    #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //位带操作 //把“位带地址+位序号”转换别名地址宏 #define ...

  2. STM32位带操作总结---浅显易懂

    正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...

  3. 【ARM】---STM32位带操作总结---浅显易懂

    正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...

  4. STM32 中 BIT_BAND(位段/位带)和别名区使用入门(转载)

    一. 什么是位段和别名区 是这样的,记得MCS51吗? MCS51就是有位操作,以一位(BIT)为数据对象的操作,MCS51可以简单的将P1口的第2位独立操作: P1.2=0;P1.2=1 :这样就把 ...

  5. STM32位带操作

    STM32的位带操作是基于cortex内核自带的,而不是st公司独创.基本的思路就是用一个32位的地址空间访问一个bit,因为stm32只支持32位数据的读取,不像51单片机一样,是可以单独对一位操作 ...

  6. STM32中的位带(bit-band)操作(转)

    源:STM32中的位带(bit-band)操作 支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写.在 CM3 中,有两个区中实现了位带.其中一个是 SRAM 区的最低 1MB 范围 ...

  7. 关于STM32位带操作随笔

    以前在学习STM32时候关注过STM32的位带操作,那时候只是知道位带是啥,用来干嘛用,说句心里话,并没有深入去学习,知其然而不知其所以然.但一直在心中存在疑惑,故今日便仔细看了一下,写下心得供日后参 ...

  8. STM32—位带操作

    STM32中的位带操作: 名字为位带操作,实际上是对位的操作,位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见. 51 单片机中通过关键字 sbit 来实现位定义, STM32 ...

  9. (stm32学习总结)—GPIO位带操作

    本章参考资料:<STM32F10X-中文参考手册>存储器和总线构架章节.GPIO 章节,<CM3 权威指南 CnR2>存储器系统章节. 位带简介 位操作就是可以单独的对一个比特 ...

随机推荐

  1. [Linux.NET]Nginx 泛解析配置请求映射到多端口实现二级域名访问

    由于想实现一个域名放置多个应用运行的目的,而不想通过域名后加端口号方式处理,这种方式处理记起来太麻烦,偷懒党简直不能忍,故而考虑了使用二级域名来处理多个应用同时运行.Google了一番资料并进行了尝试 ...

  2. 洗礼灵魂,修炼python(55)--爬虫篇—知识补充—RFC 2616 http状态码

    不多说直接上状态码表: 状态码 含义 100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽 ...

  3. 常用Linux 服务器命令--各种性能指标命令

    如果你想知道你的服务器正在做干什么,你就需要了解一些基本的命令,一旦你精通了这些命令,那你就是一个专业的 Linux 系统管理员. 监控命令## iostat### iostat命令用来显示存储系统的 ...

  4. Sublime Text 3 注册码激活码被移除的解决办法

    新版的sublime text3中加入了验证功能,之前成功注册的也被移除了,在网上搜索的验证码要么已经失效要么已经被封,少数几个正常的注册输入进去注册成功后几分钟之内这个注册码就会被莫名其妙的被移除. ...

  5. FLask上传文件

    目录 Flask上传文件 改进上传 上传进度条 一个更简便的方案 Flask上传文件 文件上传的基本原理实际上很简单,基 本上是: 一个带有 enctype=multipart/form-data 的 ...

  6. Linux之删除带有空格的文件(而不是目录)

    大家平时工作中对不带空格的文件接触较多.这样一来删除操作也是比较简单的.但是有时我们会接触带有空格的文件.对于这种文件我们应该如何删除呢? 首先我们演示一下find命令结合xargs命令删除不带空格的 ...

  7. ghostscript远程代码执行漏洞复现

    这两天网上ghostscript又又有漏洞信息了,但是没有poc,于是找找资料把今年8月21日的那个验证下 1.关于ghostscript Ghostscript是一套建基于Adobe.PostScr ...

  8. February 7th, 2018 Week 6th Wednesday

    We are all resigned to death: it is life we aren't resigned to. 我们可以屈从于死神,但我们却不能让生活任意摆布. Of all the ...

  9. asp.net core 中使用StyleCop.StyleCopAnalyzers

    1.nuget中安装 StyleCop.Analyzers 当前版本1.1.0-beta004 2.在项目根目录新增 stylecop.json文件 { "settings": { ...

  10. SpringMVC 使用JSR-303进行校验 @Valid

    注意:1 public String save(@ModelAttribute("house") @Valid House entity, BindingResult result ...