我有一个功能正在搜索九个" 1"在64位变量(RFID标签号)中,如果找到,将它们移动到MSB。 理解为什么它不能正常工作我有一个很大的问题。
这是我的变量
uint64_t volatile RFID_data2= 0b1111111110000000000000000000000000000000000000000000000000000000;
我发送它作为函数的指针
test_flag= header_align(&RFID_data2);
uint8_t header_align(uint64_t *data){
uint64_t bit_mask=(uint64_t)
0b1111111110000000000000000000000000000000000000000000000000000000;
if((*data&bit_mask)==bit_mask){
PORTA ^= (1<<PORTA2);
return 1;
}
这种情况永远不会实现,但如果我改变了这个条件:
if((*data==bit_mask){
PORTA ^= (1<<PORTA2);
return 1;
}
它似乎运作良好。
我还写了另一个条件 - 这是有效的。
if((*data&bit_mask)>(bit_mask-1) && (*data&bit_mask)<(bit_mask+1 )){
PORTA ^= (1<<PORTA2);
return 1
我可以看到AND&#39;&amp;&#39;操作。另外,当我将RFID_data更改为32位变量时没有任何问题。我正在使用Attiny441和GCC编译器,Atmel Studio 有没有办法让它在64位上工作?
我改变了函数以取uint64t(非指针),但问题仍然存在。我也尝试创建全局变量,并删除volatile变换器,但它仍然无法正常工作。 使用宏UINT64_C也没有帮助。 它看起来像:
uint64_t RFID_data;// global var
int main(void)
{
RFID_data=(0xFF80000000000000);// write into global var
uint64_t RFID_data2=(0xFF80000000000000);
while(1)
{
test_flag=header_align(RFID_data2);// send local variable
}
}
uint8_t header_align(uint64_t data){
uint64_t bit_mask = UINT64_C(0xFF80000000000000);
if((data&bit_mask)==bit_mask){
PORTA ^= (1<<PORTA2);//nothink
return 1;
}
我还尝试通过全局变量检查if-condtion:
if((RFID_data&bit_mask)==bit_mask){
PORTA ^= (1<<PORTA2);///nothink
return 1;
}
两种方式都没有返回1,也没有改变PORTA2状态。
仅当我在header_allgin中创建一个新的局部变量时才有效,如下所示:
uint8_t header_align(uint64_t data){
uint64_t RFID_data3 = UINT64_C(0xFF80000000000000);
uint64_t bit_mask = UINT64_C(0xFF80000000000000);
if((RFID_data3&bit_mask)==bit_mask){
PORTA ^= (1<<PORTA2);// here i can see signal
return 1;
}}
是通过全局变量还是通过功能参数来使其工作?
答案 0 :(得分:1)
只需使用正确的后缀。
L for int32
LL for int64
UL for uint32
uint64的ULL
答案 1 :(得分:1)
好像你在这里发现了一个真正的编译器错误!
GCC版本:
avr-gcc(GCC)4.8.1
(启用-O1或-O2优化,在-O0,问题似乎不存在)
减少测试用例:
#include <stdint.h>
uint8_t volatile tmp;
__attribute__((noinline)) void test_64(uint64_t d64)
{
if ((d64 & 0xFF800000UL) == 0xFF800000UL){
tmp ++;
}
}
__attribute__((noinline)) void test_32(uint32_t d32)
{
if ((d32 & 0xFF800000UL) == 0xFF800000UL){
tmp ++;
}
}
int main(void)
{
test_64(0);
test_32(0);
while(1);
}
关键部分的汇编程序输出:
00000228 <test_64>:
228: 08 95 ret
0000022a <test_32>:
22a: 66 27 eor r22, r22
22c: 77 27 eor r23, r23
22e: 80 78 andi r24, 0x80 ; 128
230: 61 15 cp r22, r1
232: 71 05 cpc r23, r1
234: 80 48 sbci r24, 0x80 ; 128
236: 9f 4f sbci r25, 0xFF ; 255
238: 09 f0 breq .+2 ; 0x23c <test_32+0x12>
23a: 08 95 ret
23c: 80 91 00 20 lds r24, 0x2000
240: 8f 5f subi r24, 0xFF ; 255
242: 80 93 00 20 sts 0x2000, r24
246: 08 95 ret
00000248 <main>:
248: 20 e0 ldi r18, 0x00 ; 0
24a: 30 e0 ldi r19, 0x00 ; 0
24c: 40 e0 ldi r20, 0x00 ; 0
24e: 50 e0 ldi r21, 0x00 ; 0
250: 60 e0 ldi r22, 0x00 ; 0
252: 70 e0 ldi r23, 0x00 ; 0
254: 80 e0 ldi r24, 0x00 ; 0
256: 90 e0 ldi r25, 0x00 ; 0
258: 0e 94 14 01 call 0x228 ; 0x228 <test_64>
25c: 60 e0 ldi r22, 0x00 ; 0
25e: 70 e0 ldi r23, 0x00 ; 0
260: cb 01 movw r24, r22
262: 0e 94 15 01 call 0x22a ; 0x22a <test_32>
266: ff cf rjmp .-2 ; 0x266 <main+0x1e>
<强>观察强>
对于32位,生成正确的代码。对于64位,根本不进行比较,代码编译好像if
的结果总是为假。本机GCC正确编译这两个函数。
您应该避免在代码中使用64位变量。
该错误现已在GCC错误跟踪器中得到确认,您可以在此处关注:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85805
因此,在撰写本文时,所有足够现代的avr-gcc版本都会受到影响,直到修复完毕。
答案 2 :(得分:0)
将常量强制转换为uint64_t
并不是制作uint64_t
字面值的正确方法。您应该使用UINT64_C
宏代替:
uint64_t bit_mask = UINT64_C(0b1111111110000000000000000000000000000000000000000000000000000000);
或者如果你喜欢hex
uint64_t bit_mask = UINT64_C(0xFF80000000000000);