c语言左移16位在左移10位,C语言位运算应用实例

文章目录

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;

}

经测试,上述代码可以稳定实现自定义数据协议的编码解码工作。

抗传输丢包效果良好,除非恰好连续丢 “此数据低段” 和“下一数据高段” ,否则不会读取到错误信息。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值