一、位操作概述

针对MCU的嵌入是开发中经常涉及到寄存器的操作,例如GPIO配置低寄存器GPIOx_CRL(共32个bit),有时需要改变其中的一位或者几位bit值,同时不能影响其它bit位的值。

例如,需要设置第0位bit=1时,不能简单的设置为:GPIOx_CRL=0x01  ,这样的方法会使得低配置寄存器GPIOx_CRL的其它比特位都置为0。

对于二进制位操作来说:

不管该位原来的值是0还是1,它跟0进行&运算,得到的结果都是0,而跟1进行&运算,将保持原来的值不变;

不管该位原来的值是0还是1,它跟1进行|运算,得到的结果都是1,而跟0进行|运算,将保持原来的值不变。

正确的方法是:

GPIOx_CRL=GPIOx_CRL | 0x01      或者        GPIOx_CRL |= 0x01

或者使用如下方法更加清晰,第几位需要置1就将0x01左移几位。

GPIOx_CRL  |=   (0x01 << 0);

二、位操作具体用法-提取、清零、置1、判断

位操作的用法可以分为四类:

1、寄存器数据的位、字节读取操作:1)提取某一个字节,2)提取某一位;

2、寄存器数据的位、字节清零操作:1)清零某一个字节,2)清零某一位;

3、寄存器数据的位、字节置1操作:  1)将某一个字节置1, 2)将某一位置1;

4、判断某一位或某几位连续的值:1)判断某一位的值,2)判断某几位连续位的值。

1、寄存器数据的位、字节读取操作

1)提取某一个字节

#include <stdio.h>
#include <stdlib.h>#define    GET_LOW_BYTE0(x)    ((x >>  0) & 0x000000ff)  /* 获取第0个字节 */
#define GET_LOW_BYTE1(x)    ((x >>  8) & 0x000000ff)  /* 获取第1个字节 */
#define GET_LOW_BYTE2(x)    ((x >> 16) & 0x000000ff)  /* 获取第2个字节 */
#define GET_LOW_BYTE3(x)    ((x >> 24) & 0x000000ff)  /* 获取第3个字节 */int main()
{unsigned int a=0x44332211;printf("0x%x的第0个字节为:0x%x\n",a,GET_LOW_BYTE0(a));printf("0x%x的第1个字节为:0x%x\n",a,GET_LOW_BYTE1(a));printf("0x%x的第2个字节为:0x%x\n",a,GET_LOW_BYTE2(a));printf("0x%x的第3个字节为:0x%x\n",a,GET_LOW_BYTE3(a));return 0;
}

2)提取某一位

#include <stdio.h>
#include <stdlib.h>#define    GET_BIT(x, bit) ((x & (1 << bit)) >> bit)   /* 获取第bit位 */int main()
{unsigned int a=0x51;printf("0x%x的对应的二进制是:%x %x %x %x %x %x %x %x \n",a,GET_BIT(a,7),GET_BIT(a,6),GET_BIT(a,5),GET_BIT(a,4),GET_BIT(a,3),GET_BIT(a,2),GET_BIT(a,1),GET_BIT(a,0));printf("0x%x的第0位的值是:%x\n",a,GET_BIT(a,0));printf("0x%x的第1位的值是:%x\n",a,GET_BIT(a,1));printf("0x%x的第2位的值是:%x\n",a,GET_BIT(a,2));printf("0x%x的第3位的值是:%x\n",a,GET_BIT(a,3));printf("0x%x的第3位的值是:%x\n",a,GET_BIT(a,4));printf("0x%x的第3位的值是:%x\n",a,GET_BIT(a,5));printf("0x%x的第3位的值是:%x\n",a,GET_BIT(a,6));printf("0x%x的第3位的值是:%x\n",a,GET_BIT(a,7));return 0;
}

2、寄存器数据的位、字节清零操作

1)清零某一个字节

#include <stdio.h>
#include <stdlib.h>#define    CLEAR_LOW_BYTE0(x)  (x &= 0xffffff00)  /* 清零第0个字节 */
#define CLEAR_LOW_BYTE1(x)  (x &= 0xffff00ff)  /* 清零第1个字节 */
#define CLEAR_LOW_BYTE2(x)  (x &= 0xff00ffff)  /* 清零第2个字节 */
#define CLEAR_LOW_BYTE3(x)  (x &= 0x00ffffff)  /* 清零第3个字节 */int main()
{unsigned int a=0x44332211;unsigned int b=0x44332211;unsigned int c=0x44332211;unsigned int d=0x44332211;printf("0x44332211的第0个字节清零后的值是:%#.8x\n",a,CLEAR_LOW_BYTE0(a));printf("0x44332211的第1个字节清零后的值是:%#.8x\n",b,CLEAR_LOW_BYTE1(b));printf("0x44332211的第2个字节清零后的值是:%#.8x\n",c,CLEAR_LOW_BYTE2(c));printf("0x44332211的第3个字节清零后的值是:%#.8x\n",d,CLEAR_LOW_BYTE3(d));return 0;
}

