干货 | union在嵌入式中的一种实用应用
其中应用于管理不同的数据
的用法中有一些小伙伴不是很理解,给我留言了。这篇文章我们就一起看一些实例来进一步理解。
温馨提示:本公众号由于开通得比较晚,所以不具备留言功能。所以大家想看哪些内容,可以在公众号聊天界面留言,小编会参考大家的一些意见输出一些小编的能力范围内能写的内容。另外,本人水平有限,文章中如若出现错误或笔误,也可在聊天界面留言告知我,谢谢!一起成长、一起进步。期待留言~
以下面这个例子为例:
我们看一看这个例子中用到哪些数据:
1、7个用电器状态
2、4个电源线参数
在这个例子中,我们该如何创建数据会比较好呢?
方法一:全局变量
方法一就比较简单粗暴了:
/* 公众号:嵌入式大杂烩 */
uint8_t ele1_status;
uint8_t ele2_status;
uint8_t ele3_status;
uint8_t ele4_status;
uint8_t ele5_status;
uint8_t ele6_status;
uint8_t ele7_status;
float voltage;
float current;
float active_power;
float reactive_power;
这种方法是我们刚学编程、单片机的时候经常这么干,包括现在工作了,一些做算法的同事大都是这么干的。这里我们不讨论使用全局变量的好坏。我们从代码的风格上看,这么多数据,就这么摆着,感觉很散乱。
方法二:创建一个结构体
既然这些数据都是要显示到屏幕上的数据,那我们可以用一个结构体包起来:
/* 公众号:嵌入式大杂烩 */
/* lcd显示的数据 */
struct lcd_disp_data
{
/* 用电器状态 */
uint8_t ele1_status;
uint8_t ele2_status;
uint8_t ele3_status;
uint8_t ele4_status;
uint8_t ele5_status;
uint8_t ele6_status;
uint8_t ele7_status;
/* 电源线参数 */
float voltage;
float current;
float active_power;
float reactive_power;
};
这样看起来较全局变量没那么乱,也更便于管理一些。实际编程中,我们可能会把struct lcd_disp_data
当做一个整体(或者叫做对象
)来使用,假如操控这样一个整体发送到LCD进行显示,需要发送多少字节数据呢?
我们不考虑字节对齐,至少占用23个字节数据:
假如我们有时候只需要单独更新用电器状态或电源线参数呢,那岂不是白白传输了多余的数据,增加了通信负担。方法三可稍微减轻通信负担,下面看看方法三:
方法三:联合体嵌套结构体
使用联合嵌套结构体的方法可以弥补方法二的缺点,这就是我们文首提到的方法,也是我们本篇笔记想要分享的内容。下面针对这个例子看看具体做法:
/* 公众号:嵌入式大杂烩 */
/* 数据包类型 */
enum DATA_PKG_TYPE
{
ELE_STATUE_PKG = 1,
POWER_LINE_PARA = 2
};
/* 用电器状态 */
struct ele_status
{
uint8_t ele1_status;
uint8_t ele2_status;
uint8_t ele3_status;
uint8_t ele4_status;
uint8_t ele5_status;
uint8_t ele6_status;
uint8_t ele7_status;
};
/* 电源线参数 */
struct power_line_para
{
float voltage;
float current;
float active_power;
float reactive_power;
};
/* lcd显示的数据 */
struct lcd_disp_data
{
enum DATA_PKG_TYPE data_pkg_type;
union
{
struct ele_status ele_status_info;
struct power_line_para power_line_para_info;
}data_pkg_info;
};
下面看看不考虑对齐的情况,struct lcd_disp_data
占多少字节:
可见,能节省了一定的空间,数据包数越多,效果越明显。
这里加了一个data_pkg_type数据包类型,这是必须的,否则接收端并不能识别发送端发送的是什么类型的数据。
发送数据如:
1、发送用电器状态数据
/* 公众号:嵌入式大杂烩 */
/* 发送用电器状态数据 */
tx_data.data_pkg_type = ELE_STATUE_PKG;
tx_data.data_pkg_info.ele_status_info.ele1_status = 1;
tx_data.data_pkg_info.ele_status_info.ele2_status = 1;
tx_data.data_pkg_info.ele_status_info.ele3_status = 1;
tx_data.data_pkg_info.ele_status_info.ele4_status = 1;
tx_data.data_pkg_info.ele_status_info.ele5_status = 1;
tx_data.data_pkg_info.ele_status_info.ele6_status = 1;
tx_data.data_pkg_info.ele_status_info.ele7_status = 1;
2、发送电源线参数数据
/* 公众号:嵌入式大杂烩 */
/* 发送电源线参数数据 */
tx_data.data_pkg_type = POWER_LINE_PARA;
tx_data.data_pkg_info.power_line_para_info.voltage = 220.0;
tx_data.data_pkg_info.power_line_para_info.current = 0.044;
tx_data.data_pkg_info.power_line_para_info.active_power = 4.966;
tx_data.data_pkg_info.power_line_para_info.reactive_power = 0.22;
接收数据如:
/* 公众号:嵌入式大杂烩 */
switch (data_pkg_type)
{
case ELE_STATUE_PKG :
// 解析用电器状态数据......
break;
case POWER_LINE_PARA :
// 解析电源线参数数据......
break;
default: break;
}
以上就是本次的分享,如有错误,欢迎指出,谢谢!
如果觉得文章有用,麻烦帮忙转发,有更多的人阅读也是我们继续更新的动力!