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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

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

该用户从未签到

2#
发表于 2022-10-31 11:22 | 只看该作者
在嵌入式C程序中,经常使用“|”,“&”,“^”等运算符,对变量或寄存器的某一个或某几个位进行置1、清0和取反操作。
. v3 A0 a4 V% s  g; f置1:* M2 w; b3 r) H& w: o& W! x
P0 |= 0b1000 0000;    //将P0的bit7置1,同时不影响P0的其它位# B7 q4 B5 s  z2 S) y# E4 w
P0 |= 0b1100 0000;    //将P0的bit7和bit6置1,同时不影响P0的其它位; m: b6 W  u9 k+ G" s, S
清0:. c3 N& U) O* ~) H& [! \* T+ V
P0 &= 0b0111 1111;    //将P0的bit7清0,同时不影响P0的其它位1 q1 A+ i+ F. W1 v* r" v. m7 [
P0 &= 0b0011 1111;    //将P0的bit7和bit6清0,同时不影响P0的其它位, v4 ?2 U2 ?/ A! w
取反:# j! h: y0 e. A3 Y  a( Q
P0 ^= 0b1000 0000;    //将P0的bit7取反,同时不影响P0的其它位0 f" A: y  B( K- ?
P0 ^= 0b1100 0000;    //将P0的bit7和bit6取反,同时不影响P0的其它位8 W8 ?: B1 T! H0 e  x

" Y  t) G. u* A+ ]以上代码,只在支持二进制的编译器下才能工作。而keil不支持二进制,所以可改为以下写法:
+ X3 M& p7 ^+ |置1:8 F" Q3 g) x) s% x2 V
P0 |= 0x80;    //将P0的bit7置1,同时不影响P0的其它位  g( P9 \: |% Z7 H/ m2 n
P0 |= 0xC0;    //将P0的bit7和bit6置1,同时不影响P0的其它位! k7 |& E0 J  q
清0:5 l7 C. D7 P+ Z; Q/ p
P0 &= ~0x80;    //将P0的bit7清0,同时不影响P0的其它位
; n# C% J* f: h2 r* Y" G' YP0 &= ~0xC0;    //将P0的bit7和bit6清0,同时不影响P0的其它位. d1 O+ M$ y- ^0 A
取反:* A8 z4 d! o& G$ E7 b. s
P0 ^= 0x80;    //将P0的bit7取反,同时不影响P0的其它位  D5 w& f) d" `1 h
P0 ^= 0xC0;    //将P0的bit7和bit6取反,同时不影响P0的其它位
4 X' L9 Q0 r# {2 `9 J. k7 \% D7 j
更直观的写法是:
5 G/ U: Q! Q/ s! w# T#define  BIT(X)   (1<<(X))
7 V$ w4 p% `" g+ ]这样,
. r# L5 d% k- E  F& K/ X9 WBIT(0)会被展开为1 << 0,即0b0000 0001 << 0,即0b0000 0001,即0x01# \0 h( Q6 Y+ r
BIT(1)会被展开为1 << 1,即0b0000 0001 << 1,即0b0000 0010,即0x02. \; m2 a0 l" G6 `! |! W
BIT(0)会被展开为1 << 2,即0b0000 0001 << 2,即0b0000 0100,即0x04. C6 F6 c* x! M
……" B# S, t/ t. i6 ^/ L
BIT(1)会被展开为1 << 7,即0b0000 0001 << 7,即0b1000 0000,即0x80
* z# [+ W8 S5 g, C于是,$ d' A8 i/ y# \- t5 W
BIT(7)|BIT(6)会被展开为0b1000 000 | 0b0100 0000,即0x80 | 0x40,即0xC0% ]3 j- y$ T) ^: `
( W) e3 d' a, ]3 i+ z) H; ~+ t
于是,
% A, N0 B% ^' u# k' x置1:* y3 T0 m! Y: G3 W' b
P0 |= BIT(7);                     //将P0的bit7置1,同时不影响P0的其它位
2 [  v7 x, H- N( F8 \1 X  R' UP0 |= BIT(7)|BIT(6);          //将P0的bit7和bit6置1,同时不影响P0的其它位- ?& c8 ^' d9 l4 C. }8 ?# W
清0:
/ Z0 ?* }  W: m' S7 n$ D, KP0 &= ~BIT(7);                 //将P0的bit7清0,同时不影响P0的其它位- |! y0 E5 F3 p! x, D
P0 &= ~(BIT(7)|BIT(6));    //将P0的bit7和bit6清0,同时不影响P0的其它位3 l+ \2 h: P0 k% Q2 X
取反:* R- i0 g& H7 f8 ~  g9 _
P0 ^= BIT(7);                   //将P0的bit7取反,同时不影响P0的其它位
5 ]( u' }  k5 e- J5 z! GP0 ^= 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-10-8 14:20 , Processed in 0.140625 second(s), 24 queries , Gzip On.

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

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

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