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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

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

该用户从未签到

2#
发表于 2022-10-31 11:22 | 只看该作者
在嵌入式C程序中,经常使用“|”,“&”,“^”等运算符,对变量或寄存器的某一个或某几个位进行置1、清0和取反操作。. x3 W: L3 P5 x2 u
置1:, P" I- e& W" a7 m) D
P0 |= 0b1000 0000;    //将P0的bit7置1,同时不影响P0的其它位1 _- R0 A- y* W) _
P0 |= 0b1100 0000;    //将P0的bit7和bit6置1,同时不影响P0的其它位5 t1 U5 t! A9 G5 G
清0:
1 D/ n) g; ?% h& r% F% Y8 [P0 &= 0b0111 1111;    //将P0的bit7清0,同时不影响P0的其它位
  H5 e8 c' V6 a* p2 N, Y' ]' _3 @P0 &= 0b0011 1111;    //将P0的bit7和bit6清0,同时不影响P0的其它位; B* L+ t+ J% S2 P" E: a
取反:# E6 G/ z: {) ?1 P+ G% E& X$ s
P0 ^= 0b1000 0000;    //将P0的bit7取反,同时不影响P0的其它位
; L% E+ v% f2 e  x/ Y; L( [P0 ^= 0b1100 0000;    //将P0的bit7和bit6取反,同时不影响P0的其它位
- P0 J  Y6 m5 e8 a4 b  L4 C6 {+ C& p3 E: k% ?2 E% d& U
以上代码,只在支持二进制的编译器下才能工作。而keil不支持二进制,所以可改为以下写法:
3 o2 \% \( R* E置1:
+ G( D+ G- R" g+ N$ TP0 |= 0x80;    //将P0的bit7置1,同时不影响P0的其它位( S" A9 e6 c1 w. B
P0 |= 0xC0;    //将P0的bit7和bit6置1,同时不影响P0的其它位
) @: ]2 o* m* L% @7 Q  E清0:
: `. j, f9 ]# @7 X! L6 hP0 &= ~0x80;    //将P0的bit7清0,同时不影响P0的其它位& M4 R5 E' e( ~$ V1 ]
P0 &= ~0xC0;    //将P0的bit7和bit6清0,同时不影响P0的其它位6 L2 t! d, _8 V0 l
取反:5 F$ k& h. R% m5 J9 e
P0 ^= 0x80;    //将P0的bit7取反,同时不影响P0的其它位! @* ?) j  N) \# F+ F+ {- @
P0 ^= 0xC0;    //将P0的bit7和bit6取反,同时不影响P0的其它位
. L4 b, R( u( m" G" |7 E/ m  Q1 j/ K
更直观的写法是:! V6 X. J- i  }" `
#define  BIT(X)   (1<<(X))
% @' @% A, W; R- J) [3 r5 U/ ^这样,; ^3 H. Z* D9 G+ ]  d% I
BIT(0)会被展开为1 << 0,即0b0000 0001 << 0,即0b0000 0001,即0x01/ v# O2 n1 H! o7 p2 N$ O2 g# ]) V6 ^
BIT(1)会被展开为1 << 1,即0b0000 0001 << 1,即0b0000 0010,即0x02, @8 p5 G6 X0 r9 G1 c
BIT(0)会被展开为1 << 2,即0b0000 0001 << 2,即0b0000 0100,即0x04
$ D/ g9 c0 y$ R/ x% ^……, N: G, M) t0 D2 \) T" _2 M, c
BIT(1)会被展开为1 << 7,即0b0000 0001 << 7,即0b1000 0000,即0x80
; z- R/ [. H* r: X. g- m$ S于是,0 B* r+ m, U: d% l4 M; r5 P& I
BIT(7)|BIT(6)会被展开为0b1000 000 | 0b0100 0000,即0x80 | 0x40,即0xC01 Y( n% g2 ~4 {, l& Y

: ]- ?( z: U2 Y0 a* Y+ \6 n, \. a于是,5 P% b9 G' |7 z, t) i) S
置1:" F. k* P) w8 t; w- r
P0 |= BIT(7);                     //将P0的bit7置1,同时不影响P0的其它位
' K" _3 K, g  m+ S3 A- R' {P0 |= BIT(7)|BIT(6);          //将P0的bit7和bit6置1,同时不影响P0的其它位. |% E: D: u9 ?" h' I, J
清0:( N7 f+ j( e" `! m+ F
P0 &= ~BIT(7);                 //将P0的bit7清0,同时不影响P0的其它位
% @% K" ], o/ N% f( PP0 &= ~(BIT(7)|BIT(6));    //将P0的bit7和bit6清0,同时不影响P0的其它位. {+ c4 ?+ }. v, \! _$ x/ K
取反:! h1 E! W( I# ]7 @6 w+ {3 t
P0 ^= BIT(7);                   //将P0的bit7取反,同时不影响P0的其它位7 R/ U1 O) I' i- Q4 \# q
P0 ^= 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-6-18 05:23 , Processed in 0.062500 second(s), 23 queries , Gzip On.

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

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

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