关于利用结构体和联合体数据收发的两种方法

2023-05-16

关于利用结构体和联合体数据收发的两种方法

关于最近接手的小项目,有了一些经验,所以进行一下记录。


文章目录

  • 关于利用结构体和联合体数据收发的两种方法
  • 前言
  • 一、联合体法
  • 二、结构体法
  • 小tips


前言

在我们利用自己的板子进行数据的收发通信时,会遇到发来的数据不是我想要的数据或者我发出的数据和对方接收到的数据不是一个。这是因为在数据转移的过程中出现了对齐不正确或者大小端的纰漏,在这里我介绍自己项目开发中常用的两种方法。此处的通讯线路为CAN总线进行介绍。

一、联合体法

当我们进行CAN总线通讯时,收发的字节数为8个字节以内,而我们收发的过程中,这些字节数据是以数组的形式uint8_t arr[ ]进行保存的。这就帮助我们可以顺利的将数据进行打包和存储。接收CAN消息,利用固件库的CAN结构体可以将8字节数据引用出来。接下来介绍联合体获取数据和发送数据的方法。

typedef union 
{
		uint32_t u32_data[2];
		uint16_t u16_data[4];
		uint8_t  u8_data[8];
	  //数据提取,转化,拆分的meas
}c_wttk; 
c_wttk function;

如上为我们所定义的联合体类型和联合体变量。当我们从CAN中获取到8字节数组数据即

typedef struct {
    uint32_t rx_sfid;                                                   /*!< standard format frame identifier */
    uint32_t rx_efid;                                                   /*!< extended format frame identifier */
    uint8_t rx_ff;                                                      /*!< format of frame, standard or extended format */
    uint8_t rx_ft;                                                      /*!< type of frame, data or remote */
    uint8_t rx_dlen;                                                    /*!< data length */
    uint8_t rx_data[8];      //这个8字节数据                                           /*!< receive data */
    uint8_t rx_fi;                                                      /*!< filtering index */
} can_receive_message_struct;
can_receive_message_struct pframe;

中的 uint8_t rx_data[8]; 我们将这些数据赋值给以上的联合体数据,举个例子即:

memcpy(&function.u8_data,pframe.rx_data,sizeof(u8_data));

我们就把数据转移到我们所需要的联合体中了,根据我以前博文中利用的联合体使用方法就可以将数据进行不同位数转换的发送了。

二、结构体法

首先向大家介绍一下结构体的按字节对齐的两种方法:

第一种方法:
#pragma pack(1) //按照1字节方式对齐
“结构体类型”
#pragma pack() //对齐结束
两个预编译指令之间的结构体内的内容都会非常紧密的按单个字节对齐,不会留出多余的空隙。

第二种方法:
利用预编译指令__attribute__((packed))
比如:

typedef struct
{
	uint8_t selfcheck_status 	: 2; 
	uint8_t selfcheck_reserved 	: 6;

	uint8_t alm_empty			: 1;	
	uint8_t alm_block			: 1;	// 1 - blocked
	uint8_t alm_reserved 		: 6;

	uint8_t signal_source		: 2;	// 00 - pwm, 01 - can
	uint8_t signal_reserved 	: 6;

	// byte3
	uint16_t baud_rate;					// baudrate rate, big endian	
	uint8_t reserved1;

	// byte6
	uint8_t enable_empty		: 1;	// 1 - turn off alm_empty
	uint8_t enable_block		: 1;	// 1 - turn off alm_block
	uint8_t enable_reserved		: 6;

	// byte 7
	uint8_t heartbeat;					// cycle 0x00<->0xff
}__attribute__((__packed__)) status_msg_t;

第二种方法的好处就是,可以进行单个结构体的按字节对齐结构体,不用多次强调第一种方法的预编译指令。

同样地,可以进行数值的转移:

status_msg_t status;
can_receive_message_struct pframe;
memcpy(&status, pframe.rx_data, sizeof(status_msg_t ));

