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

C51中对不可位寻址的特殊寄存器设置为啥常看到用或逻辑置位

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
之前一直用汇编编写51的程序,感觉比较复杂的运算还是蛮麻烦的,于是就开始学习C51编程,看到书里的实例中对一些不能进行位寻址的特殊寄存器的置位,往往都采用了或逻辑运算来实现(|=),尤其在程序开始时就需要初始化定义的特殊寄存器,为什么不直接赋值而需要用或逻辑运算?简单举个例子,程序中只需要使用T0,8位重装模式,照汇编里的习惯直接TMOD赋值(TMOD=0x02),但是书里面却使用了 TMOD|=0x02。实在不明白为啥。还望各位大侠指点小的一二,在此表示非常感谢& T+ d; g# Z( y1 m: V$ F

该用户从未签到

2#
发表于 2022-10-31 11:22 | 只看该作者
在嵌入式C程序中,经常使用“|”,“&”,“^”等运算符,对变量或寄存器的某一个或某几个位进行置1、清0和取反操作。+ m  G4 ?- a% ?
置1:$ _- l* u& Q* R( v
P0 |= 0b1000 0000;    //将P0的bit7置1,同时不影响P0的其它位3 [' ~0 n/ ^. C  W. @
P0 |= 0b1100 0000;    //将P0的bit7和bit6置1,同时不影响P0的其它位
/ @) T+ V9 h2 R. Y9 z8 Q# Q清0:+ r" K$ _9 ^. v5 v$ x" s3 L1 `
P0 &= 0b0111 1111;    //将P0的bit7清0,同时不影响P0的其它位& C: p+ P, D: B: a' X3 |& @* ]5 n
P0 &= 0b0011 1111;    //将P0的bit7和bit6清0,同时不影响P0的其它位
& W# O0 R" d# r8 M8 w) f取反:
# S: r& Y& A" @! w! J/ f+ A1 jP0 ^= 0b1000 0000;    //将P0的bit7取反,同时不影响P0的其它位4 c9 O+ z% T5 r4 q) K4 x$ X9 F
P0 ^= 0b1100 0000;    //将P0的bit7和bit6取反,同时不影响P0的其它位  }- C$ `9 x) C7 @! ^& M$ t- v

7 o4 ?% a2 @8 }1 h. g以上代码,只在支持二进制的编译器下才能工作。而keil不支持二进制,所以可改为以下写法:
4 p% M7 @* R4 f7 t7 W$ A5 S3 T置1:5 q) \8 h3 C( N: l$ p
P0 |= 0x80;    //将P0的bit7置1,同时不影响P0的其它位
- w3 Z  J6 P4 R( _+ @P0 |= 0xC0;    //将P0的bit7和bit6置1,同时不影响P0的其它位
; |/ m: k5 Q6 W: f& Y清0:
4 `% ]' p- [* r0 U8 z" eP0 &= ~0x80;    //将P0的bit7清0,同时不影响P0的其它位
- b5 y, u( }" S* G% _6 K/ Q/ Z  LP0 &= ~0xC0;    //将P0的bit7和bit6清0,同时不影响P0的其它位
. ?' e! s9 y" T  ~3 b取反:( i- |) v6 z! o  f/ r
P0 ^= 0x80;    //将P0的bit7取反,同时不影响P0的其它位
% C! F% ~2 |6 N$ W! _P0 ^= 0xC0;    //将P0的bit7和bit6取反,同时不影响P0的其它位
) B" i( c9 e0 O. Z: r" h! W2 l9 V/ ]+ u& `( R$ v) A
更直观的写法是:
* J. q0 y# J: R8 ?5 b#define  BIT(X)   (1<<(X))% J2 v9 v+ o0 J& q' _1 _& w
这样,
6 f- ^  u5 `/ {: l. V+ e1 _% EBIT(0)会被展开为1 << 0,即0b0000 0001 << 0,即0b0000 0001,即0x019 o) w0 M  F7 U! J/ m9 j
BIT(1)会被展开为1 << 1,即0b0000 0001 << 1,即0b0000 0010,即0x02
  _0 v! ?2 p) F  C/ YBIT(0)会被展开为1 << 2,即0b0000 0001 << 2,即0b0000 0100,即0x04
8 c$ y8 c- _' q: H: m8 v……8 d" L1 M3 S6 {
BIT(1)会被展开为1 << 7,即0b0000 0001 << 7,即0b1000 0000,即0x80) i  g+ V! O1 Q+ X0 V7 j  `& t
于是,& E+ A3 M/ w' ^
BIT(7)|BIT(6)会被展开为0b1000 000 | 0b0100 0000,即0x80 | 0x40,即0xC0) z5 K2 G3 f3 r( n* ]5 d

; Z8 s" H1 a+ n8 Z* m) m于是,
$ @1 A# a; J; z置1:; ]' M0 _$ i9 a' F+ g  D
P0 |= BIT(7);                     //将P0的bit7置1,同时不影响P0的其它位1 U# C- W; z' d0 u! V) U" y
P0 |= BIT(7)|BIT(6);          //将P0的bit7和bit6置1,同时不影响P0的其它位  K6 x5 K1 d6 M% q. t
清0:
( i" _  |* n7 q4 |9 B( `/ N2 [( uP0 &= ~BIT(7);                 //将P0的bit7清0,同时不影响P0的其它位4 X/ t* ~! Z, I+ X" S. y9 A' q) B; H
P0 &= ~(BIT(7)|BIT(6));    //将P0的bit7和bit6清0,同时不影响P0的其它位* t( y  S7 J: K( G0 o+ {% ?7 f6 S
取反:9 q, w8 P# q9 k5 p
P0 ^= BIT(7);                   //将P0的bit7取反,同时不影响P0的其它位
6 ^; r. {6 _  V1 iP0 ^= BIT(7)|BIT(6);         //将P0的bit7和bit6取反,同时不影响P0的其它位

该用户从未签到

3#
发表于 2022-10-31 13:11 | 只看该作者
每个寄存器都有好多不同的位,他们有着不同的功能,你给2之后其他位你都赋0了相当于,如果之前他有其他位你用了,相当于你给人家改了,所以用或运算,这样其他位都不会受影响。

该用户从未签到

4#
发表于 2022-10-31 13:55 | 只看该作者
假设TMOD 原本的值位XXXX XXXX共8个bit,每个bit代表寄存器里面的1个位,XXXX XXXX | 0000 0010 = XXXX XX1X,把这个值写到TMOD里面,如果你直接把0x02写到寄存器里面,那么上面描述的X位都会被清0,最后写进去的就是0000 0010
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-9-11 07:46 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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