2)清零某一位

#include <stdio.h>
#include <stdlib.h>#define    CLEAR_BIT(x, bit)   (x &= ~(1 << bit))   /* 清零第bit位 */int main()
{unsigned int a0=0x81;unsigned int a1=0x82;unsigned int a2=0x84;unsigned int a3=0x88;printf("0x81的第0个bit清零后的值是:%#.2x\n",a0,CLEAR_BIT(a0, 0));printf("0x82的第1个bit清零后的值是:%#.2x\n",a1,CLEAR_BIT(a1, 1));printf("0x84的第2个bit清零后的值是:%#.2x\n",a2,CLEAR_BIT(a2, 2));printf("0x88的第3个bit清零后的值是:%#.2x\n",a3,CLEAR_BIT(a3, 3));return 0;
}

3、寄存器数据的位、字节置1操作

1)将某一个字节置1

#include <stdio.h>
#include <stdlib.h>#define    SET_LOW_BYTE0(x)  (x |= 0x000000ff)    /* 第0个字节置1 */
#define SET_LOW_BYTE1(x)  (x |= 0x0000ff00)    /* 第1个字节置1 */
#define SET_LOW_BYTE2(x)  (x |= 0x00ff0000)    /* 第2个字节置1 */
#define SET_LOW_BYTE3(x)  (x |= 0xff000000)    /* 第3个字节置1 */int main()
{unsigned int a0=0x11111111;unsigned int a1=0x11111111;unsigned int a2=0x11111111;unsigned int a3=0x11111111;printf("0x11111111的第0个字节置1后的值是:%#.2x\n",a0,SET_LOW_BYTE0(a0));printf("0x11111111的第1个字节置1后的值是:%#.2x\n",a1,SET_LOW_BYTE1(a1));printf("0x11111111的第2个字节置1后的值是:%#.2x\n",a2,SET_LOW_BYTE2(a2));printf("0x11111111的第3个字节置1后的值是:%#.2x\n",a3,SET_LOW_BYTE3(a3));return 0;
}

2)将某一位置1

#include <stdio.h>
#include <stdlib.h>#define    SET_BIT(x, bit) (x |= (1 << bit))    /* 置位第bit位 */int main()
{unsigned int a0=0x10;unsigned int a1=0x10;unsigned int a2=0x10;unsigned int a3=0x10;printf("0x10的第0个bit置1后的值是:%#.2x\n",a0,SET_BIT(a0, 0));printf("0x10的第1个bit置1后的值是:%#.2x\n",a1,SET_BIT(a1, 1));printf("0x10的第2个bit置1后的值是:%#.2x\n",a2,SET_BIT(a2, 2));printf("0x10的第3个bit置1后的值是:%#.2x\n",a3,SET_BIT(a3, 3));return 0;
}

4、判断某一位或某几位连续的值

1)判断某一位的值

#include <stdio.h>
#include <stdlib.h>#define    SET_BIT(x, bit) (x |= (1 << bit))    /* 置位第bit位 */int main()
{unsigned int a=0x66;//二进制 01100110int i;for(i=0;i<8;i++){if(a&(1<<i))//关键点{printf("0x66二进制的bit%d位的值是1\n",i);}else{printf("0x66二进制的bit%d位的值是0\n",i);}}return 0;
}

要判断第几位的值,if里就左移几位(不要移过头了)。在针对MCU的嵌入式编程中,可通过这样的方式来判断寄存器的状态位是否被置位。

2)判断某几位连续位的值

#include <stdio.h>
#include <stdlib.h>/* 获取第[n:m]位的值 */
#define BIT_M_TO_N(x, m, n)  ((unsigned int)(x << (31-(n))) >> ((31 - (n)) + (m)))int main()
{unsigned int a=0xAA;//二进制 10101010unsigned int value=0;int i,j;for(i=0,j=1;i<8,j<8;i++,j++){value=BIT_M_TO_N(a, i, j);switch(value){case 0:printf("0xAA的bit[%d,%d]位是:00\n",i,j);break;case 1:printf("0xAA的bit[%d,%d]位是:01\n",i,j);break;case 2:printf("0xAA的bit[%d,%d]位是:10\n",i,j);break;case 3:printf("0xAA的bit[%d,%d]位是:11\n",i,j);break;}}return 0;
}

这只是一个查询连续2个状态位的例子,当连续bit位大于2时,会有多种状态,这种情况下就可以用这种方法来取出状态位,再去执行相应操作。

