task8知识点总结

第一讲:位操作符
1.位与&:
注意:位与是一个&,逻辑与是两个&(&&)。
①:真值表:1&1=1  1&0=0  0&0=0  0&1=0
通过真值表可以看出,只有当1&1时才是1,其余情况均为0。
②:位与特点:与1位与无变化,与0位与变为0

2.位或|:
注意:位或是一个|,逻辑或是两个|(||)。
①:真值表:1|0=1  1|1=1  0|0=0  0|1=1
通过真值表可以看出,只有当0|0时才是0,其余情况均为1。
②:位或特点:与1位或变为1,与0位或无变化

3.位取反~:
注意:位取反是~,逻辑取反是!
0取反变为1,非0值取反变为0。
特殊情况:当任意值按位取反后再取反时,会等于它本身。但当任意值按逻辑取反后再取反时,只会等于1,不会等于它本身。

4.位异或^:
①:真值表:
1^1=0  0^0=0  1^0=1  0^1=1
通过真值表可以看出,2个数相等结果为0,不等结果为1。
②:位异或特点:与1位异或会取反,与0位异或无变化。

5.左移位<<与右移位>>:
对于无符号数,左移时右侧补0(相当于逻辑移位)
对于无符号数,右移时左侧补0(相当于逻辑移位)
对于有符号数,左移时右侧补0(叫算术移位,相当于逻辑移位)
对于有符号数,右移时左侧补符号位(如果为正数补0,负数补1,叫算术移位)(保证不会因为右移导致符号改变)

第二讲:位与位或位异或在操作寄存器时的特殊作用 
1.寄存器的特点是按位进行规划和使用。要求是在设定特定位时不能影响其他位
2.操作步骤:读-写-改三部曲。首先,将寄存器的初值读取出来,然后对想要改变的特定位进行修改,最后,将改好的新值重新输入到寄存器中。
原因:
寄存器的读和写都要整体操作,当想要改变特定位时,不能只对这些位进行修改,不行把整个寄存器的值重新设置一遍。
3.特定位清零用&
①根据位与的特点:
与1位与无变化,与0位与变为0。
当希望改变寄存器中某些特定位的值为0而不影响其他位时,可以使用位与操作。
例如,原寄存器初值位:0xAAAA,希望讲bit4~7位清零,可以与上0xFF0F,运算后得出寄存器值为0xAA0A。

4.特定位置1用|
①根据位或的特点:
与1位或变为1,与0位或无变化。
当希望改变寄存器中某些特定位的值为1而不影响其他位时,可以使用位或操作。
例如,原寄存器初值位:0xAAAA,希望讲bit4~7位清零,可以与上0x00F0,运算后得出寄存器值为0xAAFA。

5.特定位取反用^
①根据位异或的特点:
与1位异或会取反,与0位异或无变化。
当希望改变寄存器中某些特定位的值取反而不影响其他位时,可以使用位或操作。
例如,原寄存器初值位:0xAAAA,希望讲bit4~7位取反,可以与上0x00F0,运算后得出寄存器值为0xAA5A。

6.实际运用
位或,位与:可以对GPIO的寄存器的值进行设置,实现对LED灯的开和关。
位异或:可以对GPIO的寄存器的值进行取反,实现对LED灯的电平翻转,达到闪烁的效果。

第三讲:运用位运算构建特定二进制数
有两种方法可以构建特定的二进制数
①通过工具或计算机直接构建出二进制数,然后写入寄存器中。
优点:方法比较直接,难度较小,操作方法不太困难。
缺点:依赖工具,且数据不直观,可读性较差。

②通过代码用位操作(主要是移位和位取反)来构建特定的二进制数。
1.通过移位来构建特定位为1的二进制数:
(适合用于1较少的二进制数)
方式:可以将一个二进制数通过拆分为多个零散的二进制数,并进行移位后通过或位或运算将二进制数拼接起来,构成一个完整的二进制数。
例子:需要构建一个数为0xF0F0,则可以通过将0xF先左移4位变为0xF0,再用另一个0xF左移12位变为0xF000,然后将两个数用位或运算就可以得出结果。

2.结合位取反构建特定位为0的二进制数:(适合用于0较少的二进制数)
方式:先运用移位的方式将1移到原来0应该在的位置,最后再运用位取反操作就可以得到期望的二进制数。
例子:
需要构建一个数为0xF0FF,则可以通过将0xF左移8位变为0xF00,然后再进行位取反操作将0x0F00变为0xF0FF。

