我正在使用控制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
答案 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位int
和word
):
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
请注意,只要你的结构中有指针,这个技巧将不再有效。