良许Linux教程网 干货合集 嵌入式开发中,联合体是这么用的!

嵌入式开发中,联合体是这么用的!

不管是线程间、还是设备间通信,都需制定一个通信协议,规定数据的格式、内容等。

线程间通信因为在芯片内部传输,基本可以排除数据干扰导致的异常,所以通常会设计的比较简单,但是设备间的通信(不管是无线还是有线)就会复杂一些,一般都包含帧头、校验位之类的,因此鱼鹰在一篇文章中介绍了一个基本的串口协议框架《如何写一个健壮且高效的串口接收程序?》。

因为当时刚毕业没多久,所以虽然从大的方向介绍了基本协议内容,但在细节处理上还不够好,比如可维护性、可读性等方面。

后来,鱼鹰在学习开源的飞控源码时,发现里面使用了联合体+结构体的方式,大大提高了程序的可维护性和可读性。

比如,我们的协议中有这样三条命令,心跳包、获取固件版本号、获取序列号。

image-20230904210706980
image-20230904210706980

初级版本:

直接使用基本的类型声明所需要的数据结构。

uint8_t heartbeat;
char version[6]; // "2.0.4"
char sn[7]; // "654321"

一般这样写的,大概率是工作一两年,当然也不排除工作好多年的也可能这样写。看似简单,但可维护性、可读性都非常差。

中级版本:

使用结构体的形式声明各种消息内容。

typedef struct {
  uint8_t heart_nbr;
}msg_heartbeat_def;

typedef struct {
  char version[sizeof("2.0.4") + 1];
}msg_version_def;

typedef struct {
  char sn[sizeof("123456") + 1]; 
}msg_serial_number_def;

这种方式,一般是工作两三年以上的,开始使用结构体容纳数据内容,可扩展性比较强,可维护性、可读性也不错。比如假设后面版本号这个消息里面希望同时获取编译时间,那直接在里面增加即可。

typedef struct {
  char version[sizeof("2.0.4") + 1]; 
  char compile_time[sizeof("2022-12-12, 12:00:00") + 1]; 
}msg_version_def;

如果其它代码写的比较好,甚至不需要多大改动,即可完成一次扩展。

高级版本:

在中级版本的基础上,使用联合体容纳前面的所有消息类型。

typedef struct {
  char version[sizeof("2.0.4") + 1]; 
  char compile_time[sizeof("2022-12-12, 12:00:00") + 1]; 
}msg_version_def;

当你需要发送消息的时候,可以这样发送:

typedef enum {
  MSG_ID_HEARTBEAT,
  MSG_ID_VERSION,
  MSG_ID_SN,
}msg_id_def;

void msg_uart_send(msg_id_def id, msg_data_def *msg_data, uint32_t size)
{// 这里加入帧头、消息ID、校验之类的再发送出去
#define FRAME_FIX_SIZE_MIN  10  // 组成一帧数据的最小空间,包含帧头之类的
  uint8_t send_buff[sizeof(msg_data_def) + FRAME_FIX_SIZE_MIN]; 
}
void msg_send_vesion(void)
{
   msg_data_def data;
   
   strcpy(data.version_nbr, "1.0.1");
      
   msg_uart_send(MSG_ID_VERSION, &data, sizeof(data.version_nbr));
}

因为现在大部分 IDE 都有代码提示功能,所以当你需要发送数据的时候,可以根据提示选择你需要的消息进行发送,相当方便快捷,也不容易出错。

接收消息时,可以使用 switch(id) 之类的解析对应数据。

在这个例子中,我们利用联合体的特性,将所有消息类型集成在一起,这样当你需要发送一条消息时,很容易就能找到想要的数据类型。并且在空间占用上也是非常合理的。当需要开辟缓存容纳数据帧格式,利用了联合体空间占用特性(找最大),这样你开辟的空间一定是刚刚好,不多也不少,节省了空间使用。

所以,当我们需要传输一类消息,但这些消息不会同时存在时,不如使用联合体吧。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部