3.方法使用场合
一.当想要的数少位为1,大部分为0时,可以通过多次将1左移来实现。
二.当想要的数少位为0,大部分为1时,可以先构建器位反数,然后再用位取反获得。
三.当想要的数有多个连续的1或者0时,可以多段移位后再相与得到结果。

优点:不依赖于工具,逻辑性较强,可读性较强。
缺点:操作方式较为繁琐,且方法不是很直接。

第四、五讲:位运算实战演练
①:给定一个整型数a,设置a的bit3,保证其他位不变。
解析:通过前面的知识很容易得知,只需使用左移和位或操作即可。
答案:a|=(1<<3)

②:给定一个整型数a,设置a的bit3~bit7,保证其他位不变。
解析:方式与①相似。
答案:a|=(0x1f<<3)

③:给定一个整型数a,清除a的bit15,保证其他位不变。
解析:首先移位后取反,使得除了bit15外全为1,然后进行与操作将bit15清除。
答案:a&=(~(1<<15))

④:给定一个整型数a,清除a的bit15~bit23,保证其他位不变。
解析:方式与③相似
答案:a&=(~(0x1ff<<15))

⑤:给定一个整型数a,取出a的bit3~bit8。
解析:首先通过移位和取反再位与运算将bit3~bit8保留下来,然后再右移取出bit3~bit8的值。
答案:a&=(0x3f<<3)   a>>=3

⑥:用C语言给一个寄存器的bit7~bit17赋值937(其余位不收影响)
解析:首先因为无法知道原来bit7~bit17存有什么值,所以先将其清零,然后再写入937。
答案:a&=(~(0x7ff<<7))   a|=(937<<7)

⑦:用C语言给一个寄存器的bit7~bit17中的值加上17(其余位不收影响)
解析:首先需要将bit7~bit17中的值取出后,再加上17,然后将a中的对应位清除,最后再将加完后的值写入。
答案:temp=a&(0x7ff<<7)   temp>>=7  temp+=17   a&=(~(0x7ff<<7))   a|=temp<<7

⑧:用C语言给一个寄存器的bit7~bit17赋值937,同时给bit21~bit25赋值17(其余位不收影响)
解析:首先将bit7~bit17赋值937后,再用位或操作将bit21~bit25赋值为17。
答案:解法1:a&=(~(0x7ff<<7))  a|=(937<<7)  a&=(~(0x1f)<<21)  a|=(17<<21)
解法2(推荐):a&=~((0x7ff<<7))| (0x1f)<<21)  a|=((937<<7) | (17<<21))

第六讲:用宏定义来完成位运算操作
1.意义:通过宏定义可以使得代码的逻辑性更强,可读性更好,程序的运行效率更加高效,且在移植时更加方便。

2.题目讲解
①直接用宏定义来置位、复位(最右边为第1位)
题目一:将32位的数x的第n位置位

解析:通过之前的学习得知可以通过位与、位或、位取反的方式完成置位、复位操作。只需将求中的具体参数改成宏定义中的形参即可。
答案:置位:  #define   SET_BIT(x,n)     (x|(1U<<(n-1)))
注意:在宏定义中,需要将移位的数设置为无符号,放置右移时带有符号位影响结果。且在定义的最外面一定要加括号,防止编译时出现错误。
复位:  #define    RESET_BIT(x,n)      (x&(~(1U<<(n-1))))

题目二:用宏定义将32位数的第n位到第m位置位
解析:方法与题目一类似,但是需要自己设定移位的数字,可以先将全部位置1后,右移32-(m-n+1),剩余的位数就是所需要的位数,然后就通过位或操作实现置位。
答案:   #define    SET_BITS(x,n,m)       (x|((~0U)>>(32-(m-n+1)<<n-1)))

②:截取变量的部分连续位
解析:通过四、五讲的⑤题的方法可以得出本题的解题思路。首先将需要提取的位保留下来,其他位全部置0,然后再右移对应的位来提取连续位。
答案:     #define   GET_BITS(x,n,m)    (x&~(~0U<<(m-n+1)<)<(n-1) >>(n-1))
注意:此处的特定位保留方法与题目二不同,题目二是必须在特定宽度下才能使用(例如32位),而这里的方法使用于所有宽度。首先将所有位置1,然后所需要的特定位数通过左移的方式来补0,再通过取反来实现将特定位数个数置1,然后再左移来移到对应的位置来保留特定位,最后右移来提取特定位。

总结:通过本章学习可以让我对寄存器的操作有了更加深刻的认识,了解到了寄存器的工作原理可以让我在调试程序的过程中更加得心应手。可以从最底层的操作方式来操控单片机,和库函数结合一起使用能让自己的水平有了进一步的提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值