C 使用UART发送结构

C 使用UART发送结构,c,embedded,microcontroller,uart,serial-communication,C,Embedded,Microcontroller,Uart,Serial Communication,我有两块板: -主板(M板) -从板(S板) 董事会应向董事会发出请求,董事会应予以答复 从机的答案是结构: typedef struct{ uint8_t userID; uint8_t userPass; uint16_t userData; }UserTypeDef; UserTypeDef User; 示例: M板通过发送命令GET\U user\U INFO来请求用户信息(结构)。S板应向M板返回数据结构 M板(Tx)-->获取用户信息-->(Rx)S板 S板(Tx)-

我有两块板:
-主板(M板)
-从板(S板)

董事会应向董事会发出请求,董事会应予以答复

从机的答案是结构:

typedef struct{
  uint8_t userID;
  uint8_t userPass;
  uint16_t userData;
}UserTypeDef;

UserTypeDef User;
示例:
M板通过发送命令GET\U user\U INFO来请求用户信息(结构)。S板应向M板返回数据结构

M板(Tx)-->获取用户信息-->(Rx)S板
S板(Tx)-->用户-->(Rx)M板


问题是如何使用UART发送这样的结构?

保持可读性的最佳方法是以可读的形式对其进行编码

这非常简单,只需使用
sprintf
将值编码为字符串即可

char buffer[BUFFER_LEN];
sprintf(buffer, "%i:%i:%i", user.userId, user.userPass, user.userData);
send_over_uart(buffer);

最简单的方法就是用二进制文件发送。只要接收方知道发送方的endianness是什么(并进行调整),您就可以一次性发送整个结构。这里的缺点是,一个人在看串行端口时只会看到乱七八糟的东西,如果串行端口是7位而不是8位,它将无法工作

第二个最简单的方法是将结构转换为十六进制,但仍然将其作为一个数据块发送(例如,如果您的结构是
{25,54,16745}
,则可以发送
19364169
,并让接收方将其拆分为字段。此方法的缺点是它使用的字节数是第一个方法的两倍

最困难但最可靠的方法是先发送字段名,然后再发送值。这很好,因为查看序列的人可以很容易地知道发生了什么,如果稍后向结构中添加字段,接收软件可能会在看到无法识别的名称时抛出错误。因此,从示例数据中可以看出在上面,您可能有:
userID:0x19,userPass:0x36,userData:0x4169
。缺点是发送名称会浪费大量字节,因此如果您受到串行链接速度的限制,您可能不想这样做。

编写协议文档,明确定义如何通过网络媒体传输结构的内容。然后编写实现协议的代码

传输结构/对象的代码是“数据”。接收结构/对象的代码是“反序列化”。您可以在谷歌上搜索大量有关各种序列化协议和技术的建议和示例

如果您使用的是二进制协议,那么您可以序列化C结构,方法是定义一个uint8_t指针,指向结构中的第一个字节,然后传输字节,直到传输完整个
sizeof(struct)
但是这种方法有一些缺陷,特别是当您的发送和接收设备使用不同的微控制器和/或C编译器时。如果一个微控制器使用不同的endianness,或者一个C编译器使用不同的结构填充规则,则反序列化的数据可能与另一个不同pted


这就是为什么您必须编写一个协议文档来明确定义每个字节的顺序和含义。而且您不应该依赖C编译器来组织结构,就像您的协议一样。C编译器可能会插入填充或使用错误的endianness。因此,您不应该简单地通过结构递增指针,而应该d编写序列化和反序列化例程,从网络协议消息中解析出每个字节,并将其复制到结构中的相应字节中。

显然,性能对您不感兴趣。优化4字节传输以获得性能似乎并不比可读性和易调试性更重要。您我们正在讨论将二进制转换为字符串表示。它非常慢。@SergeyA只有涉及printf系列函数时才慢。使用UART时字符串的另一个优点是,您可以使用任何垃圾终端软件轻松地侦听数据。主要缺点是协议中的有效负载较低。只需在bo上同意endiannes即可th芯片组并发送二进制结构。您所询问的内容称为。