概述
文章目录
C语言位运算应用实例
一、位操作规则
1、与 (&)
2、或 (|)
3、与或 (^)
4、取反 (~)
5、左移、右移(<< 、>>)
二、位操作应用实例
1、编码
2、解码
C语言位运算应用实例
正在准备2019年RM比赛,遇到这样一个场景:Tx2图像采集之后要把目标位置传给stm32控制板,位置信息有x/y这一属性,准备用串口做数据传输。
传输数据范围是[0,560]且为整数,但是查了一下发现stm32的串口一次最多读8位数据,也就是[0,255],没有办法,只能把数据拆成两个8位的来传输。
下面根据一应用实例总结C语言中位运算使用。
一、位操作规则
共有6种位操作
运算符
含义
&
按位与运算
i
按位或运算
^
按位异或运算
~
按位取反运算
<<
左移
>>
右移
按位运算:指把参与运算的两个数据都换位二进制后,每两个对应位进行运算并得到新二进制数*
若把存储运算结果的变量设为unsigned类型,则所有位都是数据位;否则以补码形式换算为带符号十进制数。
以下都是以unsigned型为例
1、与 (&)
运算
结果
0 & 0
0
0 & 1
0
1 & 0
0
1 & 1
1
规则:有0为0,全1为1
1、实例:
3&5 = 011 & 101 = 001=1
2、常用用法:
对某些位清零。如要对3:0位清零,只需将数据与1111 0000 &运算即可
取数据中某些位。如取0110 0110中2:1位,(0110 0110 & 0000 0110>>1=11=3
2、或 (|)
运算
结果
0
0
0
1
1
0
1
1
规则:有1为1,全0为0
1、实例:
3|5 = 011 | 101 = 111=7
2、常用用法:
对某些位赋值。如给0111 0000的3:0位赋1111:0111 0000|0000 1111 =0111 1111
3、与或 (^)
运算
结果
0 ^ 0
0
0 ^ 1
1
1 ^ 0
1
1 ^ 1
0
规则:相同为0,不同为1
1、实例:
3^5 = 011 ^ 101 = 110 = 6
2、常用用法:
使特定位翻转。将要翻转的位与1异或运算,如翻转1010的1:0位:1010^0011=1001
4、取反 (~)
运算
结果
~0
1
~1
0
规则:1变0,0变1
1、实例:
~3 = ~011 = 100 = 4
2、常用用法:
使全部位翻转。
5、左移、右移(<< 、>>)
运算
结果
a
a>>n
把数据a右移n位(换成二进制形式移),移出末位部分舍去,高位补0
1、实例:
3<<2 = 011<<2 = 01100 = 12
3>>2 = 011>>2 = 0 = 0
2、常用用法:
配合&运算把取出的位移到最低。
a>n == a/2^n
二、位操作应用实例
要处理文章开头提出的实际问题,设计数据传输格式为:
每帧数据长8位,且表示正整数(unsigned char型)
每两帧数据拼一个真实数据,最多表示12位 ( [0,4095] )
位
含义
7
指示x,y属性(1-x 0-y)
6
指示拼数据时高低属性(1-高 0-低)
5:0
数据
1、编码
思路:分别取数据 5:0 和 11:6 位域,根据数据属性补充最高两位数据。实例如下:
#include
using namespace std;
#define DATA 1200//待编码数据
#define Low 0//用于补齐高位信息
#define High 1
#define X_ctrl 1
#define Y_ctrl 0
unsigned char set_flag_bit(unsigned char data,int X_Y,int H_L) //填高2位
{
data &= 0X3F; //高2位清零 0x3F=0011 1111
if(X_Y==Y_ctrl && H_L==Low)//Y-L 00
data |= 0X00;//0x00=0000 0000
else if(X_Y==X_ctrl && H_L==Low)//X-L 10
data |= 0X80;//0x80=1000 0000
else if(X_Y==Y_ctrl && H_L==High)//Y-H 01
data |= 0X40;//0x40=0100 0000
else if(X_Y==X_ctrl && H_L==High)//X-H 11
data |= 0XC0;//0xC0=1100 0000
return data;
}
unsigned char Ldata,Hdata;
void data_processing(int data,int X_Y)
{
Ldata=data & 0XFF;//取低8(1-8)位 0xFF = 1111 1111
Ldata=set_flag_bit(Ldata,X_Y,Low);
Hdata=(data & 0X3FC0)>>6;//取高7-14位 0xFF = 1111 1111 0000 0000
Hdata=set_flag_bit(Hdata,X_Y,High);
}
int main()
{
int data = DATA;
data_processing(DATA,Y_ctrl);
//cout
return 0;
}
2、解码
思路:先取数据高二位判断属性,根据其信息拼接数据并存入x、y数据buff中。实例如下:
#include
using namespace std;
unsigned int x_real_data_buff[10];//存储x、y数据的buff,用于滑动平均滤波
unsigned int y_real_data_buff[10];
int x_real_data_cnt=0;//buff中数据个数计数
int y_real_data_cnt=0;
unsigned char data_decode(unsigned char data)
{
unsigned int real_data;
static int x_cnt=0;
static int y_cnt=0;
static unsigned char Hdata;
static unsigned char Ldata;
static unsigned char update_flag=0;//标记是否已收到高段数据(是-1,不是-0)
static float x_aver=0;
static float y_aver=0;
unsigned char X_Y_decide; //1->X
unsigned char H_L_decide; //1->H
switch((data & 0xc0)>>6)//0xc0=1100 0000,这里取高2位
{
case 0x00://00
X_Y_decide=0;
H_L_decide=0;
Ldata=(data & 0X3F);//0X3F=0011 1111,这里取出该数据帧中有效数据部分
break;
case 0x01: //01
X_Y_decide=0;
H_L_decide=1,update_flag=1;
Hdata=(data & 0X3F);
break;
case 0x02: //10
X_Y_decide=1;
H_L_decide=0;
Ldata=(data & 0X3F);
break;
case 0x03: //11
X_Y_decide=1;
H_L_decide=1,update_flag=1;
Hdata=(data & 0X3F);
break;
}
if(update_flag==1 && H_L_decide==0)//已收到高位,又收到低位,一个数据接收完成
{
update_flag=0;
real_data=Hdata;//这里直接左移会溢出丢数据,所以应先给16位的real_data再左移
real_data=(real_data<<6) | Ldata;
if(X_Y_decide==1)
x_real_data_buff[x_real_data_cnt++]=real_data;
else
y_real_data_buff[y_real_data_cnt++]=real_data;
}
}
void show_data(unsigned int *buff,int CNT)
{
for(int i=0;i
cout<
cout<
}
int main()
{
unsigned char data_buff[]={0x52,0x30,0xd2,0xb0};//待解码数据写在这里
for(int i=0;i
data_decode(data_buff[i]);
cout<
show_data(x_real_data_buff,x_real_data_cnt);
cout<
show_data(y_real_data_buff,y_real_data_cnt);
return 0;
}
经测试,上述代码可以稳定实现自定义数据协议的编码解码工作。
抗传输丢包效果良好,除非恰好连续丢 “此数据低段” 和“下一数据高段” ,否则不会读取到错误信息。
最后
以上就是优美超短裙为你收集整理的c语言左移16位在左移10位,C语言位运算应用实例的全部内容,希望文章能够帮你解决c语言左移16位在左移10位,C语言位运算应用实例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复