找回密码
 注册
查看: 278|回复: 3
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

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

该用户从未签到

2#
发表于 2022-10-31 11:22 | 只看该作者
在嵌入式C程序中,经常使用“|”,“&”,“^”等运算符,对变量或寄存器的某一个或某几个位进行置1、清0和取反操作。
! S8 H) A/ Z% T8 y$ O, x置1:
  q' V- F" A1 U5 i  \3 U9 cP0 |= 0b1000 0000;    //将P0的bit7置1,同时不影响P0的其它位* w* ~3 q$ d& R9 b
P0 |= 0b1100 0000;    //将P0的bit7和bit6置1,同时不影响P0的其它位( \) |) z( E! l7 C# z
清0:1 h3 [% ^1 G2 Q7 @1 O+ A5 E
P0 &= 0b0111 1111;    //将P0的bit7清0,同时不影响P0的其它位
% F* o& h" ^7 O) |P0 &= 0b0011 1111;    //将P0的bit7和bit6清0,同时不影响P0的其它位
* q( U) e6 J! G0 a! V( F取反:
: L% r5 T" v9 uP0 ^= 0b1000 0000;    //将P0的bit7取反,同时不影响P0的其它位
% {! N& m$ N/ }3 E& _7 \P0 ^= 0b1100 0000;    //将P0的bit7和bit6取反,同时不影响P0的其它位
% ]0 A7 k- U  [. e$ R, g- \; O+ Z. d; f7 D  X
以上代码,只在支持二进制的编译器下才能工作。而keil不支持二进制,所以可改为以下写法:+ @/ H4 B. J( K# Q; y
置1:9 g% h, @/ H9 R) I! C0 F
P0 |= 0x80;    //将P0的bit7置1,同时不影响P0的其它位9 {, p6 F1 ?) O5 ]
P0 |= 0xC0;    //将P0的bit7和bit6置1,同时不影响P0的其它位$ x0 W- {" P+ O9 H8 n1 Q3 R
清0:
" R4 l! r  Z% hP0 &= ~0x80;    //将P0的bit7清0,同时不影响P0的其它位- I2 b7 g" Y1 j( i
P0 &= ~0xC0;    //将P0的bit7和bit6清0,同时不影响P0的其它位
) l# T& S; F. X7 @取反:3 X' a1 C/ K2 B/ v
P0 ^= 0x80;    //将P0的bit7取反,同时不影响P0的其它位
" z/ c! `6 w4 V; a, b/ Q7 VP0 ^= 0xC0;    //将P0的bit7和bit6取反,同时不影响P0的其它位
9 H; |/ f! _2 V
7 J, L. A* G1 M% q; [更直观的写法是:% f8 G1 r1 Z: {+ D- m: x8 f, G
#define  BIT(X)   (1<<(X))
+ Y+ a1 a7 {3 v  X! h9 X这样,2 }0 ~5 J' P  [8 H4 p8 |% s
BIT(0)会被展开为1 << 0,即0b0000 0001 << 0,即0b0000 0001,即0x01
1 H( |! \4 _* ]8 D' M3 PBIT(1)会被展开为1 << 1,即0b0000 0001 << 1,即0b0000 0010,即0x024 u6 g9 ?  ^0 k& K
BIT(0)会被展开为1 << 2,即0b0000 0001 << 2,即0b0000 0100,即0x04
' K; }! W! B- `5 a3 K……  H3 e% ^- {7 ~$ B. S0 G
BIT(1)会被展开为1 << 7,即0b0000 0001 << 7,即0b1000 0000,即0x80
; V$ |' B1 ~0 x于是,- X, m' \0 X% o# K7 F- h1 z
BIT(7)|BIT(6)会被展开为0b1000 000 | 0b0100 0000,即0x80 | 0x40,即0xC0& Y  e/ h' X9 w4 ^! F3 B+ ^
/ ]& V9 p, l: x) d% _; g" I
于是,2 B; q- i  b% h# N
置1:: T0 z1 u3 V$ n* h# @* q
P0 |= BIT(7);                     //将P0的bit7置1,同时不影响P0的其它位; ?% n$ P' a5 V4 l$ ^' n
P0 |= BIT(7)|BIT(6);          //将P0的bit7和bit6置1,同时不影响P0的其它位
9 x! f$ x$ s* P  ]' {2 k# P清0:
8 J! S8 E" K# |+ dP0 &= ~BIT(7);                 //将P0的bit7清0,同时不影响P0的其它位$ o; m( Y; t% }6 Q. T
P0 &= ~(BIT(7)|BIT(6));    //将P0的bit7和bit6清0,同时不影响P0的其它位  y2 D5 z! d: a: |
取反:
0 F/ ?) I$ U" w: iP0 ^= BIT(7);                   //将P0的bit7取反,同时不影响P0的其它位
5 P2 C/ B! O5 v& l4 lP0 ^= 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-5-31 09:44 , Processed in 0.078125 second(s), 24 queries , Gzip On.

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

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

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