2017-05-06 7 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番目のビットをHighに設定していることを理解していますが、!!の意味は何ですか。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のあなたの定義は何であるか知っているが、彼らはそれを私はそれが1ビットであると仮定し、バイト間で8時間を歩いていることから、それはおそらく、正または負のを可能にしていますポート上のロジックは、0または1と考えることができます。

HIGHが1の場合は0x01を、HIGHの場合はすべて0x00を取得します。したがって、anytingを実行していないようです。例えば、& &の場合は、ビット単位の論理ではないブール式ですので、これは誤字でしょうか?

val&(HIGH<<i)かなり簡単ですが、やはりHIGHが定義されているものを投稿しておく必要があります。 0から7になるループiがあります。つまり、あなたは1<<0でANDing(ビット単位)をしてから1<<1、次に1<<2というようになります。 1<<0はちょうど1ですか? val&(1<<0)は、& 0x01と同じです。 1<<1 = 0x02 so val & 0x02。このコードはvalの個々のビットを分離する時に1ビットです。たとえば、valが0x07の場合、0x07 & 0x02 = 0x02?あなたは、あなたが垂直方向に一度に一つの列を分離し、両方のオペランドが1でない限り、基本的には結果が0であると言い、真理表を使用してこれを見て0x07の= 0b00000111、0x02の= 0b00000010

00000111 
&00000010 
========= 
00000010 

各ビットをラインアップ1つの列があり、両方のオペランドが1であるため、その列の結果は1であり、他の1つのオペランドまたは両方のオペランドまたはその両方はゼロであり、結果はその列に対してゼロです。

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

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

インクリメントI 2回以上と0x07ののvalのに対して評価して、あなたはHIGHが、あなたは、常にゼロが出てしまいます0であればHIGHは、1であると仮定するとval&(HIGH<<i)で少なくとも何が起こっているのかを見ますこのコードの。

ウォーキングをしたいと思っているのなら、val &をHIGHにしてはいけません。そうしないと、そのペリフェラルやそのポートの反対側にあるものが、 。

ダブルバン(!!)は私にとっては論理的な操作のように見え、ここでは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); 
} 

ここに希望は、我々は、コンパイラが偽のために$ 00を生成します知っているだろうが、それは本当のために何を生成するのでしょうか? 0x01、0xFF、C言語にはおそらく定義があります。したがって、上記のコードは、私たちの価値最下位ビット位置では

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

に基づいてビットストリームをgenratingされ、ループは、クロックをくすぐります。

私の個人的な好みは、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 

すべてのビット演算、無ブール真/偽の操作を使用します。

0以外のビットを0ビットの位置にシフトするために2つのブールノットを実行しようとしていたかどうかわかりません... lsbitが先に、または7-iが最初にmsbitです。

#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の最初のelse条件が7,6,5,4,3,2,1,0からlsbitの最初の0,1,2,3,4,5,6から1を歩いていることを理解できます。ビット7までは分離しているので、これは一度に1ビット、おそらくはビットシフターを分離しようとしています。私の単純なプログラムが示しているように(もしあなたがHIGHを1にすると、少なくとも別のコンパイラとビットを分離しないので、これが移植性のあるCならそれは意味をなさない)。 –

関連する問題