亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial Internet of Things >> 嵌入式

学习嵌入式 C 编程语言:理解联合数据对象

了解嵌入式 C 语言中称为联合的数据对象。

了解嵌入式 C 语言中称为联合的数据对象。

嵌入式C中结构和联合的区别

在本系列的前一篇文章中,我们讨论了嵌入式 C 中的结构允许我们将不同数据类型的变量分组,并将它们作为单个数据对象进行处理。

除了结构之外,C 语言还支持另一种数据结构,称为联合,可以将不同的数据类型分组为单个数据对象。本文将提供有关工会的一些基本信息。我们将首先看一个声明联合的介绍性示例,然后我们将研究该数据对象的一个​​重要应用。

介绍性示例

声明联合很像声明结构。我们只需要将关键字“struct”替换为“union”即可。考虑以下示例代码:

union test { uint8_t c; uint32_t i;}; 

这指定了一个模板,它有两个成员:“c”,占用一个字节,“i”,占用四个字节。

现在,我们可以创建这个联合模板的变量:

联合测试u1; 

使用成员运算符 (.),我们可以访问“u1”联合的成员。例如,以下代码将 10 分配给上述联合的第二个成员,并将“c”的值复制到“m”变量(必须是 uint8_t 类型)。

u1.i=10;m=u1.c; 

将分配多少内存空间来存储“u1”变量?结构的大小至少与其成员大小的总和一样大,而联合的大小等于其最大变量的大小。分配给联合的内存空间将在所有联合成员之间共享。在上面的例子中,“u1”的大小等于 uint32_t 的大小,即四个字节。这个内存空间在“i”和“c”之间共享。因此,为这两个成员之一赋值将改变另一个成员的值。

你可能想知道,“使用相同的内存空间来存储多个变量有什么意义?有这个功能的应用程序吗?”我们将在下一节探讨这个问题。

我们需要共享内存空间吗?

让我们看一个例子,其中联合可以是一个有用的数据对象。假设,如下图 1 所示,您的系统中有两个设备需要相互通信。

图 1

“设备 A”应向“设备 B”发送状态、速度和位置信息。状态信息由三个变量组成,分别表示电池电量、操作模式和环境温度。该位置由显示 x 轴和 y 轴位置的两个变量表示。最后,速度由单个变量表示。假设这些变量的大小如下表所示。

变量名 大小(字节) 说明
power 1 电池充电
op_mode 1 操作模式
temp 1 温度
x_pos 2 X 位置
y_pos 2 Y 位置
vel 2 速度

如果“设备 B”不断需要拥有这些信息的每一部分,我们可以将所有这些变量存储在一个结构中并将该结构发送到“设备 B”。结构体的大小至少要与这些变量的大小之和一样大,即九个字节。

因此,每次“设备A”与“设备B”通话时,都需要通过两个设备之间的通信链路传输一个9字节的数据帧。图2描述了“设备A”用来存储需要通过通信链路的变量和数据帧的结构。

图 2

然而,让我们考虑一个不同的场景,我们只是偶尔需要发送状态信息。此外,假设在给定时间不需要同时具有位置和速度信息。换句话说,有时我们只发送位置,有时只发送速度,有时只发送状态信息。在这种情况下,将信息存储在九字节结构中并通过通信链路传输似乎不是一个好主意。

状态信息只能用三个字节表示;对于位置和速度,我们分别只需要四个和两个字节。因此,“设备 A”在一次传输中需要发送的最大字节数是四个,因此,我们只需要四个字节的内存来存储这些信息。这四字节的内存空间将在我们的三种消息类型之间共享(见图 3)。

另外需要注意的是,通过通信链路的数据帧长度从九字节减少到四字节。

图 3

总而言之,如果我们的程序有互斥的变量,我们可以将它们存储在共享内存区域中,以保留宝贵的内存空间。这可能很重要,尤其是在内存受限的嵌入式系统中。在这种情况下,我们可以使用联合来创建所需的共享内存空间。

上面的例子表明,使用联合来处理互斥变量也可以帮助我们节省通信带宽。节省通信带宽有时甚至比节省内存更重要。

对消息包使用联合

让我们看看如何使用联合来存储上述示例的变量。我们有三种不同的消息类型:状态、位置和速度。我们可以为状态和位置消息的变量创建一个结构(以便将这些消息的变量分组并作为单个数据对象进行操作)。