下一篇文章结合STM32F103介绍关于具体寄存器的操作。

C语言位操作 - bit 、byte的清零,置1,提取,判断相关推荐

  1. 常用的位操作:置位、清零与测试

    以下程序可用于把某个位置位.清零或测试某位为0还是1: #include <stdio.h> #include <stdbool.h>int setbit(int num, i ...

  2. 同步电路出现异步清零可以吗_异步清零和同步清零置数区别

    [相关知识]:中规模集成计数器的功能表阅读.反馈清零法和反馈置数法的应用等.本文引用地址:http://www.eepw.com.cn/article/201610/311031.htm [解题方法] ...

  3. 常见位操作:获取,设置,清零

    1 /*常见位操作:获取,设置,清零 2 * 3 * */ 4 public class BitGet { 5 /* 6 * 该函数实现获取功能 7 * 先将1左移动i位,左移动0位变成了000000 ...

  4. c语言用位运算将一个数清零,C语言学习笔记_位运算

    C语言学习笔记_位运算 知识点记录 基本位运算 按位与:全1为1,见0为0:与1相与无变化,与0相与变为0:可用于特定位清零 按位或:见1为1,全0为0:与1相或变为1,与0相或无变化:可用于特定位置 ...

  5. 按键清零是0xff吗c语言,msp40_c语言.docx

    msp40_c语言 实验目的巩固编写和调试C语言程序的方法:了解简单电路的控制方法实验任务简单电子表的设计用8 个发光二极管以秒为单位显示时间值,按下面步骤完成一个简单电子表的设计:1)硬件连线:用跳 ...

  6. 8.裸板--C语言下的寄存器的读写置位清零操作

    从CPU的角度来看,外设的寄存器跟通用寄存器操作一样,对它们的地址进行读写移位等操作即可进行配置读取写入等动作. 通用寄存器有15个 寄存器名字 Reg# APCS 意义 R0 a1 工作寄存器 R1 ...

  7. 秒表清零c语言程序,显示的秒表 C语言程序

    显示的秒表 C语言程序 源程序代码: //名称:用1602LCD设计的秒表 //说明:首先按下K1键时开始计时,自此按下时暂停,第三次按下时继续累积计时,再次按下时停止计时,K2键用于清零秒表. // ...

  8. 存储器块清零c语言版,存储器块清零实验报告

    有关单片机存储器块清零实验的试验报告 存储器块清零实验报告 班级: 11级计科班 姓名:苏靖 学号:1120070544 日期:2012-12-19 一.实验目的: 1.掌握存储器读写方法 2.了解存 ...

  9. 存储器块清零c语言版,存储器块清零实验

    版权所有 实验一 存储器块清零 一.实验目的 1.掌握存储器读写方法: 2.了解存储器的块操作方法. 二.实验说明 本实验指定某块存储器的起始地址和长度,要求能将其内容清零.通过该实验学生可以了解单片 ...

最新文章

  1. 如何利用webmin在Linux主机中添加网站
  2. IM实现联系人及联系人分组的数据库设计
  3. head first python(第三章)–学习笔记
  4. mysql 2003 10038_关于MySql10038错误的完美解决方法(三种)
  5. Gitbook中有序列表不能正常显示的解决办法
  6. Golang 位向量
  7. python字符串_Python字符串
  8. 【海康威视】2022届超新星-AI算法工程师-萤石-暑假实习面经
  9. hudi系列-文件压缩(compaction)
  10. 硬盘数据恢复的原理是什么?清空、格式化数据真的就没有了吗?
  11. dhcp二层中继和三层中继
  12. 改变世界前,先改变自己
  13. 神话是这样打破的-南阳理工学院
  14. 当PLSQL一直打不开怎么办
  15. 第8期——STA接入过程
  16. 手写板输入乱码的解决(只是设置的问题)
  17. [CVPR2022] Cross-Model Pseudo-Labeling for Semi-Supervised Action Recognition
  18. IP数据包 标识 标志 片偏移
  19. linux chown命令文件,Linux chown命令详细介绍和使用实例(改变文件或目录的所有者)...
  20. 自动驾驶(六十五)---------ROS学习笔记(1)

热门文章

  1. 抓包都不会 你还想爬美女图??
  2. PHP的内码转换函数 mb_convert_encoding()
  3. ubuntu下设置开机自启守护进程
  4. luogu1594 护卫队
  5. 20200117开会:项目之星:总结
  6. Python+Selenium — 爬取京东搜索商品页数据
  7. EDG夺冠,用Python分析一波:粉丝都炸锅了
  8. JS实现单张图片闪烁效果
  9. 黄金 白银T+D 盈利计算器
  10. 什么是GMT,什么是UTC - GMT,UTC是什么意思啊?