刚开始学习STM8单片机时,看别人的代码,在设置寄存器的时候经常使用,位或、位与、左移、右移等运算,就很不理解,为什么不直接给寄存器赋值,非要搞的这么复杂。直到后来程序写的多了,才明白这样写的好处。比如我们现在要设置PB5口为输出口。首先我们需要设置PB口的方向寄存器PB_DDR。

我们要设置PB5口为输出,那么就要把DDR5位设置为1。那么要设置的寄存器PB_DDR寄存器二进制数据为 0010 0000,转换为16进制为 0x20。设置寄存器的语句为

PB_DDR = 0x20;

这样操作寄存器看起来没什么问题,也挺方便。唯一的问题就是每次要先将设置的二进制数确定好,然后再转换为16进制数,再赋值给寄存器。代码少的时候没什么感觉,但是一旦代码量比较大,要设置的寄存器比较多时,再这样操作就比较麻烦,特别是设置的寄存器值要进行改变时再去计算二进制数,在转换成16进制数,就非常麻烦。而且还要不停的查阅参考手册,来确认寄存器的每一位值。一不小心很容易设置错,排除原因的时候又很难发现。
为了方便程序的编写和维护,这时候就需要用到移位运算。还是上面的例子,要设置PB5口为输出,需要将PB_DDR寄存器的第5位设置为1,其他位不变。那么将1左移5位,第五位不就刚好是1了吗。我们来看看移位操作,首先1的二进制数为
0000 0001
将这个数左移五位,最高位移出去,最低位补0,那么,向左移动5位后,变为
0010 0000
转换为16进制数为 0x20。于是对PB_DDR寄存器的设置语句可以改为:

 PB_DDR = 1<<5;

将1左移5位,然后赋值给PB_DDR寄存器。这样从代码上一眼就能看出来这是设置PB_DDR寄存器的DDR5为1。比上面的那种操作方式看起来简洁明了。
如果要继续设置PB4为输出的时候,寄存器的设置就可以写为:

     PB_DDR = 1<<4;

这样就将PB4口设置为了输出口。这时我们发现了一个问题,当将PB4设置为输出口时寄存器的值变为 0001 0000,DDR4为0,但是又将上一步设置的DDR5的值由1 变为0了,将PB4设置为输出后,又将PB5设置为了输入,改变了设计初衷。
那么如何解决这种问题呢,就需要用到位运算。先看看位或运算和位与运算的区别:
位或运算 |: 位之间进行或运算,如果有一个位为1,结果就为1。
位与运算&:位之间进行与运算,如果有一个位为0,结果就为0。
在设置PB4的时候不希望影响到PB5位,那么就可以用位或运算,给第4位或1,不管第4位以前的值是1还是0,与1进行或运算后,第4位的值就会变成1。那么在给PB_DDR赋值时,先进行或运算.

     PB_DDR = PB_DDR | 0x10;

同样为了方便程序书写和阅读,将16进制数改为位移运算。

     PB_DDR = PB_DDR | (1<<4);

为了书写简便,可以将上面的语句简写为:

     PB_DDR |= 1<<4;

这样在操作寄存器其中一位的时候,不会影响到其他位。这时如果设置PB4、PB5为输出,可以这样写:

     PB_DDR |= 1<<4;PB_DDR |= 1<<5;

这样通过位移运算和位或运算的组合,可以很方便的设置寄存器值。 从语句上就能很清楚的看到是设置 PB_DDR寄存器的第4位和第5位为1。
如果这时候又需要将PB4口设置为输入模式,那么就需要将DDR4位由1变为0。位或运算只能将0变为1,不能将1变为0。而位与运算可以将1变为0,那么可以用位与运算实现。给PB_DDR寄存器的第4位位与0,就能将DDR4位由1变为0。
第4位为0,其他位为1二进制数为 1110 1111 转换为16进制数为0xEF。

      PB_DDR = PB_DDR & 0xEF;

这样在不影响其他位的情况下,将第4位变为了0。但是这样换算16进制也很麻烦,能不能同样用位移运算实现。但是位移运算是高位溢出后,低位自动补0。我们需要的是自动补1,那么有没有其他办法实现。我们观察设置第4位为0和第4位为1时的二进制数据
0001 0000
1110 1111
这两组数据刚好互补,那么将第4位为1其他位为0的数进行取反操作,那么得到的数刚好就是我们位与运算需要的数。
那么上面的设置语句可以改为

       PB_DDR = PB_DDR &( ~(1<<4));

将1左移4位后,先取反,让第4位变为0,其他位变为1,在和寄存器原先的值进行位与运算,那么就可以在不影响其他位的情况下,将第4位由1变为0。
上面的设置语句可以简写为:

     PB_DDR &=   ~(1<<4);

通过增加一个取反运算,就可以实现用位移运算对寄存器某一位清0。
通过上面的分析可以得出一个结论 位或 | 运算可以实现将寄存器的某一位置1,而 位与& 运算可以实现将寄存器的某一位清0。通过这几种运算符的组合,设置寄存器时就会很方便快捷。
如要将PB4设置为输出,PB5设置为输入,那么运用上面的方法,可以很轻松的写出

         PB_DDR |= 1<<4;PB_DDR &= ~(1<<5);

