2017-05-06 2 views
-1

Je commence à en savoir plus sur la programmation AVR ATMEGA.
En lisant un article sur le fonctionnement interne d'Arduinos, j'apprends comment la méthode shiftOut est structurée. Je suis un peu familier avec les opérations de manipulation de bits jusqu'à présent, mais j'ai une expression que je ne comprends pas encore:Opérations bit à bit utilisant des registres à décalage

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); 
    } 
} 

La ligne PORTD |= !!(val & (HIGH << i)); n'est pas 100% clair pour moi. Je comprends que j'ai mis le bit High sur PORTD mais que signifie le !! et val&(HIGH <<i))

Je sais que cela peut paraître basique, mais pouvez-vous m'aider s'il vous plaît?

+0

m'a l'air brisé. –

+0

Que voulez-vous dire? – sesc360

+0

Ceci est le code original de l'Arudino 'wiring_shift.c' sauf que 1 a été changé pour HIGH – sesc360

Répondre

0

juste essayer:

#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); 
}   

Je ne sais pas ce que votre définition de HIGH est mais comme ils marchent il 8 fois à travers un octet je suppose qu'il est un peu, il permet à peut-être positif ou négatif logique sur le port, donc pourrait être un 0 ou 1 je pense.

Je reçois tout 0x01 si HIGH est 1 et tout 0x00 si HIGH est 0. donc il ne semble pas faire quoi que ce soit. Lorsque vous avez & & par exemple, c'est une expression booléenne qui n'est pas logique, donc c'est peut-être une faute de frappe? Le val&(HIGH<<i)val&(HIGH<<i) est assez simple, encore une fois vous devriez avoir posté ce que HIGH a été défini comme, supposons que c'est un 1 puisque c'est le plus logique par rapport au reste du code. Il y a une boucle i qui va de 0 à 7. donc cela signifie que vous êtes anding (bitwise) avec 1<<0 puis 1<<1 puis 1<<2 et ainsi de suite. 1<<0 est juste 1 pas vrai? donc val&(1<<0) est le même que val & 0x01. 1<<1 = 0x02 donc val & 0x02. ce code est un bit à la fois isolant les bits individuels dans val. vous comprenez que si par exemple val est 0x07 alors 0x07 & 0x02 = 0x02? vous en ligne chaque bit jusqu'à 0x07 = 0b00000111, 0x02 = 0b00000010

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

vous regardez cette verticale isoler une colonne à la fois et utiliser la table de vérité qui dit essentiellement le résultat est 0 à moins que les deux opérandes sont 1, il y a une colonne où les deux opérandes sont un 1 donc le résultat pour cette colonne est un 1, le reste des colonnes l'un ou l'autre opérande ou les deux est un zéro donc le résultat est nul pour cette colonne.

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

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

Incrémenter i deux fois plus et évaluer contre un val de 0x07 et vous voyez ce qui se passe au moins avec le val&(HIGH<<i) en supposant que HIGH est un 1, si HIGH est un 0 alors vous obtiendrez toujours des zéros sortent de ce code. Si vous voulez et avec un piéton, pourquoi ne faites-vous rien? & HIGH, donc encore une fois cela n'a de sens que si ce périphérique ou ce qui est à l'autre extrémité de ce port désire cette chose un peu à la fois .

Le double bang (!!) ressemble à une opération logique pour moi et n'a aucune affaire ici IMO.

Un seul coup est une opération logique

#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); 
} 

L'espoir ici serait que nous savons que le compilateur génère 0x00 pour un faux, mais qu'est-ce qu'il générons un vrai? 0x01, 0xFF, le langage C a probablement une définition. Ainsi, le code ci-dessus est générent un flux binaire en fonction de notre valeur

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

En position LSBit, la boucle chatouille une horloge.

Ma préférence personnelle ne serait pas jouer à des jeux avec la spécification du langage C, mais explicite à ce que vous voulez faire:

#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 

en utilisant toutes les opérations au niveau du bit, pas booléennes opérations vrai/faux. Je me demandais s'ils essayaient de faire deux booléens non alignés pour décaler le bit non nul vers la position zéro ou quelque chose ... au lieu de lsbit en premier ou 7-i pour msbit en premier.

#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

de sorte que vous pouvez comprendre J'espère que la première condition de msbit est marcher un à partir de 7,6,5,4,3,2,1,0 le premier lsbit 0,1,2,3,4,5,6, 7 aussi loin que le bit et l'isoler, donc c'est essayer d'isoler un peu à la fois, peut-être un peu décalé. mais comme mon programme simple le démontre (si vous faites un a 1 élevé, il n'isole pas les bits au moins avec un autre compilateur, donc si c'était portable C ça n'a pas beaucoup de sens). –