嵌入式linux寄存器位运算,嵌入式linux C语言(一)――位运算的使用
嵌入式linux C语言(一)――位运算的使用
ARM是内存与IO统一编址,SoC中有很多控制寄存器,通过对这些寄存器进行位运算对这些控制寄存器进行设置,进而控制外设功能。在修改寄存器某些位的过程中不能修改其他的位。
一、位运算基础
C语言基本的位操作符有与、或、异或、取反、左移、右移六种位运算符。如下表所示:
符号
描述
运算规则
&
与
两个位都为1时,结果才为1
|
或
两个位都为0时,结果才为0
^
异或
两个位相同为0,相异为1
~
取反
0变1,1变0
<<
左移
各二进位全部左移若干位,高位丢弃,低位补0
>>
右移
各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
位运算使用说明:
1、六种位运算只能用于整型数据,对float和double类型进行位操作会被编译器报错。
2、逻辑运算与位运算的区别:逻辑运算是将参与运算的两个表达式整体的结果进行逻辑运算,而位运算是将参与运算的两个数据,按对应的二进制数逐位进行逻辑运算。逻辑运算符有逻辑与&&、逻辑或||、逻辑非!,位运算则有六种运算符,位与&、位或|、位异或^、位取反~、位左移<>。
3、如果左移位数>=类型长度,在GCC环境下,GCC编译器会报警告,但实际左移位数为左移位数%(8 * sizeof(int))。例如:
int i = 1, j = 0x80000000; //设int为32位
i = i << 33; // 33 % 32 = 1 左移1位,i变成2
j = j << 33; // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃
4、在C语言中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变。左移时总是移位和补零。右移时无符号数是移位和补零,此时称为逻辑右移;而有符号数大多数情况下是移位和补最左边的位(也就是补最高有效位),移几位就补几位,此时称为算术右移。 算术移位是相对于逻辑移位,它们在左移操作中都一样,低位补0即可,但在右移中逻辑移位的高位补0而算术移位的高位是补符号位。
右移对符号位的处理和左移不同,对于有符号整数来说,比如int类型,右移会保持符号位不变。符号位向右移动后,正数的话补0,负数补1,也就是汇编语言中的算术右移。当移动的位数超过类型的长度时,会取余数,然后移动余数个位。
int i = 0x80000000;
i = i >> 1; //i的值不会变成0x40000000,而会变成0xc0000000
5、位操作符的运算优先级比较低,因为尽量使用括号来确保运算顺序,否则很可能会得到莫明其妙 的结果。比如要得到像1,3,5,9这些2^i+1的数字。写成int a = 1 << i + 1;是不对的,程序会先执行i + 1,再执行左移操作。应该写成int a = (1 << i) + 1。
二、位运算的使用
1、位与运算&
位与运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑与运算。典型应用如下:
A、特定数据段清零
快速对某一段数据单元的数据清零
unsigned int a = 0x00FF1278;
a &= 0xFFFF0FFF;//对a的bit12--bit15位进行清零,a=0x00FF0278
//a &= ~(0xF<<12) ;//对a的bit12--bit15位进行清零,a=0x00FF0278
B、保留数据区的特定位
unsigned int a = 0x00FF1278;
a &= (0xF<<12);//保留a的bit12--bit15位,其他清零,a=0x00001000
C、判断奇偶数
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数
2、位或运算符|
位或运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑或运算。典型应用如下:
A、对数据位置1
unsigned int a = 0x00FF0278;
a |= 0x0000F000;//对a的第12-15位置1,a=0x00FFF278
//a |= (0xF<<12);//对a的第12-15位置1,a=0x00FFF278
3、位异或^
位异或运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑异或运算。只有当对应位的二进制数互斥的时候,对应位的结果才为真。典型应用如下:
A、特定位取反
设定一个数据的指定位,将1换为0,0换为1。例如整型数a=321,,将其低八位数据进行翻位的操作为a=a^0XFF。
B、数值交换
a=a^b;
b=b^a;
a=a^b;
不使用第三方变量可以用位操作来实现交换两数
4、位非~
位非运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑非运算。
A、变换符号
变换符号只需要取反后加1
5、位左移<<
左移运算的实质是将对应的数据的二进制值逐位左移若干位,并在空出的位置上填0,最高位溢出并舍弃。
6、位右移>>
位右移运算的实质是将对应的数据的二进制值逐位右移若干位,并舍弃出界的数字。如果当前的数为无符号数,高位补零。
如果当前的数据为有符号数,在进行右移的时候,根据符号位决定左边补0还是补1。如果符号位为0,则左边补0;但是如果符号位为1,则根据不同的计算机系统,可能有不同的处理方式。可以看出位右移运算,可以实现对除数为2的整除运算。
提示将所有对2的整除运算转换为位移运算,可提高程序的运行效率。
A、求绝对值
int i = a >> 31;
return i == 0 ? a : (~a + 1);
或
int i = a >> 31;
return ((a ^ i) - i);
7、嵌入式开发中常用位操作
A、将寄存器指定位(第n位)置为1
GPXX|= (1<
GPXX |=(1<< 7) | (1<< 4 ) | (1<< 0);//第0、4、7位置1,其他保留
B、将寄存器指定位(第n位)置为0
GPXX &= ~(1<
将寄存器的第n位清0,而又不影响其它位的现有状态。
GPXX &= ~(1<<4 )
C、嵌入式开发位操作实例
unsigned int i = 0x00ff1234;
//i |= (0x1<<13);//bit13置1
//i |= (0xF<<4);//bit4-bit7置1
//i &= ~(1<<17);//清除bit17
//i &= ~(0x1f<<12);//清除bit12开始的5位
//取出bit3-bit8
//i &= (0x3F<<3);//保留bit3-bit8,其他位清零
//i >>= 3;//右移3位
//给寄存器的bit7-bit17赋值937
//i &= ~(0x7FF<<7);//bit7-bit17清零
//i |= (937<<7);//bit7-bit17赋值
//将寄存器bit7-bit17的值加17
// unsigned int a = i;//将a作为i的副本,避免i的其他位被修改
// a &= (0x7FF<<7);//取出bit7-bit17
//a >>= 7;//
// a += 17;//加17
// i &= ~(0x7FF<<7);//将i的bit7-bit17清零
// i |= (a<<7);//将+17后的数写入bit7-bit17,其他位不变
//给一个寄存器的bit7-bit17赋值937,同时给bit21-bit25赋值17
i &= ~((0x7FF<<7) | (0x1F<<21));//bit7-bit17、bit21-bit25清零
i |= ((937<<7) | (17<<21));//bit7-bit17、bit21-bit25赋值
三、位操作的宏定义
//用宏定义将32位数x的第n位(bit0为第1位)置位
#define SET_BIT_N(x,n) (x | (1U<
//用宏定义将32位数x的第n位(bit0为第1位)清零
#define CLEAR_BIT_N(x,n) (x & (~(1U<
//用宏定义将32位数x的第n位到第m位(bit0为第1位)置位
#define SET_BITS_N_M(x,n,m) (x | (((~0U)>>(32-(m-n+1)))<
//用宏定义将32位数x的第n位到第m位(bit0为第1位)清零
#define CLEAR_BITS_N_M(x,n,m) (x & (~(((~0U)>>(32-(m-n+1)))<
//用宏定义获取32位数x的第n位到第m位(bit0为第1位)的部分
#define GET_BITS_N_M(x,n,m) ((x & ~(~(0U)<>(n-1))
嵌入式linux寄存器位运算,嵌入式linux C语言(一)――位运算的使用相关推荐
- c语言复数的运算实验报告,C语言复数的运算(实验报告).doc
实验报告 题目:复数的四则运算 班级: 13信管 姓名:白浩然 学号:201340403034 完成日期:2014.05.21 一.需求分析 1.本演示程序中复数由两个相互之间存在次序关系的实数构成. ...
- c语言复数的运算实验报告,C语言复数的运算实验报告.doc
C语言复数的运算实验报告 实验报告 题目:复数的四则运算 班级: 13信管 姓名:白浩然 学号:201340403034 完成日期:2014.05.21 一.需求分析 1.本演示程序中复数由两个相互之 ...
- 怎么得到16位校检和-c语言,16位CRC校验C语言算法.pdf
16位CRC校验C语言算法.pdf CRC 算法原理及C 语言实现 摘 要 本文从理论上推导出CRC算法实现原理,给出三种分别适应不同计算机或微控 制器硬件环境的C语言程序.读者更能根据本算法原理,用 ...
- c语言位数组如何实现,C语言实现位数组(bit数组)与位数组的简单应用举例
学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 今天有朋友遇 ...
- 两位数码管秒表c语言,两位数码管显示计时器.doc
两位数码管显示计时器 一.题目 用定时0的方式1实现数码管两位59S循环计时(计时器) 二.思路方案 本实验利用单片机的定时器/计数器定时和计数的原理,通过proteus 仿真软件来实现模拟实现.模拟 ...
- c语言位与运算的作用,c语言位运算符的用法
c语言位运算符的用法 C语言中位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果.下面小编就为大家介绍下c语言位运算符的用法. ...
- ubuntu20.04.1 64位搭建嵌入式linux开发环境
目录 背景 开发环境的搭建 1.交叉编译工具的安装 2.开发工具和依赖库的安装 2.1. 必需部分 2.2.可选部分 ubuntu20.04.1 64位配置和编译Linux3.0内核 背景 市面上的嵌 ...
- linux查看内存_嵌入式操作系统的内存,你了解多少?
关注.星标公众号,不错过精彩内容 来源:EDN电子技术设计 linux 内存是后台开发人员,需要深入了解的计算机资源.合理的使用内存,有助于提升机器的性能和稳定性.本文主要介绍 linux 内存组织结 ...
- 嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...
<嵌入式linux应用程序开发完全手册>中断控制器操作(外部中断)学习笔记 一.ARM中断体系 当一个"异常"发生时,或者说当收到一个中断触发信号时,ARM9将会自动完 ...
最新文章
- mysql 基于gtid复制_深入MySQL复制(二):基于GTID复制
- 【Python-ML】SKlearn库L1正则化特征选择
- 2.2.7 局部最优化问题
- createrepo常用参数
- 第五章 列表、元组和字符串[DDT书本学习 小甲鱼]【6】
- springboot 获取application参数_LOOK ! SpringBoot的外部化配置最全解析
- 关于Linux路由表的route命令
- preloadlazy load
- python模块调用模块_Python模块调用
- python 集合(set)
- matlab 下的集成学习工具箱
- 步骤1:mybatis工程的创建
- tn文本分析语言(三):高级语法
- vue template标签_vue为什么要求组件模板只能有一个根元素?
- Docker入门之安装MySQL
- 基于matlab的16QAM调制解调仿真
- C++面试题(数据结构)
- 7-5 游客检票 - 实验3 简单的计算及输入输出 -《Python编程基础及应用实验教程》(高等教育出版社)
- 列线图计算每个患者得分,并生成Roc曲线。
- Word文档另存为PDF时修改的交叉引用还原bug