2017-05-06 113 views
-1

我入门学习更多关于AVR ATMEGA编程。
阅读有关Arduinos的内部工作原理的文章,我学习了shiftOut方法是如何构成的。我是那种为位操作的熟悉,到目前为止,但我有一个表情我不明白尚未:位运算使用移位寄存器

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) 
{ 
    uint8_t i; 

    for (i = 0; i < 8; i++) { 
     if (bitOrder == LSBFIRST) { 
      PORTD |= !!(val & (HIGH << i)); 
     } else { 
      PORTD |= !!(val & (HIGH << (7 - i)));   
     } 
     PORTB |= (HIGH << clockPin); 
     PORTB ^= (HIGH << clockPin); 
    } 
} 

线PORTD |= !!(val & (HIGH << i));不是100%我清楚。我知道我在PORTD上设置第i位高,但!!是什么意思,val&(HIGH <<i))

我知道这可能听起来很基本,但你能帮我解决吗?

+0

对我来说很难过。 –

+0

你是什么意思? – sesc360

+0

这是Arudino'wiring_shift.c'的原始代码,除了1已被更改为HIGH – sesc360

回答

0

试试看:

#include <stdio.h> 
#define HIGH 0 
int main (void) 
{ 

    unsigned char i; 
    unsigned char PORTD; 
    unsigned char val; 

    PORTD=0; 

    for(val=3;val;val<<=1) 
    { 
     printf("0x%02X\n",val); 
     for(i=0;i<8;i++) 
     { 
      PORTD |= !!(val & (HIGH << i)); 
      printf("PORTD 0x%02X\n",PORTD); 
     } 
    } 
    return(0); 
}   

我不知道你HIGH的定义是什么,但因为它们是跨字节走这8时间,我认为它是一个位,这也许能够提供正或负端口上的逻辑,所以可能是0或1我想。

我得到的所有0×01,如果HIGH为1,所有为0x00,如果高为0,因此似乎没有做点儿什么。当你有& &例如这是一个布尔表达式不按位逻辑,也许这是一个错字?

val&(HIGH<<i)虽然很简单,但您应该发布HIGH被定义为什么,让我们假设它是1,因为这相对于代码的其余部分是最有意义的。有一个循环我是从0到7而去,这意味着你是安定(位)与1<<0然后1<<1然后1<<2等。 1<<0只是1个权利?因此val&(1<<0)与val & 0x01相同。 1<<1 = 0x02 so val & 0x02。这段代码每隔一位就会隔离val中的各个位。你明白,如果例如val是0x07然后0x07 & 0x02 = 0x02?你行的每一位达0x07的= 0b00000111,0×02 = 0b00000010

00000111 
&00000010 
========= 
00000010 
你看这一次垂直隔离一列,并使用真值表基本上说,结果是0,除非两个操作数均为1

,有一列的两个操作数是1,所以该列的结果是1,其余列的一个或另一个操作数或两者都是零,因此该列的结果为零。

00000111 
&00000100 
========= 
00000100 

00000111 
&000010000 
========= 
00000000 

递增我两次,评估对的0x07的一个VAL和你看到的是与val&(HIGH<<i)至少发生假设HIGH是1,如果高是0,那么你总是会得到零问世这段代码。

如果你想和一个走一个你为什么不只是做VAL &高,所以这同样没有道理,除非是外围或什么是该端口的另一端在同一时间的事情希望这一个位。

双爆(!!)对我来说看起来像一个逻辑操作,在这里没有业务IMO。

单爆炸是一个逻辑运算

#include <stdio.h> 

#define HIGH 1 

int main (void) 
{ 

    unsigned char i; 
    unsigned char PORTD; 
    unsigned char val; 

    PORTD=0; 

    val=3; 
    { 
     printf("0x%02X\n",val); 
     for(i=0;i<8;i++) 
     { 
      PORTD |= !(val & (HIGH << i)); 
      printf("PORTD 0x%02X\n",PORTD); 
     } 
    } 
    return(0); 
} 

这里的希望是,我们知道编译器将生成0x00作为一个假的,但到底是什么它产生的是真的吗? 0x01,0xFF,C语言可能有一个定义。所以上面的代码是genrating基于我们的价值

PORTD 0x00 
PORTD 0x00 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 

在位置,所以LSb的比特流,该循环发痒的时钟。

我个人的偏好不会玩与C语言规范的游戏,但要明确你想要做什么:

#include <stdio.h> 
#define HIGH 1 
int main (void) 
{ 

    unsigned char i; 
    unsigned char PORTD; 
    unsigned char val; 

    PORTD=0; 

    val=3; 
    { 
     printf("0x%02X\n",val); 
     for(i=0;i<8;i++) 
     { 
      PORTD |= (~(val>>i))&1; 
      printf("PORTD 0x%02X\n",PORTD); 
     } 
    } 
    return(0); 
}   

PORTD 0x00 
PORTD 0x00 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 
PORTD 0x01 

使用的所有位操作,没有布尔真/假操作。

想知道他们是否试图做两个布尔穷人连续的不为零的位第一或7 - 我第一次转移到零位位置或东西...而不是为为,所以LSb最高位。

#include <stdio.h> 
#define HIGH 1 
int main (void) 
{ 

    unsigned char i; 
    unsigned char PORTD; 
    unsigned char val; 

    PORTD=0; 

    val=3; 
    { 
     printf("0x%02X\n",val); 
     for(i=0;i<8;i++) 
     { 
      PORTD |= (val>>i)&1; 
      printf("PORTD 0x%02X\n",PORTD); 
     } 
    } 
    return(0); 
}   
+0

所以你可以理解我希望msbit的第一个条件是从7,6,5,4,3,2,1,0行走一个lsbit的第一个0,1,2,3,4,5,6, 7只要位和隔离,所以这是试图一次隔离一个位,也许是一个移位器。但是正如我简单的程序演示的那样(如果你使HIGH为1,它至少不会与另一个编译器隔离,所以如果这是可移植的C,它没有多大意义)。 –