通过以上方法,就可以将发来的数据进行了保存。
同样的发送,也是先将数据放到联合体中,按位进行存放,即uint8_t中数值实际上只占1位的数据存到结构体按位1位的元素内容中。把所有数据都填充到结构体中后,通过memcpy拷贝到发送数据结构体的数组中,进行CAN的发送:
(此处使用我自己的代码进行回忆)

	memcpy(frame.u8Data,&Spreader_status_tx.valve_ctrl,sizeof(valve_ctrl_def));  //copy两个字节的元素到frame的联合体中
	
   	memcpy(&spreader_valve_can_frame, &frame, sizeof(can_basic_frame_t));  //copy到要发送的结构体中

小tips

一、联合体的赋值可以直接 ‘=’,比如:
Spreader_status_rx.plate_report = plate_report_t;
联合体的取地址必须加&符号,比如:&plate_report_t;
二、数组的赋值,不能直接‘=’赋值,它需要用函数strcpy()或者memcpy()来进行所有数组元素的数值转移。但是数组的取地址直接使用数组首地址直接进行取地址即可,即:pRxCan->u8Data。即数组名pRxCan->u8Data就是首地址。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于利用结构体和联合体数据收发的两种方法 的相关文章

随机推荐

  • E:Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)

    出现这个问题的原因可能是有另外一个程序正在运行 xff0c 导致资源被锁不可用 而导致资源被锁的原因 xff0c 可能是上次安装时没正常完成 xff0c 而导致出现此状况 解决方法 xff1a 输入以下命令 sudo rm var cach
  • shell 脚本中的引用问题

    原始代码如下 bin sh myvar 61 34 Hello world 34 echo myvar echo 34 myvar 34 echo 39 myvar 39 echo myvar echo Enter some test re
  • Linux内核的TCP源码入门(一)

    文章目录 前言一 TCP报文段结构1 报文段整体结构2 TCP首部 固定部分3 TCP首部 选项 options 二 TCP接收和发送数据1 TCP的 34 接口 34 2 发送数据3 接收数据3 1 ip层向上调用INET Socket层
  • 【API接口工具】postman-Windows版、Linux安装

    Windows安装 Postman 适用于 Windows 7 及更高版本 下载最新的 Postman 版本 选择并运行该 exe文件以安装 Postman Postman v9 4 是 Postman 的最后一个版本 xff0c 同时支持
  • 四轴飞控DIY调试起飞简明步骤

    四轴飞控DIY调试起飞简明步骤 调试起飞简明步骤Step1 xff1a 飞控配置Step2 xff1a 试飞目标测试内容坐标系 Step3 xff1a 试飞方法1 升降 xff08 Throttle xff09 2 偏航 xff08 yaw
  • PX4模块设计之二十七:LandDetector模块

    PX4模块设计之二十七 xff1a LandDetector模块 1 LandDetector模块简介2 模块入口函数2 1 主入口land detector main2 2 自定义子命令custom command 3 LandDetec
  • 穿越机用途和机架尺寸

    穿越机用途和机架尺寸 1 穿越机的用途2 穿越机的机架3 机架的类型3 1 正X型机架3 2 宽X型机架3 3 长X型机架3 4 Hybrid机架3 5 涵道机架 4 总结 1 穿越机的用途 穿越机按功能分 xff0c 主要分为竞速Race
  • 关于穿越机FPV视频果冻效应的讨论

    关于穿越机FPV视频果冻效应的讨论 1 名词定义2 摄像原理2 1 快门分类2 2 常见传感器2 3 卷帘拍摄 3 产生原因4 解决方法4 1 振动出处4 2 软件方法 辅助作用 4 3 硬件方法 直接办法 5 F450试验机FPV视频问题
  • 四轴飞控DIY Mark4 - 减震

    四轴飞控DIY Mark4 减震 1 DIY Mark42 改进事项2 1 Mark4 5 inches机架2 2 2205 2450KV 无刷电机2 3 电机与机架的TPU防震2 4 飞控防震垫圈2 5 三叶平衡桨 3 试飞效果3 1 视
  • Java的压力测试工具之Jmeter

    size 61 large Apache JMeter是Apache组织开发的基于Java的压力测试工具 用于对软件做压力测试 xff0c 它最初被设计用于Web应用测试但后来扩展到其他测试领域 它可以用于测试静态和动态资源例如静态文件 J
  • 四轴飞控DIY Mark4 - 整理&参数优化

    四轴飞控DIY Mark4 整理 amp 参数优化 1 历程2 参数优化2 1 固件BF4 3 12 2 动态怠速值2 3 滤波参数2 4 电调PWM频率2 5 GPS高度配置2 6 返航速度和高度2 7 线性推力修正2 8 图传频道调整
  • ArduPilot开源飞控系统之简单介绍

    ArduPilot开源飞控系统之简单介绍 1 源由2 了解 amp 阅读2 1 ArduPilot历史2 2 关于GPLv32 3 ArduPilot系统组成2 4 ArduPilot代码结构 3 后续3 1 DIY F4503 2 软件设
  • ArduPilot Kakute F7 AIO DIYF450 之GPS配置

    ArduPilot Kakute F7 AIO DIYF450 之GPS配置 1 源由2 步骤2 1 模块预测试2 2 物理连接2 3 UART配置2 4 Compass使能2 5 GPS使能2 6 校准Compass 3 GPS amp
  • ArduPilot之开源代码框架

    ArduPilot之开源代码框架 1 系统框架2 工程框架2 1 工程目录2 2 代码组成2 3 运行流程 4 硬件传感器总线4 1 I2C4 2 SPI4 3 UART4 4 CAN 5 软件设计概念6 总结7 参考资料 在研读ArduP
  • COPY 一种接近最优的导航网格生成算法以及基于导航网格的寻路算法

    提出背景 xff1a 长距离寻路会出现掉帧现象 xff0c 为了提高寻路速度 xff0c 并为3D环境中的寻路方案提供基础算法实现 目前状况 xff1a 由于3D游戏对帧率要求很高 xff0c 而在游戏中进行一次长距离的寻路可能要花费8 1
  • 解析串口-接收完整数据帧

    在linux下编写串口通讯程序 xff0c 采用select监听串口的可读事件 xff0c 一旦可读 xff0c 调用read 但是我们会发现 xff0c read一次得到的数据通常不是完整的一个数据帧 比如完整数据帧为 但是实际上需要re
  • STL 基本容器 优缺点比较

    总结在先 xff1a xff11 如果需要高效的随机存取 xff0c 不在乎插入和删除的效率 xff0c 使用vector xff1b 2 如果需要大量的插入和删除元素 xff0c 不关心随机存取的效率 xff0c 使用list xff1b
  • STL源码剖析--vector容器

    写在前面 vector是我们在STL中最常用的容器 xff0c 我们对它的各种操作也都了然于胸 然而我们在使用vector的时候总会有一种很虚的感觉 xff0c 因为我们不清楚接口内部是如何实现的 在我们眼里宛如一个黑箱 xff0c 既危险
  • TCP/UDP调试工具的使用

    TCP UDP调试工具下载链接 前文 当我们写好一个TCP UDP的程序时 但是无法通信时 光看代码又找不出原因时 我们可以借助调试工具来检查是服务端还是客户端出现了问题 这样就很大的减少了错误的排查范围 再次感叹一下 这个工具真的很好用
  • 关于利用结构体和联合体数据收发的两种方法

    关于利用结构体和联合体数据收发的两种方法 关于最近接手的小项目 xff0c 有了一些经验 xff0c 所以进行一下记录 文章目录 关于利用结构体和联合体数据收发的两种方法前言一 联合体法二 结构体法小tips 前言 在我们利用自己的板子进行