Forum: Mikrocontroller und Digitale Elektronik geschachtelte if Abfrage auf AVR Pins


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Johannes (Gast)


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

von Falk B. (falk)


Lesenswert?

Passt soweit. Was passiert denn? Sind die Pins WIRKLICH alle HIGH?

von Johannes (Gast)


Lesenswert?

Ah habs es hinbekommen. Irgendwie bin ich mit den Klammern 
durcheinandergekommen. Dem Compiler fehlte da was :-(

von hufnala (Gast)


Lesenswert?

Hi, vielleicht zum debuggen die Ports separieren und einzeln die PINx 
werte zur Fehlersuche binaer/hex ausgeben. Dann bieten sich zur beseren 
Lesbarkeit auch noch Masken an.

//hufnala

von Falk B. (falk)


Lesenswert?

@Johannes (Gast)

>Ah habs es hinbekommen. Irgendwie bin ich mit den Klammern
>durcheinandergekommen. Dem Compiler fehlte da was :-(

Das hätte man ja wohl sagen können und die Fehlermeldung hier posten! 
Siehe Netiquette!!

von Dieter F. (Gast)


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

von Carl D. (jcw2)


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.

: Bearbeitet durch User
von B. S. (bestucki)


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.

: Bearbeitet durch User
von Carl D. (jcw2)


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.

von Sascha W. (sascha-w)


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

von Carl D. (jcw2)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.