uint64_t变量带&操作

时间:2018-04-29 21:29:03

标签: c avr atmel attiny

我有一个功能正在搜索九个" 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;
    }}

是通过全局变量还是通过功能参数来使其工作?

3 个答案:

答案 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);