Bitabfragen:
Ich habe ein kleines C-Programm für einen ATMEL ATMEGA 8-16 geschrieben.
Weil ich noch keine tiefgreifenden Kenntnisse habe, probiere ich halt
gerne mal etwas aus, indem ich ein Programm etwas umgestalte. Das soll
heißen, dass ich Abfragen, die mir unübersichtlich erscheinen, auch mal
in eine andere Form zu bringen versuche. Habe mir einige
Programmiervorschläge angesehen und versuche diese dann anzuwenden.
Dabei bin ich auf ein kleines Problem gestoßen, da ich der Meinung bin,
dass folgende Statements eigentlich äquivalent sein müssten, aber leider
der Programmablauf später das Gegenteil zeigt.
*Die folgende Abfrage funktioniert einwandfrei:*
while (PIND & ((1 << PIND0) | (1 << PIND1)))
/* Wenn Bit 1 (PIND0) ODER Bit 2 (PIND1) gesetzt ist wird die Schleife
ausgeführt */
*Die nächste Abfrage funktioniert merkwürdigerweise nicht:*
if (PIND & ((1 << PIND0) & (1 << PIND1)))
/* Wenn Bit 1 (PIND0) UND Bit 2 (PIND1) gesetzt sind wird die Anweisung
ausgeführt */
Bzw.
while (PIND & ((1 << PIND0) & (1 << PIND1)))
/* Wenn Bit 1 (PIND0) UND Bit 2 (PIND1) gesetzt sind wird die Schleife
ausgeführt */
Warum ist das so ?
Die Abfrage mit „ODER“ funktioniert, die mit „UND“ aber nicht.
*Ändere ich die Abfrage aber um in:*
if ((PIND & 0x03) == 0x03)
bzw.
while ((PIND & 0x03) == 0x03)
dann funktioniert die „UND“-Abfrage einwandfrei !!!
Was mache ich denn hier verkehrt ?...
Hab schon alles Mögliche ausprobiert…. Bin aber leider kein Profi,
habe gerade erst mit der Programmierung in C nach 15 Jahren wieder
angefangen, hatte vorher ein bissl mit Assembler programmiert, aber auch
nur Amateurmäßig….
Ich wäre für einen kleinen Tipp sehr dankbar…..
Ja, genau das versuche ich ja, indem ich mal was ausprobiere...
Ist nicht so easy wenn man jahrelang nix gemacht hat.. jedenfalls
sehen für mich die Bedingungen der UND-Verknüpfung gleich aus.... soll
heißen...
if ((PIND & 0x03) == 0x03) ist für mich dasselbe wie
if (PIND & ((1 << PIND0) & (1 << PIND1))), also ne 1 auf Pin D0 UND ne 1
auf Pin D1....
da ich ja bereits zugegeben habe, dass ich gerade mal wieder am anfang
stehe, hoffte ich auf einen hinweis....
ist schon schwer, wenn man alleine alles rausfinden muss... noch
schwieriger ist es, wenn man antworten bekommt, die wenig hilfreich
sind, obwohl die guten leute offenkundig des rätsels lösung wissen, aber
nicht bereit sind, sie preiszugeben....
LG
Duffy
Hi, André,
> *Die folgende Abfrage funktioniert einwandfrei:*>> while (PIND & ((1 << PIND0) | (1 << PIND1)))> /* Wenn Bit 1 (PIND0) ODER Bit 2 (PIND1) gesetzt ist wird die Schleife> ausgeführt */>
PIND, PIND0 und PIND1 sind Makros.
Was bedeuten die denn?
Schrecklich wäre, wenn PIND eine Portadresse bezeichnet, PIND0 und PIND1
aber nur die Nummer eines Pins im Port.
Wenn ich den Pegel an einem bestimmten Pin eines Ports abfragen will,
dann lese ich den, beispielsweise mit while(bit_is_clear(PIND, 0)) ...;
Logik üben ist ja fein, aber besser erst mal mit Zahlen statt mit
unklaren Ausdrücken.
Ciao
Wolfgang Horn
(PIND & 0x03) == 0x03 ist genau dann erfüllt, wenn beide Bits 0
(...0001) und 1 (...0010) gesetzt sind, andere Bits sind egal.
Für PIND & ((1 << PIND0) & (1 << PIND1)) ist erstmal (1 << PIND0) & (1
<< PIND1) nötig.
(1 << PIND0) & (1 << PIND1) heißt: ...0001 binär verUNDet mit ...0010.
Und das ist immer.
Diese 0 wird mit PIND verUNDet, was ebenfalls immer 0 gibt, egal was in
PIND steht.
Meintest du (1 << PIND0) | (1 << PIND1) statt (1 << PIND0) & (1 <<
PIND1)?
Dann wären die beiden Ausdrücke schon ähnlicher, auch wenn immer noch
nicht gleichwertig (weil im zweiten Fall bereits eines der Bits für
insgesamt "wahr" reicht).
Also, nochmal, was sagt uns UND?
A B E
0 0 0
0 1 0
1 0 0
1 1 1
in Worten: Nur wahr, wenn alle Bedingungen wahr sind.
und dann sollte dir noch die ODER-Verknüpf. bekannt sein:
A B E
0 0 0
0 1 1
1 0 1
1 1 1
in Worten: Bereits wahr, wenn mindestens eine Bedingung wahr ist.
Logische Bit-Verknüpfungen: & (UND) | (ODER)
Logische Verknüpfungen: && (UND) || (ODER)
André Derfert schrieb:> if ((PIND & 0x03) == 0x03) ist für mich dasselbe wie>> if (PIND & ((1 << PIND0) & (1 << PIND1))), also ne 1 auf Pin D0 UND ne 1> auf Pin D1....
Für dich vielleicht, aber für einen Compiler ist das was ganz
unterschiedliches. Das Problem ist, daß du nicht logisch (im Sinne
boole'scher Logik), sondern umgangssprachlich denkst. Du willst
abfragen, ob PIND0 UND PIND1 gesetzt sind, also schreibst du eine
UND-Verknüpfung hin. Aber das ist falsch.
Bei
1
(1<<PIND0)&(1<<PIND1)
wrd jedes einzelne Bit aus 1 << PIND0 mit dem entsprechenden Bit aus 1
<< PIND1 UND-Verknüpft. Als Ergebnis kommt dann ein Wert mit den
dazugehörigen Ergebnis-Bits raus. Da sind dann nur die Bits 1, die auch
in beiden Eingangswerten 1 sind. Die Rechnung sieht dann etwa so aus:
1
1 << PIND0 = 1 << 0 = 00000001
2
1 << PIND1 = 1 << 1 = 00000010
3
**********************************************
4
(1 << PIND0) & (1 << PIND1) = 00000000
Aus deiner Abfrage wird also ein:
1
if(PIND&0)
Und bei dieser Verknüpfung kann im Ergebnis kein Bit jemals 1 sein, da
auf der rechten Seite alle Bits 0 sind.
> ist schon schwer, wenn man alleine alles rausfinden muss...
Deshalb wurden Bücher und Tutorials erfunden, die sowas erklären.
> noch schwieriger ist es, wenn man antworten bekommt, die wenig hilfreich> sind, obwohl die guten leute offenkundig des rätsels lösung wissen, aber> nicht bereit sind, sie preiszugeben....
Die meisten Leute hier haben eben wenig Lust, vorgekaute Lösungen zu
präsentieren, sondern versuchen lieber, den Fragesteller zu animieren,
selbst auf die Lösung zu kommen.
Hmm..
Danke erst mal für die Resonanz..
@Wolfgang:
Also, für mich ist 0x03 keine Zahl, wenn ich Hex-Ausdrücke in Programmen
sehe, gehen mir immmer die Nackenhaare hoch. Nicht, weil ich damit nicht
umgehen kann, sondern weil es für mich einfach zu viel Kopfarbeit
bedeutet, wenn man mal schnell was im Programm nachvollziehen möchte.
Ich finde dann die Ausdrücke mit (1 << PINx) oder so leichter zu
verstehen als irgendein 0x3f oder so was, da rechnet man sich ja nen
heißen bei.
@Klaus:
Vielen Dank, ich glaube das hat mich einen Schritt weiter gebracht, wenn
es so ist dass (1<<PIND1) = 00000010 und (1 << PIND0) = 00000001 ist,
dann kann es natürlich nicht funktionieren.
@Christian:
Danke für die kleine Einführung in die logischen Verknüpfungen, aber ich
denke, wer die Wahrheitstabellen von UND und ODER nicht kennt, sollte eh
die Finger davon lassen, soll heißen, dass ich damit bestens vertraut
bin. Trotzdem danke.
Also, nochmal kurz zum Verständnis:
Ich suchte eine andere Form der Abfrage if ((PIND & 0x03) == 0x03)
---> (Bit 1 und Bit 2 bzw. PIND0 und PIND1 beide gleichzeitig gesetzt).
Das ist ein Zustand, der nicht vorkommen darf, weil PIND0 in meinem
Projekt bedeutet, dass ein Motor rechts herum läuft und PIND1 sorgt für
den Linkslauf. Klar, dass beides zusammen nicht passieren darf.
Also letztendlich will ich detektieren, ob Bit 1 und Bit 2 gleichzeitig
gesetzt sind, unabhängig von den restlichen Bits. Und das möglichst
nicht mit Hex- und Dezimalausdrücken, sondern auf Basis der
Bitdarstellung (1<<PINDx).
Danke, Christian,
das bedeutet aber doch, dass die Bedingung erfüllt ist, wenn nur einer
der beiden PINs High ist, oder nicht ?
Jedenfalls habe ich eine derartige Abfrage schon in meinem Programm,
weil der Controller ja auch was tun soll, wenn einer der beiden Pins
high ist (entweder Rechtslauf oder Linkslauf), und das funktioniert ja
auch soweit.
Nur wenn beide Pins high sind, dann erfolgt eine akustische
Fehlerausgabe.
Und das habe ich bislang nur hinbekommen, indem ich eine UND-Verknüpfung
mit dem Hexwert der entsprechend gesetzten Bits durchgeführt hab, wie
ich in den Beispielen schon vorher beschrieben hatte.
André Derfert schrieb:> Also, nochmal kurz zum Verständnis:> Ich suchte eine andere Form der Abfrage if ((PIND & 0x03) == 0x03)> ---> (Bit 1 und Bit 2 bzw. PIND0 und PIND1 beide gleichzeitig gesetzt).
Nun, wenn du die Wahrheitstabellen für UND und ODER kennst, dann sollte
ja klar geworden sein, daß 0x03 dem Ausdruck (1 << PIND0) | (1 << PIND1)
entspricht.
> Das ist ein Zustand, der nicht vorkommen darf, weil PIND0 in meinem> Projekt bedeutet, dass ein Motor rechts herum läuft und PIND1 sorgt für> den Linkslauf. Klar, dass beides zusammen nicht passieren darf.> Also letztendlich will ich detektieren, ob Bit 1 und Bit 2 gleichzeitig> gesetzt sind, unabhängig von den restlichen Bits. Und das möglichst> nicht mit Hex- und Dezimalausdrücken, sondern auf Basis der> Bitdarstellung (1<<PINDx).
André Derfert schrieb:> Danke, Christian,> das bedeutet aber doch, dass die Bedingung erfüllt ist, wenn nur einer> der beiden PINs High ist, oder nicht ?
Nein, denn sowas, wie PIND0 oder PIND1 sind einfach nur definierte
Zahlen, nämlich 0(PIND0) und 1 (PIND1), so, also:
1
if(PIN&((1<<PIND0)|(1<<PIND1)))
entspricht ebenfalls
1
if(PIN&((1<<0)|(1<<1)))
, welches wiederrum
1
if(PIN&(1|2))
entspricht,
1
if(PIN&0x3)
Also, der rechte Ausdruck ist immer definiert, auf High, da du ja die 1
um die Pinnummer verschiebst, der rechte Ausdruck ist daher immer wahr.
Du willst ja den linken Ausdruck überprüfen, sei PIN:
0000 00 01 , da
1
(1<<PIND0)|(1<<PIND1)
ja 0x3 und somit 0000 00 11 ist, und UND dadurch falsch ist, ist if
falsch, wenn aber PIN nun
0000 00 11 ist, und der rechte Ausdruck ja immer gleich ist, kommt wahr
raus.
Mit dem ODER von
1
(1<<PIND0)|(1<<PIND1)
verknüpft man ja nur einfach die Werte, die vorgegeben sind. Die
dadurch entstandene Maske wird mit dem PIN geUNDt und dann geschaut, ob
PIND0 und PIND1 in !! PIN !! gesetzt sind, nicht andersrum.
Vielleicht siehst du auch, dass dein if(PIN & ( (1 << PIND0) & (1 <<
PIND1))) dadurch Blödsinn ist, dann 0 und 1 UND garantiert 0 ist, du
löscht sie gegenseitig aus, da PIND0 und PIND1 ja absichtlich wohl nicht
das gleiche beinhalten.
> Nun, wenn du die Wahrheitstabellen für UND und ODER kennst, dann sollte> ja klar geworden sein, daß 0x03 dem Ausdruck (1 << PIND0) | (1 << PIND1)> entspricht.
Klar Rolf, das weiß ich schon.
Mein Problem ist, dass ich dachte dass:
if (PIND & ((1 << PIND0) & (1 << PIND1))) --- man beachte das "&"
zwischen
den PINs !!
dasselbe wäre wie
if ((PIND & 0x03) == 0x03)
Das scheint wohl aber nicht so, die Frage ist also, was genau ist dann
if (PIND & ((1 << PIND0) & (1 << PIND1))) ????
Ich tendiere dazu, anzunehmen, dass Klaus recht hatte und das ganze
folglich so zu deuten sein müsste :
if (PIND & ((00000001) & (00000010)))
Und das ergibt natürlich immer 0 !!
Danke Christian...
Aber dann dürfte mein Programm ja nicht funktionieren...
Die Abfrage um die es ging hatte ja nur den Zweck einen Fehler in meiner
Auswerteelektronik festzustellen und einen Meldung auszugeben.
Aber das gesamte Programm befindet sich in einer Schleife, die der Form
entspricht, die Du hier dargelegt hast
-- while (PIND & ((1 << PIND0) | (1 << PIND1)))
hier mal ein Ausschnitt aus dem Programm:
while(1)
{
while (PIND & ((1 << PIND0) | (1 << PIND1)))
{
if ((PIND & 0x03) == 0x03)
{
Hilfe1 = Frequenz;
Frequenz = 30;
ALARM = 1;
}
else
{
Frequenz = Hilfe1;
ALARM = 0;
}
while ((PIND & 0x03) == 0x03)
{
PORTC &= 0xFC;
ALARMTON(TONDAUER_ALARM, Frequenz); /* OUTPUT ERROR */
}
.
.
.
.
}
}
Wenn es so ist, wie Du sagst, dann dürfte mein Programm gar nichts
bewirken, da ja angeblich
die Bedingung nur dann erfüllt ist, wenn beide Pins auf High sind. Aber
das Programm macht sowohl
den Rechtslauf (PIN0 = High), als auch den Linkslauf (PIN1 = High).
Und erzwinge ich den verbotenen Zustand (Beide Pins auf High), dann geht
auch die Fehlerausgabe.
Ich bin etwas verwirrt jetzt.
André Derfert schrieb:> Das scheint wohl aber nicht so, die Frage ist also, was genau ist dann>> if (PIND & ((1 << PIND0) & (1 << PIND1))) ????
Das habe ich doch ausführlich erklärt!
André Derfert schrieb:> Aber das gesamte Programm befindet sich in einer Schleife, die der Form> entspricht, die Du hier dargelegt hast> -- while (PIND & ((1 << PIND0) | (1 << PIND1)))
Das stimmt auch nicht ganz. Wie es aussehen müßte, hab ich auch erklärt.
Wenn du keinen Bock hast, meine Antworten zu lesen, dann kann ich's auch
gleich bleiben lassen.
@Klaus
Danke sehr.. damit funktioniert es.. Hurra !
@Rolf
Sorry, aber Du bist ja nicht der Einzige, der hier was schreibt, ich
lese mir das sehr wohl durch, aber wie so oft ist es mit der
Kommunikation nicht so einfach...
Wird das Problem, dass ich schildere denn auch so verstanden, wie ich es
haben möchte ?? Manchmal scheint man auch nur aneinander vorbeizureden.
Tut mir Leid, wenn Du Dich auf den Schlips getreten fühlst, das war
nicht meine Absicht
André Derfert schrieb:> @Rolf> Sorry, aber Du bist ja nicht der Einzige, der hier was schreibt, ich> lese mir das sehr wohl durch, aber wie so oft ist es mit der> Kommunikation nicht so einfach...> Wird das Problem, dass ich schildere denn auch so verstanden, wie ich es> haben möchte ?? Manchmal scheint man auch nur aneinander vorbeizureden.> Tut mir Leid, wenn Du Dich auf den Schlips getreten fühlst, das war> nicht meine Absicht
Es hat für mich zweimal so ausgesehen, als hättest du meine Antwort gar
nicht erst gelesen, weil du Fragen gestellt hast, die ich eigentlich
schon beantwortet hatte.
Wenn dir an meiner Antwort was nicht klar ist, kannst du ja nochmal
konkret nachfragen.