将结构设置为AVR中的数组

时间:2013-05-23 22:08:00

标签: c struct avr

我正在使用控制RTC的AVR-atmega处理器。在atmega中,RTC的时间保存为结构:

typedef struct {
uint8_t    year;
uint8_t    month;
uint8_t    hours;
uint8_t    minutes;
"and so on..."
} time_t;

我在atmega中有一个全局变量“time”(volatile time_t * time;)。

我编写了一个C程序,通过USB将当前时间的数组发送到atmega,以便在RTC上设置正确的时间。

在atmega的USB功能中,代码如下:

time = (void *) data;

其中data是从我的C程序发送的数组与当前时间。 这是正确的方法吗? 我现在的问题是,当我尝试从atmega读取时间,即atmega返回我的结构时,我偶尔得到随机值,但大部分时间我都得到实际设置的时间。

希望我解释它有些可以理解......

由于

// Noxet

3 个答案:

答案 0 :(得分:2)

由于时间结构的对齐,您可能会看到问题。如果想要在短边或字边界上对齐它,编译器可以自由填充结构。您可以尝试通过使用__packed或#pragam pack来指示编译器不要进行任何填充。 E.g

typedef __packed struct {
uint8_t    length;
uint16_t   weight;
} Fish;

因为这个结构是3个字节宽,所以一些编译器会将它填充(在开头或结尾)以在内存中对齐它(使其为4个字节宽) - 以提高访问速度等。如果它的打包它将是严格的3字节宽。

编辑:语法可能如下所示AVR

typedef __attribute__((packed)) struct { ...

我认为Eric试图制作的(这是正确的)是你还需要考虑你的data指针的范围。如果该数据的范围有限,即在使用time的生命周期内将被释放,那么您需要将字节从数据复制到time_t结构而不是仅仅指向可能被释放的内存(正如Eric建议使用memcpy)。

答案 1 :(得分:2)

我们在这里有3个问题,我将逐一解决:

1 - alignement  在结构体中,体系结构的ABI可以指定所有值在某个任意单词边界上对齐,所以结构如下:

struct TheStruct{
    char a;
    int  man;
}

可能真的存储在内存中(假设32位intword):

char [0] 
pad  [1]
pad  [2]
pad  [3] 
int  [4]
int  [5]
int  [6]
int  [7]

这在AVR和英特尔中可能有所不同......

2 - endianness

我认为AVR和英特尔都将是小端...所以这可能不会成为一个问题,但是:

存储32位int 0x01234567的计算机可以将其存储在内存中:
[0x01] [0x23] [0x45] [0x67] big endian或
[0x67] [0x45] [0x23] [0x01]小端

3 - 网络与主机字节顺序 我真的不确定如何通过USB驱动程序对其进行整理,但是有可能再次使用uart将切换其字节序...这是字节序的子集,请参阅:wikipedia < / p>

如果我是你,我会编写代码来精确处理字节中的缓冲区:

int value1 = 0x1234567

char * buffer =  calloc(1,bufferSize);
buffer[0] = value1 & 0xff000000 > 6;
buffer[1] = value1 & 0x00ff0000 > 4;
buffer[2] = value1 & 0x0000ff00 > 2;
buffer[3] = value1 & 0x000000ff;
...

它有点令人讨厌,在组装中可能更容易做,但我认为这是获得可靠数据交换的最佳方式.. 一定要记录下来。

答案 2 :(得分:-2)

尝试类似

的内容
char data[10];
struct time_t myTime;
myTime.year = 2013; 
// ... snip
memcpy(data, myTime, sizeof(myTime)); // copy myTime to the array

要接收它,它与反转参数的操作相同

memcpy(myTime, data, sizeof(myTime)); // copy data into myTime

请注意,只要你的结构中有指针,这个技巧将不再有效。