我最近开始使用this UART library来传输数据。测试用例有效,但是阅读库并不是一件轻而易举的事(至少对我而言)。
我的目标是通过传输控制器上的结构将数据存储在接收微控制器上的结构中。 I thought I was close on my last implementation,但它无处可去。
我想避免犯同样的错误。这是我的协议的伪代码。看起来我忽略了什么吗?
转移
1) Instance struct
2) Point at its memory location
3) For each variable in struct, write its data to the register
接收
1) Instance struct
2) Point at its memory location
3) When the register buffer is full, read register and store to struct by index
答案 0 :(得分:3)
序列化是您认为乍一看非常简单的事情,但正如一些评论者所指出的那样,有很多细节需要加以考虑。字节序很重要,但您还需要知道编译器如何组织结构中的数据。编译器倾向于尝试以最小化读/写数据所花费的时间的方式在内存中对齐数据。 16/32/64位处理器将具有一次访问几个字节数据的机器指令(例如,用于添加两个32位整数等),这些将要求所访问的存储器以一种方式对齐感。访问字节的指令可以使用任何地址,访问16位字的指令要求它们位于偶数地址,访问32位双字的指令要求它们位于可被4整除的地址,依此类推。除此之外,C中的许多标准类型在不同平台上可以有不同的宽度,您可以开始欣赏这个主题的广度。
至少你真的需要定义一个基本的协议,它准确地详细说明了所讨论的结构将如何被序列化。不同的微处理器和/或编译器可以以不同的方式存储数据,如果您希望您的代码稍微可移植,您将希望避免仅将数据移动到缓冲区中。您在评论中提到发送和接收设备将使用相同的微控制器,因此原则上您可以放弃一个简单的实现。但是正如我所看到的,你已经在做一些实现天真序列化的工作了,所以你也可以花时间来获得定义明确的序列化。如果你想验证你的位是否都到达了正确的位置,它可能会让您免于后悔。它还可以避免传输大量未使用的填充位(参见下面的第二个链接)。
你应该看一下关于序列化的这个问题:(C - serialization techniques)。有几个不同的答案,但接受的答案几乎是我的建议。只要知道结构的大小,就可以在没有缓冲区的动态内存分配的情况下获得结构,但是为每个数据对象设置专用的“serialize _...()”函数是一条很好的选择。
我还建议您仔细阅读本文档:(http://www.catb.org/esr/structure-packing/)。它旨在展示如何使用struct packing来节省内存,但它也是理解如何在C中序列化数据的一个很好的来源(主题密切相关)。
几年前,我不得不推出自己的微型串行协议,使一些8位PIC通过GPIO相互通信,我发现通过定义启动/停止条件和简单数据很有趣协议。一种相当常见的方法是为数据包启动/停止字节,然后以一致的格式描述数据,例如:
[start byte] [type0] [length0] [data0] [type1] [length1] [data1] ... [typeN] [lengthN] [dataN] [end byte]
上述格式是一种更通用/灵活的方法,一些高级协议允许使用类似格式描述大型数据结构。但是在我们只有一条可能消息的简单情况下,我们可以假设发送设备和接收设备在消息中的每个“对象”的顺序上达成一致,并且它们也知道每个“对象”的类型和字节长度,所以您不需要传输此数据。如果要传输多个可能的结构中的一个,可以使用单个[type]字节来传递正在发送的结构。你真的有很多选择,所以玩得开心。使用CRC可以获得奖励积分,以确保您的数据不受损坏。
我为缺乏花哨的格式而道歉;我是一个真正回答SO问题的新手。