联合体配合结构体解析串口数据,以及解析数据时遇到隐式转换怎么解决

正文

项目需求:

上篇Rd03d测试的文章中用到了struct+union解析串口发来的数据,把代码扣了下来在实际应用中,Rd03d发的数据格式是:帧头部(AA FF 03 00)+帧内数据(目标1信息(8个8位数据)+目标2信息(8个8位数据)+目标3信息(8个8位数据))+帧尾部(55 CC).我的目的是要把帧内数据的两个8位数据拼成一个十六位数据来得到Rd03d检测到的X(16位),Y(16位),Z(16位)坐标数据,有一个方法很简单就是你把读出来的两个8位数据转成16位然后高8位左移8位与低8位进行或逻辑运算就可以的到,但这种方法很笨,如果他发送100个8位数据过来你是不是要一个一个写!所以还有一种方法就是struct+union解析.

extern uint8_t Buffer[30];

//目标1的信息
int16_t Target1_XPos=0;
int16_t Target1_YPos=0;
int16_t Target1_Speed=0;
int16_t Target1_Rate=0;

//目标2的信息
int16_t Target2_XPos=0;
int16_t Target2_YPos=0;
int16_t Target2_Speed=0;
int16_t Target2_Rate=0;

//目标3的信息
int16_t Target3_XPos=0;
int16_t Target3_YPos=0;
int16_t Target3_Speed=0;
int16_t Target3_Rate=0;

#pragma pack (1)
typedef struct{
	short x;
	short y;
	short v;
	short d;
}PersonInfo;

typedef struct{
	union{
		unsigned char data[4];
		unsigned int  data4;
	}head;
	PersonInfo person[3];
//	unsigned char tail[2];
} Info;
#pragma pack()

//将数组Buffer里的数据解析成十进制数据
void Translat_Rd05RegDate()
{
	if(BuffFullFlag==1)
	{
		Info * pInfo = (Info*)Buffer;
		Target1_XPos =pInfo->person[0].x;
		Target1_YPos =pInfo->person[0].y;
		Target1_Speed=pInfo->person[0].v;
		Target1_Rate =pInfo->person[0].d;
		
		Target2_XPos =pInfo->person[1].x;
		Target2_YPos =pInfo->person[1].y;
		Target2_Speed=pInfo->person[1].v;
		Target2_Rate =pInfo->person[1].d;
		
		Target3_XPos =pInfo->person[2].x;
		Target3_YPos =pInfo->person[2].y;
		Target3_Speed=pInfo->person[2].v;
		Target3_Rate =pInfo->person[2].d;		
	}

}

void Show_Rd03d_Data()
{
	Translat_Rd05RegDate();

	if (BuffFullFlag == 1)//判断数组是否满了
	{
		Serial_Printf("***************Rd05 Data***************:\n");
		Serial_Printf("Target1_XPos=%d\n",Target1_XPos);
		Serial_Printf("Target1_YPos=%d\n",Target1_YPos);
		Serial_Printf("Target1_Speed=%d\n",Target1_Speed);
		Serial_Printf("Target1_Rate=%d\n",Target1_Rate);
		
		Serial_Printf("Target2_XPos=%d\n",Target2_XPos);
		Serial_Printf("Target2_YPos=%d\n",Target2_YPos);
		Serial_Printf("Target2_Speed=%d\n",Target2_Speed);
		Serial_Printf("Target2_Rate=%d\n",Target2_Rate);
		
		Serial_Printf("Target3_XPos=%d\n",Target3_XPos);
		Serial_Printf("Target3_YPos=%d\n",Target3_YPos);
		Serial_Printf("Target3_Speed=%d\n",Target3_Speed);
		Serial_Printf("Target3_Rate=%d\n",Target3_Rate);
		Serial_Printf("**************Buffer Data*************:\n");
		for(int i=0;i<30;i++)
		{
			Serial_Printf("Buffer[%d]=%x",i,Buffer[i]);
			Serial_Printf("\n");
		}
		Serial_Printf("\n\n");
		BuffFullFlag = 0;
	}

}

怎么用 struct+union:

先把上面这个代码放一边,先来看怎么用通俗易懂的话讲清struct+union怎么用.

先来看一段代码

#include<stdio.h>

int xPos=0,yPos=0,zPos=0,kPos=0;
int head0,head1,tail0,tail1;
int dat;
#pragma pack (1)
typedef struct{
	unsigned short x;
	unsigned short y;
	unsigned short z;
	unsigned short k;
	
}Pos;

typedef struct{
	union{
		unsigned char dat[2];	
		short data4;	
	}head;
	Pos DatInfo;
	unsigned char tail[2];	 
}RxStr;
#pragma pack ()
unsigned char buffer[12]={0x88,0x88,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x99};
int main()
{
	RxStr *pDat=(RxStr*)buffer;
	
	dat=pDat->head.data4;
	head0=pDat->head.dat[0];
	head1=pDat->head.dat[1];
	xPos=pDat->DatInfo.x;
	yPos=pDat->DatInfo.y;
	zPos=pDat->DatInfo.z;
	kPos=pDat->DatInfo.k;
	tail0=pDat->tail[0];
	tail1=pDat->tail[1];
	
	printf("data4=%x\n\n",dat);
	printf("head0=%x\n",head0);
	printf("head1=%x\n",head1);
	printf("xPos=%x\n",xPos);
	printf("yPos=%x\n",yPos);		
	printf("zPos=%x\n",zPos);
	printf("kPos=%x\n",kPos);
	printf("tail0=%x\n",tail0);
	printf("tail1=%x\n",tail1);
}

运行结果

一步一步看

主函数

RxStr *pDat=(RxStr*)buffer;

将buffer数组强制转换成了结构体RxSrt型的指针,并创建一个RxStr型的指针pDat指向buffer.

此时结构体RxStr会一一被塞满buffer数组的数据,先接收到的塞在后面,后接收到的塞在前面.比如最开始,0x88,0x88分别塞到了union里的dat[0],dat[1]当中.紧接着0x11,0x22塞入unsigned short型的x中,0x33,0x44塞入unsigned  short型的y中,0x55,0x66塞入unsigned  short型的z中,0x77,0x88塞入unsigned  short型的k中,然后0x99,0x99分别塞入tail[0]和tail[1]中.这样完成了接收到的数据一一塞入对应的变量中,有些变量是8位(unsigned char),有些变量是16位(short),我们要的是把两个8位放在一个16位的变量中解析数据,所以我们只取那个16位的变量.

遇到的隐式转换的问题:

有一个问题是问什么在Pos结构体中要用到unsigned short的类型而不直接用short类型?

这里就涉及到隐式类型转换

来看个例子

如果用short型的变量打印16进制有时候好像并没有打印出自己设想的值来,这是为什么

因为运算时计算机把short和char型的变量隐式转换了,把他转为int的变量进行运算.记住有符号时,如果他的补码最高位为1那转为int型运算时他就会把高位位补上1,反之则补上0如上图:

a的16进制是1000100010001000

b的16进制是0111011101110111

a的最高位是1所以隐式转换时他的高位都被补上了1,也就是ffff

b的最高位是0所以隐式转换时他的高位都被补上了0

如何解决隐式转换的问题:

无符号时不会补位,所以用无符号的short,如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值