单片机位操作的逻辑运算详解

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机位操作的逻辑运算详解

从51单片机转到其他的芯片时,总会遇到一个非常郁闷的问题,就是其他芯片有的也许没有位操作。所以

最大的问题就是通过逻辑操作来改变一个字节的某个位。于是在这里总结一下关于位操作的一些表达式。

首先,对一个字节,8位也好,16位也好,32位也好,

只有两种操作,一种叫置位,一种叫清零。先从置位说起。

置位可以对全部位进行操作,也可以对某个位进行操作。

全部操作很简单直接赋值就ok了。我们假设一个无

符号字符型uchar为8位。且最低位为0,也就是说0-7位,而不是1-8位,那么改变值的状态只需要直接等于

就ok了

uchar a=0;

a=0xfe;

这样的话,就让a的低1-7位置1,a的0位不变

但这样做有一个问题,我每次改变数值时,还要先打开

计算器,然后设置到2进制功能,然后要把我要选择的

位输入进去,比如100,然后按16进制功能。然后计算

器显示4。我觉得这样很麻烦。咋办呢,结果前辈们就

想出了一个法子。通过位移的方法改变一个为,就变成

了这样

uchar a=0;

a = (1<<5);

这样做的话,就把a的第6位(注意是第6为不是第5位,因为数据最低位是0,而不是1,因为我总是搞混,所以也告诫大家,小心着方面的错误,如果搞混,你的数据有可能出错)置1。那么a的值用2进制表示的话那就是00100000b,那么可能又会有人问,如果我想把第2和第3位置1怎么办呢?那么你可以这样

uchar a=0;

a = (3<<1);

这样做的意思是将二进制(11)位移到第二位的地方。那么第二位,是第一个1,第三位是第二个1。同理假如让第3位和低5位为1,第4位为0,怎么办。

uchar a=0;

a = (5<<2);

这样就可以实现101位移到第3位了,以上,基本是置位的大概操作了,当然这只是一次性的。也就是说,如果我希望1次只操作一个位,比如当a=00000001b时,我希望a的第二位也置1,且第一位仍然保持1,怎么办呢?那也有办法,可以采用与操作。例如:a为1,我希望a的第2位置1,且第1位保持不变,那么

uchar a=1;

a |= (1<<1);

这样就可以达到想要的结果了。然我们来看看,这是为什么?

首先,a=1,变成二进制时,a=00000001b

然后再看下面的那个表达式

a |= (1<<1);

分析一下,看过c语言相关书籍的人大概都知道这个一

个含有复合的赋值运算符的表达式。这个式子可以拆成:a=a|(1<<1);

这样就不难理解了,(1<<1)的意思是把1左移1位,那么结果就是10b,把这个结果在和a进行或操作,我们知道或操作是同为0结果才是0。

a

00000001

或操作 00000010

结果

00000011

所以这个公式就可以使在不改变a=1的情况下,再使

a的第2位变成1,这样的结果就是a=3。这就是这个公

式的大概原理。

不仅这个,我还可以分别对两个不同的位进行操作。所

以我可以这样:

uchar a=1;

a |= (1<<2)|(1<<3)|(1<<4)|(1<<5);

这样的话,就可以把第3、4、5、6位全部置1,而且保持a的第1位不变,这个公式的最终结果是00111101b。同样,这招,在全部置位也有效。但是a原来的值就消

失了

uchar a=1;

a = (1<<2)|(1<<3)|(1<<4)|(1<<5);

那么结果只有4个1,00111100b,第1位的一就没有了

同样比如(3<<1)也可以出现在单一置位当中

uchar a=1

a |= (3<<1);

这个表达式结果为00000111b。到这,置位操作,基

本上就都在这了,大多数程序,这几个方法也够了,这

也是晚上普遍的方法,也许还有其他的方法,如果你知道,希望能够通知我。下面说说清0,清0可以用(&=~),举个例子:

uchar a=0xfe;

a &=~ (1<<4);

让我们来分析一下这个式子,首先这和上面一样,是一个含有复合的赋值运算符的表达式。拆开来以后

a=a&(~(1<<4))

这个式子比刚才要复杂一些,让我们先来看看括号最里面的(1<<4)

结果为10000b,然后我们把这个式子取反,因为a是8

位的,所以结果被转换成11101111b,然后我们在把a和这个结果进行与运算。因为与运算的规律是全1为1。

a

11111110b

与操作

11101111b

结果

11101110b

现在,我们清楚了这个结果时怎么来的了。

同样同时使两位变为0也可以通过(3<<5)来实现,比如

uchar a=0xfe;

a &=~ (3<<4);

这样也是可以得到希望的结果的,但是需要注意一下,(1<<2)|(1<<3)|(1<<4)|(1<<5),像这种一位一位的变则需要注意一下了。因为清零中先需要取反,所以如果希

望一位一位的变,则需要用括号,把结果扩起来,形成

一个值,然后再取反,才能得到想要的结果了。比如

uchar a=0xfe;

/*

注意,这样做是不对的,结果只会把第二位清0,

a &=~ (1<<2)|(1<<3)|(1<<4)|(1<<5);

*/

a &=~ ((1<<2)|(1<<3)|(1<<4)|(1<<5));

这样做才能达到希望的效果。

可能大家会想,用(&=)会得到啥样的结果呢?这我试了一下

uchar a=0xfe

a &= (1<<4);

首先(1<<4),结果是10000,然后再进行与操作

a

11111110b

与操作 00010000b

结果

00010000b

这个结果不是我们想要的,不过这个结果可以达到屏蔽我们不要的位,比如在判断中,判断最高位是否为1,可以采用这样的语句

相关文档
最新文档