找回密码
 注册
关于网站域名变更的通知
查看: 236|回复: 1
打印 上一主题 下一主题

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

[复制链接]
  • TA的每日心情
    开心
    2022-12-9 15:13
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    跳转到指定楼层
    1#
    发表于 2022-3-3 17:23 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

    EDA365欢迎您登录!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    本帖最后由 Heaven_1 于 2022-3-3 18:59 编辑 ; b; `5 g* D! K7 N( z

    7 v. r# \4 Z- S$ n为了像51单片机一样能够对某个管脚单独操作,引入了位带操作这样的操作机制。& Q. W: E2 U8 M$ x" J
    9 ]; f$ t/ g! R# a; C/ A* K. {7 I
    如下图,位带(Bit band)区就是就是你想单独操作的IO的区域,比如PA1、PA2。而位带别名区就是你给每一位重新起了个名字的那一片地址区域。可以看下表,M3内核存储器映射表,你能看到1M内存的BitBand区,还有与之对应的32M内存的BitBand别名区,因为你将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。7 E  w  l. Y4 o0 Z
    0 c9 W) U" K$ f* g
    0 k% x. Q% F' _4 ]% b

    & J9 K7 k0 ?2 v( `) M4 f( }6 h7 s7 q想进行位带操作,应该先去找该位对应的别名区的地址,找到了这个地址,对这个地址进行操作,那么实际上也就是对该位进行操作了。
    + g8 D. n" O! Y2 l9 c  j" ]: `9 |5 J; k' B% T
    官方给出了如下相应的计算公式:6 W% T; C5 Q: k5 J$ T2 i
    # w7 i% x1 G" n3 ?3 O3 j
    AliasAddr
    * h5 d* O/ i. q
    2 w; L5 {% k+ N=0x42000000+((A‐0x40000000)*8+n)*4
    . M/ q# o. B9 x) t9 s" U" B" q$ {" g+ ~/ d+ V
    =0x42000000+ (A‐0x40000000)*32 + n*4
    5 o$ D) V1 d. n9 [: m
    ! E7 @3 I9 b) s' \6 o5 I! z其中,AliasAddr是别名区的地址,A是GPIOA->ODR的地址,n是该端口的上的某一位。
    2 Q- I1 X1 f7 j; U( Q. c3 _7 q
    4 f: d2 r$ W+ h* q0x42000000是位带别名区域的起始地址,A是输出数据寄存器GPIOA->ODR的地址,A的地址先减去位带区基地址,得到的是相对于位带区基地址的偏移地址,那么膨胀之后还是一个偏移地址,是相对于位带别名区基地址的偏移量,加上位带别名区域基地址,就得到了其对应的别名区地址。
    4 y; b( H7 g# y6 @2 |# {+ i0 p, y! o6 B9 V" h( @
    多数情况下,大家见到的代码,应该是以下这个样子,一共分为三步:* |4 v: m- N, l3 n( D1 N
    # Y9 x9 Y' C2 e* F: C
    #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
    5 c9 S7 x$ ~! z
    , a1 M0 \1 V9 J! @, @5 A8 k- C#define MEM_ADDR(addr) *((volatile unsigned long *(addr))) v- e% O' T+ J9 D

    ( ?1 C8 p( Y: \7 z% q) X( Y#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
    7 h3 U# H$ P+ E: }/ w1 N- S3 E% D, O
    第一步,就是我们上面分析的,得到位带别名区域的32位地址。
    ( c+ E# D5 R0 |3 G& X; |
    ( S$ u  h- G4 y. v1 O2 l0 Q第二步,就是将第一步得到的32位地址,给转换成一个指针变量,并且操作这个地址里的值,唯一的区别,就是由于安全的考虑,多加了一个volatile 这样的关键字。
    , C5 p- K+ u" n; O2 S8 `
    , u  p' y5 S' p9 f举个例子
    7 W( s  c: Q- d! m8 P0 N3 B* G. b0 c' _
    如下,想直接访问0x00000001这个地址,并且给这个地址写1,该怎么做呢?
    : n* o1 O# X6 c' w4 p7 q) Q* T; V8 `1 q! F$ E# @4 F/ \( Y
    # define ADDR 0x00000001
    . l. s& Q7 Z* K  w/ m5 B/ s" k% S! U, D
    *(int *)ADDR = 1;
    2 o* A( [: Y6 J1 ~3 S* a
    & L2 Y& u/ o) `# {  L; L第三步,就是将前两部,结合在一起,根据传入的addr和bit计算得到32位的地址,然后强制类型转换,使得我们可以去操作这个地址里的值。
    3 J' J; b- l0 N
    , W5 J1 W8 v& R  j% B$ g$ J6 U提示:bitnum<<2相当于bitnum2乘以4,位运算相关文章:C语言操作寄存器的常见手法,实际上在计算机底层乘法也是基于位运算实现的。9 }/ k; ?8 m; B
    5 u- a( }8 g, m8 e/ v5 m

    3 U; u0 ]0 ]1 B6 v- V' F& d' p
    9 Z2 i+ F  V- s. y# C) a0 F2 d
    * d9 n2 ~+ P4 C9 k* t! L

    该用户从未签到

    2#
    发表于 2022-3-3 19:08 | 只看该作者
    很详细,很适合后面的使用
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-10-9 09:48 , Processed in 0.140625 second(s), 27 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表