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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

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

该用户从未签到

2#
发表于 2022-10-31 11:22 | 只看该作者
在嵌入式C程序中,经常使用“|”,“&”,“^”等运算符,对变量或寄存器的某一个或某几个位进行置1、清0和取反操作。/ j  N0 ~& V6 Y/ @/ [0 W. n; S- _
置1:
( n! P$ t' P  E8 mP0 |= 0b1000 0000;    //将P0的bit7置1,同时不影响P0的其它位
. X- H+ X( M; K: u1 `P0 |= 0b1100 0000;    //将P0的bit7和bit6置1,同时不影响P0的其它位- N5 g' [5 [% F, ^- B& |
清0:
" A7 \$ ]/ K+ O6 \P0 &= 0b0111 1111;    //将P0的bit7清0,同时不影响P0的其它位5 F3 |& ?9 c9 r! A# F9 w5 z
P0 &= 0b0011 1111;    //将P0的bit7和bit6清0,同时不影响P0的其它位' n8 I) g9 ^4 o2 J8 ?6 F. O% f" z
取反:
5 {3 w/ T  U8 p- a% sP0 ^= 0b1000 0000;    //将P0的bit7取反,同时不影响P0的其它位; r; c( r+ A, \/ S- }1 Q/ u3 m! h) {  N
P0 ^= 0b1100 0000;    //将P0的bit7和bit6取反,同时不影响P0的其它位
& z. U- u" o/ A3 M
% @, M, z6 k8 F) `4 k: }" f, v以上代码,只在支持二进制的编译器下才能工作。而keil不支持二进制,所以可改为以下写法:/ O1 S8 D+ h8 u
置1:! O, |! _1 ^1 X# W( k7 e) Y) P
P0 |= 0x80;    //将P0的bit7置1,同时不影响P0的其它位
& e6 |( M  K9 F1 s3 Y$ \% Y- N0 vP0 |= 0xC0;    //将P0的bit7和bit6置1,同时不影响P0的其它位9 W) }4 W5 @3 p: U( I
清0:8 g4 y0 W- s! R1 x! E
P0 &= ~0x80;    //将P0的bit7清0,同时不影响P0的其它位
1 D8 K+ S8 Q6 x) A2 RP0 &= ~0xC0;    //将P0的bit7和bit6清0,同时不影响P0的其它位
- C  n9 ?1 i3 M/ x6 ^取反:
" c# ~% ?6 q' x  @2 ~0 XP0 ^= 0x80;    //将P0的bit7取反,同时不影响P0的其它位1 B! F1 U) V/ P5 \
P0 ^= 0xC0;    //将P0的bit7和bit6取反,同时不影响P0的其它位, x1 G7 Q& Y& B7 Q8 Z

. l8 K. u( G- z6 h( ]' Z' P# D1 l- s更直观的写法是:
# [8 t- X2 R- I7 S# t5 r  N#define  BIT(X)   (1<<(X))
. \2 A8 }" b2 i+ ^, i- i) q, r" X这样,4 h3 L, d" o5 s4 n! O$ b6 v
BIT(0)会被展开为1 << 0,即0b0000 0001 << 0,即0b0000 0001,即0x01. f' d! `6 s. t+ d, [" T
BIT(1)会被展开为1 << 1,即0b0000 0001 << 1,即0b0000 0010,即0x02
; P' D" }9 g/ hBIT(0)会被展开为1 << 2,即0b0000 0001 << 2,即0b0000 0100,即0x04
* G: X7 D3 _& z9 c& A8 _: L……
$ @$ P2 h7 m3 _$ tBIT(1)会被展开为1 << 7,即0b0000 0001 << 7,即0b1000 0000,即0x80* g. i1 ?8 ?( v4 i3 Q4 v
于是,! C" M7 Z) [9 r8 J
BIT(7)|BIT(6)会被展开为0b1000 000 | 0b0100 0000,即0x80 | 0x40,即0xC0- {) G' M; f; V2 D
/ Q% S6 P8 p7 J" M1 z; j
于是,
8 u0 z2 S2 c" m& u置1:
) b' k: h; k5 N1 [& H6 wP0 |= BIT(7);                     //将P0的bit7置1,同时不影响P0的其它位
0 J& N9 B4 y& M( q' zP0 |= BIT(7)|BIT(6);          //将P0的bit7和bit6置1,同时不影响P0的其它位, V, h* `/ N" `4 M) E! `
清0:) t3 P8 s! }: C
P0 &= ~BIT(7);                 //将P0的bit7清0,同时不影响P0的其它位
  N5 `" d/ w7 R" s* }P0 &= ~(BIT(7)|BIT(6));    //将P0的bit7和bit6清0,同时不影响P0的其它位
, v$ D7 r+ B: r/ g取反:
0 n( F7 T& G; }- _9 B9 kP0 ^= BIT(7);                   //将P0的bit7取反,同时不影响P0的其它位
  m4 ?" H: R7 b1 X5 n' Q! DP0 ^= 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-7-28 01:47 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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