首页
学习
活动
专区
圈层
工具
发布
50 篇文章
1
C语言中如何实现数据帧封装与解析
2
【熟视C语言】如何快速的了解一个库函数(C语言讲解,以string.h中的部分库函数为例)
3
C语言代码封装MQTT协议报文,了解MQTT协议通信过程
4
NV12数据格式转H265编码格式实现过程
5
基于Modbus协议实现Openplc与Kingview的仿真通讯与模拟测试
6
onvif协议最新版本_接口协议测试工具
7
linux后台开发常用调试工具
8
C/C++开发人员要了解的几大著名C/C++开源库[通俗易懂]
9
适用于嵌入式环境的加速计算库
10
Linux下WebRTC框架Janus编译过程
11
探索嵌入式应用框架(EAF)
12
[C&C++]联合体union的特征及用其进行传输
13
联合体和结构体一起解析数据
14
国标GB28181协议客户端开发(四)实时视频数据传输
15
6.1 C/C++ 封装字符串操作
17
C语言进阶——自定义类型
18
干货 | 结构体、联合体嵌套使用的一些实用操作
19
C语言的面向对象编程
20
QT应用编程: 编写低功耗BLE蓝牙调试助手(Android系统APP)
21
设计模式之接口隔离原则C++实现
22
嵌入式软件开发的框架思维
23
通过面向对象设计串口协议
24
QT应用编程: 开发串口调试助手
25
一种高效的串口自定义16进制通信协议的嵌入式应用开发解决方案
26
嵌入式中状态机的几种骚操作
27
【干货】用FreeRTOS搭建Event-Driven应用框架
28
嵌入式开发基础之任务管理(线程管理)
29
SIP菜鸟如何学SIP
30
Linux下使用libuvc读取控制USB免驱摄像头
31
Linux 使用strace命令查找进程卡死原因
32
84-OOP之组合
33
如何调试多线程程序
34
GDB多线程调试分析
35
GDB多线程多进程调试
36
一个简单实用的线程基类
37
OpenThread是世界上最舒心的跨平台多线程并发库
38
OpenMiniServer是一个超迷你、 超易用的C++高并发跨平台服务器框架
39
OpenSocket是跨全平台的高性能高并发网络库
40
一个C++多线程TCP服务Demo
41
一文搞懂网络库的分层设计!
42
实现一个接收多路RTP流,输出一路RTMP流的简单MCU
43
谈谈嵌入式应用软件人机界面开发的菜单框架编写
44
union 的概念及在嵌入式编程中的应用
45
让终端支持https,移植OpenSSL和libcurl到嵌入式linux,遇到的问题总结
46
日常工作中的设计:解耦和封装
47
一种简易的嵌入式设备系统日志记录方法
48
PLC和计算机通信的数据采集方法和传输监控的实现(1)
49
C++随笔(五)三种实现串口通信的方式
50
开源一个自己写过的MQTT 客户端调试工具

[C&C++]联合体union的特征及用其进行传输

  1. 使用union进行串口/UDP等数据传输
  • 2.1. 用union定义传输协议
  • 2.2. 赋值&发送
  • 2.3. 接收&解析

1. 联合体union的特征及应用

1.1. 特征

结构体(变量)中,结构的各成员顺序排列存储,每个成员都有自己独立的存储位置。联合(union)变量的所有成员共享同片存储区/内存。因此联合变量每个时刻里只能保存它的某一个成员的值。

联合变量也可以在定义时直接初始化,但这个初始化只能对第一个成员进行。例如下面的描述定义了一个联合变量,并进行了初始化。

代码语言:javascript
复制
typedef union 
{
    char   a;//占1个字节
    float  b;//占4个字节
    double c;//占8个字节
    int    d;//占4个字节
}UData;
UData x1 = {5}; //只有x1.a被初始化
//总共UData这种类型的变量占有的大小为 8 个字节
  • union中可以定义多个成员,union的大小由最大的成员的大小决定,如上文中所示的联合体类型UData的大小由所占空间最大的double c变量决定;
  • union成员共享同一块大小的内存,一次只能使用其中的一个成员;
  • 对union某一个成员赋值,会覆盖其他成员的值(但前提是成员所占字节数相同,当成员所占字节数不同时只会覆盖相应字节上的值,比如对char成员赋值就不会把整个int成员覆盖掉,因为char只占一个字节,而int占四个字节)。
  • union量的存放顺序是所有成员都从低地址开始存放的

因此,运用最后一个特性可以用联合(union)来判断CPU的大小端(字节序)。

1.2. 特征

代码语言:javascript
复制
static union
{
    char chr[4];
    unsigned long lng;
}Endian_Test = { { 'L', '?', '?', 'B' } };

#define Endianness ( (char)Endian_Test.lng )

用联合(union)来判断CPU的大小端(字节序):

代码语言:javascript
复制
#include <iostream>
using namespace std;



static union
{
    char chr[4];
    unsigned long lng;
}Endian_Test = { { 'L', '?', '?', 'B' } };

#define Endianness ( (char)Endian_Test.lng )



int main()
{
    cout << "该电脑的字节序为:" << endl;
    if ('L'==Endianness)
    {
        cout << "小端字节序 - Little Endianness" << endl;
    } 
    else
    {
        cout << "大端字节序 - Big Endianness" << endl;
    }


    return 0;
}

在我电脑上运行的结果为:

该电脑的字节序为: 小端字节序 - Little Endianness

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

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

2.1. 用union定义传输协议

代码语言:javascript
复制
//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. 赋值&发送

代码语言:javascript
复制
    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; 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. 接收&解析

代码语言:javascript
复制
    UnData revData;
    receive(revData.buf);//接收数据

    // 解析
    uint8 chkSum = 0;
    for (int i = 0; i < 21; 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;
    }
下一篇
举报
领券