这时候在看用以前对寄存器的操作方法,先设置对应的二进制数为 DDR4 为1 DDR5为0 0001 0000 转换为16进制数位 0x10 设置语句为

     PB_DDR = 0x10;

明显可以发现直接设置寄存器操作起来麻烦,程序可读性很差。要修改寄存器的值时很费劲。
所以在以后代码编写中,推荐大家多用位或、位与、左移、右移、取反这些运算的组合方式进行寄存器设置。

STM8学习笔记---寄存器操作之位或和位与运算相关推荐

  1. crh寄存器_牛人的STM32学习笔记(寄存器版本).doc

    牛人的STM32学习笔记(寄存器版本) 一.GPIO口的配置 STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个双向IO组成.并且没个IO口均可配置成8种模 ...

  2. 学习笔记:操作系统启动过程

    学习笔记:操作系统启动过程 参考资料: 1.<操作系统真象还原>郑钢 2.<操作系统引导探究> 谢煜波 操作系统启动过程 按下电源后: 电源键连接的电信号线发送一个电信号给主板 ...

  3. 嵌入式学习笔记——寄存器实现控制LED小灯

    文章目录 前言 GPIO通用输出模式 初始化LED小灯的GPIO 原理图 初始化代码 初始化的效果 功能函数封装 直接分开宏定义两个 使用条件运算符 封装函数实现简单的功能 KEIL MDK一些技巧 ...

  4. STM8学习笔记----普通IO口模拟串口功能

    串口在产品应用中很常见,但是单片机的默认带的串口往往比较少,有时候就会出现串口不够用,所以就想着能不能用普通IO口模拟串口来实现串口的功能. 要模拟串口首先要清楚串口数据传输过程中的原理. 常用的串口 ...

  5. memcached高速缓存学习笔记002---telnet操作memcached

    memcached高速缓存学习笔记002---telnet操作memcached 停止memcached  memcached.exe  -d stop 停止 memcached.exe -p 112 ...

  6. Apifox 学习笔记 - 前置操作

    Apifox 学习笔记 - 前置操作 设置 Content-Length 参考资料 设置 Content-Length Content-Type: application/x-www-form-url ...

  7. js学习笔记82——操作内联样式

    js学习笔记82--操作内联样式 通过js修改元素的样式 查参考手册 内联样式 读取元素的样式 看如下代码 <!DOCTYPE html> <html lang="en&q ...

  8. 深度学习笔记(三)计算图及其导数运算方法

    通过上文logistic regression的讲解知道,正向运算可以计算输出结果,而反向运算可以计算梯度或导数,从而调整参数. 通过简单的运算式引出计算图的组成,从而引出深度学习中前向传播和反向传播 ...

  9. STM8学习笔记---如何在程序中确定寄存器名称

    在刚开始写程序的时候,在程序中需要设置寄存器的时候,往往不知道寄存器名称怎么写才是对的,这时候可以通过头文件来查看寄存器是如何调用的.在打开一个IAR工程文件,打开main.c文件,然后再引用的头文件 ...

最新文章

  1. 苏州之行的点滴感悟---活动中老师的言论以及火车上遇到的人
  2. 2年质保期刚过就翘辫子,这是什么骚设计?
  3. - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
  4. mysql-5.7.24 linux下载_Linux下安装mysql-5.7.24
  5. 一款开源免费且快速,高效和安全的跨平台备份程序:Restic使用教程
  6. java编程思想3感悟(4)---被隐藏的具体实现
  7. 【声传播】——多层介质平面波的反射问题
  8. 设计一个采用udp实现数据传输的程序_TCP/IP、UDP、HTTP、MQTT、CoAP这五种物联网协议...
  9. 浅谈VMD---变分模态分解
  10. GitHub常用优秀开源Android项目
  11. RDKit入门教程(1)——RDKit 安装 (Win10)
  12. 有负数c语言除法,C语言负数的除法和求余运算
  13. 如何在图片上添加边框和文字
  14. 注册一个域名需要多少钱_购买一个域名要多少钱?
  15. 干货:自助分析BI产品实践指南
  16. 为什么很多聪明的人,却一辈子在社会最底层?
  17. !function(){}() 什么意思
  18. 正则匹配所有的a标签
  19. blast java_使用python实现BLAST
  20. jason by gson复习

热门文章

  1. iOS开发中的单元测试(三)——URLManager中的测试用例解析
  2. 国内三大PT(Private Tracker)站分析
  3. poj 3167(KMP+树状数组)
  4. 用matlab做数据处理的几个小坑
  5. 查看目录中的内容及权限
  6. Linux centosVMware shell编程 for循环、while循环、break跳出循环、continue结束本次循环、exit退出整个脚本...
  7. 慕课学习--DNS的作用
  8. 第三章:3.8 登陆 Django 默认后台
  9. LinkedList实现类
  10. LAMP 补充----非原创