2

我正在尝试从用 C 编程的 PIC 接收二进制记录。

发送的数据结构如下:

typedef struct{int32 num1;
              float num2,num3,num4,num5;
              ...
              }RecordStructure;

typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;

我的问题是这样的:

前 4 个字节/字符是否属于int32 num1,接下来的 4个属于float num2等等?

如果是这样,我在传输方面遇到了重大问题;如果不是,我如何辨别数据的最终位置?

4

4 回答 4

3

是的,在第一部分,但有一个警告。

C 标准要求将第一个结构成员放在结构的开头。因此 int32 将是传输的前四个字节。但是,PIC 可能具有不同的字节顺序,因此您最终可能会从 PIC 发送 0x12345678,并在接收端读取值 0x78563412。

至于其余结构成员的寻址,您的编译器可以自由地在每个成员之间添加填充。通常这是为了优化内存访问而做的事情。

如果您有可能从 PIC 中获取一些文本输出,则可以使用 stddef.h 中的 offsetof() 宏获取结构成员的偏移量:

fprintf(stderr, "num2 offset=%d\n", offsetof(RecordStructure, num2));
fprintf(stderr, "num3 offset=%d\n", offsetof(RecordStructure, num3));
于 2012-09-25T20:48:12.630 回答
1

数据在结构中的对齐方式可能因编译器以及用于强制特定对齐的编译指示而异。

如果此编译器在双字边界上对齐项目,则前 4 个字节 num1 应与 char 数组的前 4 个字节对齐,后 4 个字节 num2 应与 char 数组的后 4 个字节对齐,等等。

如果可能,您可以做的是在收到数据时使用调试器检查数据。在发送的数据中,您放置一个特定的十六进制数字序列,这样您就可以知道事情是否按照您的想法排列。

所以在 PIC 结构中发送的数据可能是:

RecordStructure myRecord;
myRecord.num1 = 01F2E3D4C;
myRecord.num5 = myRecord.num4 = myRecord.num3 = myRecord.num2 = 0;

然后把它发过去看看它是什么样子的。以及num1的值是否相同。

如果您随后修改数据,例如如果 myRecord.num3 = 1.0,您将能够看到事情是否对齐。

于 2012-09-25T20:46:49.133 回答
1

是的。前四个字节将属于 num1,然后接下来的四个字节将属于 num2,依此类推。但是,int 和 float 中的字节顺序是特定于平台和实现的。

然而,有两个主要因素会影响这一点。一个是对齐,另一个是填充。确保将填充设置为 1 字节,以确保变量之间没有内存间隙,并尽可能将对齐设置为 1。但是根据您的编译器和硬件,对齐可能必须是 4 或 8 字节的倍数。在这种情况下,您可能需要添加一些填充变量。您可以使用 MSVC 中的 align 关键字和 GCC 中的对齐属性来更改每个结构/变量的默认对齐方式:

__declspec(align(1)) //MSVC
__attribute__((aligned(1))) //GCC

例子:

#pragma pack(1)
typedef struct{int32 num1;
              float num2,num3,num4,num5;
              ...
              }RecordStructure;

typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;
于 2012-09-25T20:51:59.223 回答
1

这个例子展示了~RecordStructure~ 的相同定义如何在PC (Linux/x86/gcc) 和PIC(18F) 两端使用。诀窍是用来#ifdef / #define支持两个编译器。

#ifdef __cplusplus
# define __PACKED
# define __PACKED2 __attribute__((packed))
#else
# define __PACKED2
#endif


typedef struct __PACKED {
    opcodes_t opcode : 8;
    union {
        osci_config_t set_config_args;
        READ_SINGLE_ARGS read_single_args;
        SAMPLE_SINGLE_ARGS sample_single_args;
        SAMPLE_INTERLEAVED_ARGS sample_interleaved_args;
    } args;
} __PACKED2 opcode_decoder_t;
于 2012-09-25T21:03:39.347 回答