最近在实验室里参与了一个QT上位机和keil下位机通信的小项目,里面涉及到RS232通信,前人采取的是带小数数据×100凑成整数再变成16进制发送的原始方法,这里采取共用体方式进行发包解包简化流程,担心遗忘做个记录。
共用体union用于传输数据的一般的用法是在新建的共用体当中新建一个char型数组,再新建一个结构体struct,结构体里面新建多个变量,当我们传递数据的时候,将需要传递的数据写入结构体变量当中,这些数据会占用若干位16进制数据(与char型数组对应),则发包时只需要将char型数组发出去,解包侧写一个相同的union,将解包接收的数据也放入对应的char型数组,则可以免去繁琐的解包函数。下面是一个范例:
(1)在.h文件中编写一个结构体储存待传输的数据:
typedef union //接收数据共用体
{
char Rcv_BUF[30];
struct Rcv_Data
{
char a;
char b;
char c;
char d;
float sp_pitchangle;
float sp_rollangle;
float sp_yawangle;
float sp_pitchrate;
float sp_rollrate;
float sp_yawrate;
}RcvData;
}u2_Rcv;
Rcv_BUF为发包用的数组,结构体RcvData为需要传输的数据,可以是任何数据格式,本例当中需要传输的数据为:abcd为char型占用一个字符,sp开头的6个数据为浮点型float,将需要的10个数据写入结构体之后,union自动将格式转换成char型保存在Rcv_BUF当中,需要的数组长度为1x4+6x4=28,这里设置Rcv_BUF长度为30。
(2)主函数写入待传输数据到发送共用体
//待发送char型数据abcd
char a[4] = { 1,2, 3, 4 };
//待发送数据sp(6个float)
float aa[6] = {32.15 ,35.64, 35.24 ,33.25,45.89,98.56 };
u1_Rcv u1_RcvUnion; //新建发送共用体
//写入待发送数据至union中的结构体
u1_RcvUnion.RcvData.a = a[0];
u1_RcvUnion.RcvData.b = a[1];
u1_RcvUnion.RcvData.c = a[2];
u1_RcvUnion.RcvData.d = a[3];
u1_RcvUnion.RcvData.sp_pitchangle = aa[0];
u1_RcvUnion.RcvData.sp_rollangle = aa[1];
u1_RcvUnion.RcvData.sp_yawangle = aa[2];
u1_RcvUnion.RcvData.sp_pitchrate = aa[3];
u1_RcvUnion.RcvData.sp_rollrate = aa[4];
u1_RcvUnion.RcvData.sp_yawrate = aa[5];
新建发送共用体u1_RcvUnion,待发送数据为char型1234及6个带两位小数点的浮点型数据,依次写入union里的结构体当中。
(3)新建接收共用体,接收解包数据
u1_Rcv u2_RcvUnion; //新建接收共用体
for(int i=0 ; i<30 ; i++) //解包数据(实际上就是memcpy数据到接收共用体的数组里)
u2_RcvUnion.Rcv_BUF[i] = u1_RcvUnion.Rcv_BUF[i];
新建一个共用体作为接收共用体,需要注意的是,接收共用体里面的数据格式需要和发送共用体的数据格式一致,否则会出现问题。如果是采取串口传输,则接收端可以直接将接收到的数据帧原封不动的丢到接收共用体的数组当中,需要注意数组存入数据的先后顺序。
(4)输出结构
float b = u2_RcvUnion.RcvData.sp_pitchangle;
cout << b << endl;
getchar();
传递过来的sp开头的数据都是float型,新建float型数据直接读取接收共用体中结构体里面的数据sp_pitchangle,不需要进行别的解包过程。
结果:32.15
可以看出直接输出了期望传输数据的第一个数据32.15,union用作数据传输十分方便便捷。