geschachtelte if Abfrage auf AVR Pins

Gast #4417660
Lesenswert?

Hallo,

ich versuche zu überprüfen, ob alle gennanten 9 Pins an einem AVR auf 
High sind. Leider ist wohl etwas an meiner Syntax falsch, ich bekomme 
nur nicht raus was es ist.

Könnt ihr mir evtl. weiterhelfen?

if (((PINC & (1<<PINC4)) && (PINC & (1<<PINC5)) && (PINC & (1<<PINC6)) 
&& (PINC & (1<<PINC7)) && ((PIND & (1<<PIND4)) && ((PIND & (1<<PIND5)) 
&& ((PIND & (1<<PIND6)) && ((PIND & (1<<PIND7)) && ((PINA & (1<<PINA4)))
{Anweisung;}
Gast #4417868
Lesenswert?

Wenn man das vernünftig (und lesbar) formatiert sieht man recht schnell, 
wo es hakt ...
1
if ( ((PINC & (1<<PINC4)) &&  (PINC & (1<<PINC5)) &&  (PINC & (1<<PINC6)) &&
2
      (PINC & (1<<PINC7)) && ((PIND & (1<<PIND4)) && ((PIND & (1<<PIND5)) &&
3
     ((PIND & (1<<PIND6)) && ((PIND & (1<<PIND7)) && ((PINA & (1<<PINA4))    )
4

5
{Anweisung;}
#4418067
Lesenswert?

Wenn man das ganze so schreibt:
1
if ( (PINC & ((1<<PINC4)|(1<<PINC5)|(1<<PINC6)|(1<<PINC7)) ) &&
2
     (PIND & ((1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7)) ) && 
3
     (PINA & ((1<<PINA4))    
4
   ) {
5
       Anweisung;
6
     }
dann ist klarer, was man eigentlich vor hat.
 Zudem sind PINx als volatile deklariert, d.h. der Compiler müßte jede 
Benutzung mit einem Zugriff umsetzen. Die Varante mit Maske, siehe hier, 
nur einmal je PINx.
Ich nehme mal an, daß Feinheiten im Einlese-Timing hier nicht 
interessant sind, da ja die exakte Reihenfolge der "Vergleiche" eh nicht 
bestimmbar ist.
#4418155
Lesenswert?

Carl D. schrieb:
> da ja die exakte Reihenfolge der "Vergleiche" eh nicht bestimmbar ist.

Doch, die Reihenfolge ist gegeben, da && und || in C einen Sequence 
Point darstellen. Hier
1
if((a == b) && (c == d)) {}
wird der Vergleich a == b vor c == d ausgeführt und wenn der erste 
Vergleich falsch ist, der zweite nicht ausgeführt. Das kann man z.B. für 
folgendes Verwenden:
1
if((x != NULL) && (*x == 123)) {}
So ist sichergestellt, dass, falls x gleich NULL ist, der Zeiger nicht 
dereferenziert wird.


Edit: Ansonsten gebe ich dir zu 100% Recht, es ist übersichtlicher und 
man läuft nicht in die Gefahr, dass der Port zwischen den einzenlen 
Vergleichen den Zustand wechselt. Je nach Anwendung ist das aber auch 
egal.
#4418285
Lesenswert?

be s. schrieb:
> Das kann man z.B. für folgendes Verwenden:
>
1
if((x != NULL) && (*x == 123)) {}
> So ist sichergestellt, dass, falls x gleich NULL ist, der Zeiger nicht
> dereferenziert wird.

Das stimmt!

Die "Einzelbit-Abfrage" sollte wegen den volatilen PINs auch zu deutlich 
mehr Code führen. Im konkreten Fall 9 PIN Zugriffe statt 3 bei 
"gruppiert". War aber bisher zu faul den GCC anzuwerfen, um das genauer 
zu untersuchen.
#4418296
Lesenswert?

Carl D. schrieb:
> Wenn man das ganze so schreibt:
>
1
> if ( (PINC & ((1<<PINC4)|(1<<PINC5)|(1<<PINC6)|(1<<PINC7)) ) &&
2
>      (PIND & ((1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7)) ) &&
3
>      (PINA & ((1<<PINA4))
4
>    ) {
5
>        Anweisung;
6
>      }
das wird so für den gewünschten Zweck nicht funktionieren, denn das 
Ergebnis der UND-Verknüpfung zwichen PINx und Maske ist immer dann 
ungleich Null wenn eines der Bits in der Maske HIGH ist.
Es müsste dann:
1
(PINC & ((1<<PINC4)|(1<<PINC5)|(1<<PINC6)|(1<<PINC7)))==((1<<PINC4)|(1<<PINC5)|(1<<PINC6)|(1<<PINC7))
so aussehen

Sascha
#4418405
Lesenswert?

Stimmt auch wieder.
Dann aber am besten so:
1
#define MASK_A       ((1<<PINC4))
2
#define MASK_C       ((1<<PINC4)|(1<<PINC5)|(1<<PINC6)|(1<<PINC7))
3
#define MASK_D       ((1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7))
4

5
if( ((PINA & MASK_A) == MASK_A) &&
6
    ((PINC & MASK_C) == MASK_C) &&
7
    ((PIND & MASK_D) == MASK_D) )
8
{
9
   // ...
10
}
Damit sind bei Bedarf nur die Defines anzupassen. Und wer will und 
entsprechende Compilerunterstützung hat, darf sie auch als
1
static const uint8_t MASK_x = ...
schreiben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren