使用union进行串口/UDP等数据传输

部分内容转载自:https://blog.csdn.net/humanking7/article/details/81057648

1. 使用union判断cpu大小端

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

Union 的特性是同一时刻只有一个成员有效,且所有的成员有一个相同的开始地址。联合体的访问不论对哪个变量的存取都是从 union 的首地址位置开始,所以可以用union来测试系统的大小端。

例:
当test.i=1时,数据是00000000,00000000,00000000,00000001
大端模式时,00000001是数据的低位,存储在高位地址中,存储如下,00000000,00000000,00000000,00000001,此时读取test.c,读取存储空间的第一个字节就是00000000,所以test.c=0说明是大端。

小端模式时,00000001是数据的低位,存储在低位地址中,存储如下,00000001,00000000,00000000,00000000,读取第一个字节就是00000001。所以test.c=1就是小端存储。

#include<iostream>
using namespace std; 
int main()
{
	union
	{
		int i;
		char c;
	}test;
	test.i=1;
	if(test.c)  cout<<"小端\n";
	else cout<<"大端\n";
	system("pause");
	return 0;
}

2假设我们要通过串口/UDP与下位机进行数据交互,数据协议为:

在这里插入图片描述

2.1 用union定义传输协议

//signed
typedef signed char        int8;
typedef short              int16;
typedef int                int32;
typedef long long          int64;
//unsigned
typedef unsigned char      uint8;
typedef unsigned short     uint16;
typedef unsigned int       uint32;
typedef unsigned long long uint64;

#pragma pack(push)
#pragma pack(1)//单字节对齐
typedef struct 
{
    uint8   Head;//占1个字节
    uint8   data1_c;//占1个字节
    float   data2_f;//占4个字节 
    uint16  data3_u16;//占2个字节
    double  data4_d;//占8个字节
    int     data5_int;//占4个字节
    uint8   checkSum;//占1个字节  
}ST_protocol;//一共占了21个字节


//用于传输的联合体变量
typedef union
{
    char        buf[21];    
    ST_protocol data;
}UnData;//用于传输的联合体变量

#pragma pack(pop)

2.2 赋值&发送

    cout << "size(ST_protocol) : " << sizeof(ST_protocol) << endl;
    cout << "size(UnData) : " << sizeof(UnData) << endl;

    // 给传输数据赋值
    UnData sendData;
    sendData.data.Head    = 0x55;//占1个字节
    sendData.data.data1_c = 'A';//占1个字节
    sendData.data.data2_f = 0.93;//占4个字节    
    sendData.data.data3_u16 = 0xAABB;//占2个字节
    sendData.data.data4_d = 1.9934;//占8个字节
    sendData.data.data5_int = 7;//占4个字节
    // 校验
    uint8 chkSum = 0;
    for (int i = 0; i < 21-1; i++)
    {
        chkSum += (uint8)(sendData.buf[i]);
    }
    sendData.data.checkSum = chkSum;//占1个字节  

    // 发送数据 
    // write(const char* buf, const int len)
    len = sizeof(sendData);
    write(sendData.buf, len);//发送

2.3 接收&解析

    UnData revData;
    receive(revData.buf);//接收数据

    // 解析
    uint8 chkSum = 0;
    for (int i = 0; i < 21-1; i++)
    {
        chkSum += (uint8)(revData.buf[i]);
    }
    if (chkSum  == revData.data.checkSum 
        && 0x55 == revData.data.Head)
    {//接收成功
        //解析出来的数据
        revData.data.data1_c;
        revData.data.data2_f;
        revData.data.data3_u16;
        revData.data.data4_d;
        revData.data.data5_int;
    }



发布了241 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ShenHang_/article/details/105083378