你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32开发中的位运算以及位带操作

[复制链接]
y369369 发布时间:2021-4-13 14:46
    为了像51单片机一样能够对某个管脚单独操作,引入了位带操作这样的操作机制。
    如下图,位带(Bit band)区就是就是你想单独操作的IO的区域,比如PA1、PA2。而位带别名区就是你给每一位重新起了个名字的那一片地址区域。可以看下表,M3内核存储器映射表,你能看到1M内存的BitBand区,还有与之对应的32M内存的BitBand别名区,因为你将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。
2.1.png
    想进行位带操作,应该先去找该位对应的别名区的地址,找到了这个地址,对这个地址进行操作,那么实际上也就是对该位进行操作了。
    官方给出了如下相应的计算公式:
AliasAddr
=0x42000000+((A‐0x40000000)*8+n)*4
=0x42000000+ (A‐0x40000000)*32 + n*4
    其中,AliasAddr是别名区的地址,A是GPIOA->ODR的地址,n是该端口的上的某一位。
   0x42000000是位带别名区域的起始地址,A是输出数据寄存器GPIOA->ODR的地址,A的地址先减去位带区基地址,得到的是相对于位带区基地址的偏移地址,那么膨胀之后还是一个偏移地址,是相对于位带别名区基地址的偏移量,加上位带别名区域基地址,就得到了其对应的别名区地址。
    多数情况下,大家见到的代码,应该是以下这个样子,一共分为三步:
  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
    % P4 H" s& S9 k3 `6 y' P  V# M
  2. #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))                                                                       ' ^, j& ^0 }4 W
  3. #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
复制代码
4 U7 v1 }0 P: p" X" B
    第一步,就是我们上面分析的,得到位带别名区域的32位地址。
    第二步,就是将第一步得到的32位地址,给转换成一个指针变量,并且操作这个地址里的值,唯一的区别,就是由于安全的考虑,多加了一个volatile 这样的关键字。
举个例子
    如下,想直接访问0x00000001这个地址,并且给这个地址写1,该怎么做呢?
  1. # define ADDR 0x00000001* W2 k. C( f: l6 [( N
  2. *(int *)ADDR = 1;
复制代码
4 |7 b; \& w7 R8 D- P
    第三步,就是将前两部,结合在一起,根据传入的addr和bit计算得到32位的地址,然后强制类型转换,使得我们可以去操作这个地址里的值。
    提示:bitnum<<2相当于bitnum2乘以4,实际上在计算机底层乘法也是基于位运算实现的。
文章出处: STM32嵌入式开发
: Y: ?! j6 k0 M/ q7 K3 Q
收藏 评论0 发布时间:2021-4-13 14:46

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版