以下结构用于此目的:

struct { uint8_t power; unit8_t op_mode; uint8_t 温度;} 状态;结构 { uint16_t x_pos; unit16_t y_pos;} 位置; 

现在,我们可以将这些结构与“vel”变量放在一个联合中:

union {struct { uint8_t power; unit8_t op_mode; uint8_t 温度;} 状态;结构 { uint16_t x_pos; unit16_t y_pos;} 位置; uint16_t vel;} msg_union; 

上面的代码指定了一个联合模板并创建了这个模板的变量(命名为“msg_union”)。在这个联合内部,有两个结构(“status”和“position”)和一个两字节的变量(“vel”)。这个联合的大小将等于其最大成员的大小,即“位置”结构,占用四个字节的内存。该内存空间由“status”、“position”和“vel”变量共享。

如何跟踪联盟活跃会员

我们可以使用上面联合的共享内存空间来存储我们的变量;但是,仍然存在一个问题:接收方应该如何确定发送的是哪种类型的消息?接收方需要识别消息类型才能成功解释接收到的信息。例如,如果我们发送一个“位置”消息,则接收到的数据的所有四个字节都很重要,但对于“速度”消息,应该只使用接收到的两个字节。

为了解决这个问题,我们需要将我们的联合与另一个变量相关联,比如“msg_type”,它表示消息类型(或最后写入的联合成员)。与表示联合的活跃成员的离散值配对的联合被称为“可区分联合”或“标记联合”。

关于“msg_type”变量的数据类型,我们可以使用C语言的枚举数据类型来创建符号常量。但是,我们将使用字符来指定消息类型,只是为了使事情尽可能简单:

struct { uint8_t msg_type;union {struct { uint8_t power; unit8_t op_mode; uint8_t 温度;} 状态;结构 { uint16_t x_pos; unit16_t y_pos;} 位置; uint16_t vel;} msg_union;} 消息; 

我们可以考虑“msg_type”变量的三个可能值:“s”表示“状态”消息,“p”表示“位置”消息,“v”表示“速度”消息。现在,我们可以将“消息”结构发送到“设备 B”,并使用“msg_type”变量的值作为消息类型的指示符。例如,如果接收到的“msg_type”的值为“p”,“设备B”就会知道共享内存空间包含两个2字节的变量。

请注意,我们必须向通过通信链路发送的数据帧添加另一个字节,因为我们需要传输“msg_type”变量。另请注意,使用此解决方案,接收方无需提前知道传入的消息类型。

替代方案:动态内存分配

我们看到联合允许我们声明共享内存区域以节省内存空间和通信带宽。但是,还有另一种方法来存储互斥变量,例如上面示例中的变量。第二种解决方案使用动态内存分配来存储每种消息类型的变量。

同样,我们需要有一个变量“msg_type”来指定通信链路发送端和接收端的消息类型。例如,如果“设备A”需要发送位置消息,它将“msg_type”设置为“p”并分配四个字节的内存空间来存储“x_pos”和“y_pos”变量。接收方将检查“msg_type”的值,并根据其值创建适当的内存空间来存储和解释传入的数据帧。

就内存使用而言,动态内存的使用可以更有效,因为我们为每种消息类型分配了足够的空间。基于联合的解决方案并非如此。在那里,我们有四个字节的共享内存来存储所有三种消息类型,尽管“状态”和“速度”消息分别只需要三个和两个字节。但是,动态内存分配可能会更慢,并且程序员需要包含释放分配内存的代码。这就是为什么程序员通常更喜欢使用基于联合的解决方案。

下一步:联合的应用

似乎联合的最初目的是为互斥变量创建共享内存区域。然而,联合也被广泛用于从较大的数据对象中提取较小的数据部分。

本系列的下一篇文章将重点介绍联合的这种应用,这在嵌入式应用中尤为重要。

要查看我的文章的完整列表,请访问此页面。


嵌入式

  1. 工业物联网应用的最佳编程语言
  2. 微处理器编程
  3. 什么是嵌入式系统编程及其语言
  4. 什么是嵌入式系统设计:设计过程中的步骤
  5. 如何处理数据?!
  6. 物联网民主化
  7. 2021 年要学习的 9 种新编程语言
  8. C - 工会
  9. 数据中心的未来
  10. 物联网中的云
  11. 评论:了解机器人编程的方法
  12. 说同一种工业语言:了解压缩机的常用测量单位