Forum: Mikrocontroller und Digitale Elektronik negative Flanke in C erkennen, Erklärung gesucht


von Rene Meier (Gast)


Lesenswert?

Hallo,

könnt ihr mir bitte einmal Code erklären, bzw. warum man es so 
"kompliziert" macht (s.u.)? Im Endeffekt möchte ich eine negative Flanke 
erkennen, also einen Wechsel an einem Portpin von 1 nach 0. Dazu wird 
der Port zyklisch abgefragt und jeweils der Status der Pins gespeichert, 
somit ergibt sich für mich folgende Situation/Wahrheitstabelle:
1
^
2
I
3
1 ------------
4
I            |
5
I            |
6
I            |
7
0            ------------------
8
I
9
+---------------------------------> t
10
Abfrage  x        y
11
12
gewünschte Wahrheitstabelle
13
 x  y | Ergebnis
14
------+----------
15
 0  0 | 0
16
 0  1 | 0
17
 1  0 | 1
18
 1  1 | 0
Der Code den ich habe macht es für mich recht kompliziert:
1
  port_neu = ~PINC;
2
  port_neu &= ((1 << MASK1) | (1 << MASK4));
3
  port_flanke = (port_alt ^ port_neu) & port_neu;
4
  port_alt = port_neu;
Soweit ich das aus der Wahrheitstabelle sehe, wird doch nur ein x UND !y 
benötigt, d.h.
1
  port_neu = ~PINC;
2
  port_neu &= ((1 << MASK1) | (1 << MASK4));
3
  port_flanke = (port_alt && port_neu);
4
  port_alt = ~port_neu;
Was übersehe ich an der Stelle, bzw. warum die XOR und UND Verknüpfung?

Gruß, Rene

von Walter T. (nicolas)


Lesenswert?

Rene Meier schrieb:
> warum die XOR und UND Verknüpfung?

Deine Variante ist x && y, und nicht x && !y.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Rene Meier schrieb:
> Was übersehe ich an der Stelle, bzw. warum die XOR und UND Verknüpfung?
Lehrbuch halt: die XOR-Verknüpfung gibt an, dass eine Änderung passiert 
ist, die UND-Verknüfung bringt die Polarität zutage.

> port_flanke = (port_alt && port_neu);
Da ist jetzt aber das falsche UND drin. Du willst da nicht logisch, 
sondern bitweise operieren...

Ich würde das so schreiben, dann ist sofort klar, dass das eine fallende 
Flanke ist:
1
  port_neu = PINC;
2
  port_neu &= ((1 << MASK1) | (1 << MASK4));
3
  port_flanke = (port_alt & ~port_neu);
4
  port_alt = port_neu;
Sonst wird einem bei den vielen Tilden ja noch ganz wuschig.

Walter T. schrieb:
> Deine Variante ist x && y, und nicht x && !y.
Nein, weil er aus dem "neuen" x das "alte" !y macht.

: Bearbeitet durch Moderator
von Dergute W. (derguteweka)


Lesenswert?

Moin,

Wird wohl beides aufs Gleiche rauslaufen.

Gruss
WK

von Walter T. (nicolas)


Lesenswert?

Lothar M. schrieb:
> Walter T. schrieb:
>> Deine Variante ist x && y, und nicht x && !y.
> Nein, weil er aus dem "neuen" x das "alte" !y macht.

Stimmt. Habe ich übersehen.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Rene Meier schrieb:
> port_flanke = (port_alt ^ port_neu) & port_neu;
> Soweit ich das aus der Wahrheitstabelle sehe, wird doch nur ein x UND !y
>   port_flanke = (port_alt && port_neu);
> Was übersehe ich an der Stelle, bzw. warum die XOR und UND Verknüpfung?

... deine Variante kann nicht unterscheiden zwischen der Flanke H->L und 
L->H.

Bei dir fehlt der zeitliche Vorrang von port_neu oder prinzipiell die 
Zeitbedingung von x und y in deiner Logikttabelle. Da ja die Zustände x 
und y eine Zeitreihe sind ...

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Apollo M. schrieb:
> Bei dir fehlt der zeitliche Vorrang von port_neu oder prinzipiell die
> Zeitbedingung in deiner Logikttabelle.
Laut Diagramm: x ist alt und y ist neu.
Man hätte natürlich auch "alt" und "neu" in die Logiktabelle schreiben 
können, aber x und y hat man eben in der Schule so gelernt... ;-)

: Bearbeitet durch Moderator
von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Lothar M. schrieb:
> an hätte natürlich auch "alt" und "neu" in die Logiktabelle schreiben
> können,
... das ändert nichts.

a && !b == !b && a, es gilt das Assoziativgesetz!
Daraus folgt doch schon "optisch", dass die Erkennung nicht 
flankenselektive sein kann.

von Walter T. (nicolas)


Lesenswert?

Apollo M. schrieb:
> Daraus folgt doch schon "optisch", dass die Erkennung nicht
> flankenselektive sein kann.

alt & !neu ist flankenselektiv. Das folgt doch schon "optisch", dass die 
Logik-Tabelle von UND nicht gleichverteilt ist. (SCNR)

: Bearbeitet durch User
von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Walter T. schrieb:
> alt & !neu ist flankenselektiv. Das folgt doch schon "optisch", dass die
> Logik-Tabelle von UND nicht gleichverteilt ist.

... dann musst du ABER synchronisiert mit dem richtigen Zustand starten.
Mach mal vor, wie das gehen soll!

von Hugo H. (hugohurtig1)


Lesenswert?

Rene Meier schrieb:
> Im Endeffekt möchte ich eine negative Flanke
> erkennen, also einen Wechsel an einem Portpin von 1 nach 0. Dazu wird
> der Port zyklisch abgefragt

Da Du Dich lt. Code ja vermutlich auf einem AVR MC bewegst - was spricht 
gegen die Nutzung eines Interrupts (statt ständig zu pollen)? Auf einem 
ATMEGA328 z.B. könntest Du INT0 oder INT1 direkt auf die 
Flankenerkennung eistellen, PCINT halt nur generell auf einen Wechsel - 
aber da brauchst Du dann nur noch zu schauen ob der aktuelle Zustand 
"LOW" ist.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Hugo H. schrieb:
> PCINT halt nur generell auf einen Wechsel -
> aber da brauchst Du dann nur noch zu schauen ob der aktuelle Zustand
> "LOW" ist.

Das entspricht genau dem hier:
port_flanke = (port_alt ^ port_neu) & port_neu;

Interrupt geht immer und ist "schicker", nur pollen ist halt weit 
verbreitet wegen c&p ... und eher Hardware/Plattform unabhängiger!

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Apollo M. schrieb:
> ... dann musst du ABER synchronisiert mit dem richtigen Zustand starten.
> Mach mal vor, wie das gehen soll!

Wo liegt das Problem? Intialisierung:
static bool alt = false;

(Ist beim Beispiel mit XOR aber auch nötig.)

Erzeugt beim Start nie eine falsch positiv erkannte Flanke, egal wie 
"neu" aussieht. Dass eine fallende Flanke vor dem Programmstart nicht 
erkannt wird, dürfte verschmerzbar sein.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Walter T. schrieb:
> Wo liegt das Problem? Intialisierung:
> static bool alt = false;

... das Problem ist, dass das Signal am Port asynchron ist und dadurch 
jederzeit eine anfängliche Synchronisierung wieder verloren geht. Du 
kannst nicht beliebig in die Zeitreihe reinspringen ... Es ist quasi ein 
Zustandsautomat.

Walter T. schrieb:
> (Ist beim Beispiel mit XOR aber auch nötig.)

... sehe ich anders, Xor erkennt jede beliebige Flankenänderung und 
danach wird über den aktuellen Zustand entschieden welche gewünscht ist.

Der Code port_flanke = (port_alt ^ port_neu) & port_neu;
ist perfekt und geht nicht besser, ausser via ISR.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Apollo M. schrieb:
> Interrupt geht immer und ist "schicker"

Pollen im Timerinterrupt ist "schicker", da man damit gleich bequem 
entprellen kann.

von Rene Meier (Gast)


Lesenswert?

wow, das ging ja mehr als schnell. Ich probiere es der Reihe nach:

@Walter T. (nicolas): du hast die Tilde ~ übersehen, die sollte negieren
@Lothar M. (lkmiller): DANKE! Das wäre mir komplett durchgerutscht. Ich 
war mir bei dem & ~ unsicher ob das direkt geht, daher hatte ich vorher 
negiert und dann verundet
@Apollo M. (Firma: @home) (majortom): aus der Wahrheitstabelle sieht man 
doch, dass x auf der Zeitachse vor y ist, d.h. zuerst eingelesen wird. 
In dem Codeschnipsel unten ist dann x=port_alt und y=port_neu. Hätte ich 
der Fairness halber auch dazuschreiben sollen, denke ich hoffentlich 
dran wenn ich wieder was frage.
In deinem letzten Beitrag: fehlt da nicht noch eine Tilde?
@Hugo H. (hugohurtig1): die Timer habe ich schon "verbraten" und in 
Nutzung, indirekt wird aber über einen (Timer Overflow-)Interrupt 
abgefragt der alle 50msec auftritt. Also pollen war an der Stelle nicht 
richtig

Vielen Dank für eure Erläuterungen. Mir ging es vor allem darum zu 
verstehen warum man es so macht. Und Lehrbuch sagte mir das nicht, viel 
eher sagte das "Wahrheitstabelle erstellen und dann Verknüpfung 
ablesen/bestimmen". Da für mich ein & einfacher zu begreifen ist, werde 
ich damit weitermachen.
1
 alt & ~neu | Ergebnis
2
------------+----------
3
  0      0  | 0
4
  0      1  | 0
5
  1      0  | 1
6
  1      1  | 0

vs.
1
 alt ^ neu | temp & ~neu | Ergebnis
2
-----------+-------------+---------
3
  0     0  |  0       0  | 0
4
  0     1  |  1       1  | 0
5
  1     0  |  1       0  | 1
6
  1     1  |  0       1  | 0

Rene

von A. S. (Gast)


Lesenswert?

Apollo M. schrieb:
> Interrupt geht immer und ist "schicker", nur pollen ist halt weit
> verbreitet wegen c&p ... und eher Hardware/Plattform unabhängiger!

Schneller und performanter vermutlich meist. Aber auch asynchron und mit 
dem Potential zum Dauerfeuer. Deshalb nicht immer schicker.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Apollo M. schrieb:
> Daraus folgt doch schon "optisch", dass die Erkennung nicht
> flankenselektive sein kann.
Klar ist sie das. Denn eigentlich wird ja hier das Signal mit sich 
selbst verglichen. Nur zu einem anderen Zeitpunkt. Und weil zwischen 
"alt" und "neu" Zeit vergangen ist, kann man so feststellen, ob sich das 
Signal geändert hat. Und auch, welche Änderung passiert ist.

Das mit den Interrupts für schnarchlangsame Signale (Taster, 
Sensoren,...) aus der Umwelt ist ein Irrweg. Im Besonderen, wenn/weil es 
anfangs noch funktioniert, aber dann austickt, wenn der Kontakt ein 
wenig gealtert ist und mehr prellt.

von Teo D. (teoderix)


Lesenswert?

Lothar M. schrieb:
> Das mit den Interrupts für schnarchlangsame Signale (Taster,
> Sensoren,...) aus der Umwelt ist ein Irrweg. Im Besonderen, wenn/weil es
> anfangs noch funktioniert, aber dann austickt, wenn der Kontakt ein
> wenig gealtert ist und mehr prellt.

Bekommt man die selben Probleme wie beim Pollen....
Die eigentliche Frage ist doch, ist es den Aufwand wert?! Beim Pollen 
muss man sich halt deutlich weniger Gedanken um dessen Konsequenzen für 
den Rest des Programms machen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Teo D. schrieb:
> Bekommt man die selben Probleme wie beim Pollen...
Nein, denn ein prellender Taster prellt dann zwar (entprellt muss so ein 
Ding sowieso werden), kann aber nicht mit zig schnell aufeinander 
folgenden Impulsen den Rechner blockieren oder kurz mal Rechenzeit 
"stehlen".

> Beim Pollen muss man sich halt deutlich weniger Gedanken um dessen
> Konsequenzen für den Rest des Programms machen.
Kommt ein wenig drauf an. Man muss auch beim Pollen mit Prozessabbildern 
arbeiten und die während eines Durchlaufs nicht ändern. Denn das immer 
wieder erneute Einlesen eines Pins an jeder Stelle, wo er "gebraucht" 
wird, kann eigenartige Fehler hervorrufen.
Auf diese Art kann es nämlich sein, dass "der obere Teil" eines 
Programms noch einen unbetätigten Taster sieht und nichts tut, der 
"untere Teil" sieht aber einen betätigten Taster und legt schon mal los.

von Teo D. (teoderix)


Lesenswert?

Lothar M. schrieb:
> Nein, denn ein prellender Taster prellt dann zwar (entprellt muss so ein
> Ding sowieso werden), kann aber nicht mit zig schnell aufeinander
> folgenden Impulsen den Rechner blockieren oder kurz mal Rechenzeit
> "stehlen".

Genau das verhinder doch das Entpellen !
Warum denken immer alle, Interrupt == NICHT Entprellt?

Beitrag #6443259 wurde von einem Moderator gelöscht.
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Teo D. schrieb:
> Genau das verhinder doch das Entpellen !
Ein Interrupt "verhindert" erst von sich aus nichts. Er zeigt nur an, 
dass eine Flanke aufgetreten ist.

> Warum denken immer alle, Interrupt == NICHT Entprellt?
Man muss im Interrupt dann sowieso auch noch entprellen z.B. über 
Zeitstempel oder sonstwie. Die Verwendung eines Interrupts allein 
entprellt auf jeden Fall gar nichts.

Aber die Entprellung das hat mit der Flankenerkennung grundsätzlich 
nichts zu tun. Oder andersrum: erst muss das Signal vernünftig entprellt 
sein, dann kann ich vernünftig Flanken erkennen.

Hier im Thread war die Frage nach der Flankenerkennung.

: Bearbeitet durch Moderator
von Hugo H. (hugohurtig1)


Lesenswert?

Lothar M. schrieb:
> Nein, denn ein prellender Taster prellt dann zwar (entprellt muss so ein
> Ding sowieso werden), kann aber nicht mit zig schnell aufeinander
> folgenden Impulsen den Rechner blockieren oder kurz mal Rechenzeit
> "stehlen".

Ich lese da nur Flankenwechsel und nichts von Taster. Ist aber egal, so 
lange es keine genaueren Informationen gibt haben mehr oder weniger alle 
Recht :-).

von Teo D. (teoderix)


Lesenswert?

Lothar M. schrieb:
> Teo D. schrieb:
>> Genau das verhinder doch das Entpellen !
> Ein Interrupt "verhindert" erst von sich aus nichts. Er zeigt nur an,
> dass eine Flanke aufgetreten ist.

Sperr den Interrupt doch einfach für x-ms, nach dem Ersten auftreten.

Lothar M. schrieb:
> Die Verwendung eines Interrupts allein
> entprellt auf jeden Fall gar nichts.

Das hat ja ach keiner behautet!?

Lothar M. schrieb:
> Aber die Entprellung das hat mit der Flankenerkennung grundsätzlich
> nichts zu tun. Oder andersrum: erst muss das Signal vernünftig entprellt
> sein, dann kann ich vernünftig Flanken erkennen.

Egal ob Interrupt o. Polling.....

von A. S. (Gast)


Lesenswert?

Lothar M. schrieb:
> Oder andersrum: erst muss das Signal vernünftig entprellt
> sein, dann kann ich vernünftig Flanken erkennen.

Klingt wie Korinten… aber es ist anders herum: Zuerst bekomme ich eine 
Flanke, und erst dann muss ich entprellen. Und wenn ich nur die eine 
Flanke brauche (Nur Tastendrücke), heißt entprellen im einfachsten 
Falle: Wieder scharf schalten, wenn für X Takte (Intervalle, was auch 
immer) das Ruhesignal anliegt.

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Da Du Dich lt. Code ja vermutlich auf einem AVR MC bewegst - was spricht
> gegen die Nutzung eines Interrupts (statt ständig zu pollen)?

Dass dein Vorschlag nichts mit der Frage des TO zu tun hat. Es geht 
darum, den Algorithmus zu besprechen, die Möglichkeiten der Hardware.

von Hugo H. (hugohurtig1)


Lesenswert?

Rene Meier schrieb:
> Im Endeffekt möchte ich eine negative Flanke
> erkennen, also einen Wechsel an einem Portpin von 1 nach 0.

Stefan ⛄ F. schrieb:
> Dass dein Vorschlag nichts mit der Frage des TO zu tun hat. Es geht
> darum, den Algorithmus zu besprechen, die Möglichkeiten der Hardware.

Klar, gut dass es Dich gibt.

von Stefan F. (Gast)


Lesenswert?

Rene, möchtest du über deinen Algorithmus diskutieren, oder über die 
Möglichkeiten der Hardware, Flanken zu erkennen? Oder noch etwas 
anderes?

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Es geht
> darum, den Algorithmus zu besprechen, die Möglichkeiten der Hardware.

Sehe ich erst jetzt :-)

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Sehe ich erst jetzt :-)

Ja, da fehlt das Wort "nicht"

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ja, da fehlt das Wort "nicht"

Deine Rückfrage an den TO klärt, dass Du gar nicht weißt ob das Wort 
wirklich fehlt :-)

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Deine Rückfrage an den TO klärt, dass Du gar nicht weißt ob das Wort
> wirklich fehlt

Mit der Rückfrage wollte ich vermeiden, dass wir uns weiter 
sinnloserweise darüber streiten, was das Thema des TO sein mag.

von Teo D. (teoderix)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mit der Rückfrage wollte ich vermeiden, dass wir uns weiter
> sinnloserweise darüber streiten, was das Thema des TO sein mag.

Oje, was ein Armutszeugnis für uns ALLE, aber DANKE. ;D

von Rene Meier (Gast)


Lesenswert?

Hallo,

hatte mich hier ausgeklinkt... Mich hat vor allem interessiert warum man 
ein XOR und UND nutzt anstatt eine UND Verknüpfung mit negiertem 
Eingang. Ich wollte keine Codeschnipsel oder praktische Implementierung 
o.ä.
Wenn ich mir das Signal angesehen habe und die Wahrheitstabelle dazu, 
dann wäre ich nie auf ein XOR + UND gekommen. Wollte also wissen was es 
für Vorteile hat, z.B. der Compiler übersetzt es in weniger ASM Befehle, 
es ist fehlerverzeihender, besser zu lesen... Was auch immer.

Gruß, Rene

von Dergute W. (derguteweka)


Lesenswert?

Rene Meier schrieb:
> Mich hat vor allem interessiert warum man
> ein XOR und UND nutzt anstatt eine UND Verknüpfung mit negiertem
> Eingang.

Weil man sich halt mal fuer eines entscheiden muss. Wenn man das dann 
hat, muss das andere, fuer das man sich nicht entschieden hat, nicht 
notwendigerweise schlechter sein.
Das versuchte ich schon in meinem ersten Post hier auszudruecken.

Gruss
WK

von Einer K. (Gast)


Lesenswert?

Rene Meier schrieb:
> Mich hat vor allem interessiert warum man
> ein XOR und UND nutzt anstatt eine UND Verknüpfung mit negiertem
> Eingang.

Die Antwort ist doch klar!

§1 Persönliche Vorlieben
§2 Eine der beiden Varianten spart Speicher oder Takte ein
§3 Wenn 2 zutrifft, mir aber egal ist, wird §1 durchgesetzt

von Peter D. (peda)


Lesenswert?

Rene Meier schrieb:
> Mich hat vor allem interessiert warum man
> ein XOR und UND nutzt

Das XOR erlaubt es, beide Flanken mit dem selben Code zu 
entprellen/entstören, auch wenn man nur eine auswerten will. Das ergibt 
eine höhere Zuverlässigkeit ohne Mehraufwand.

von A. S. (Gast)


Lesenswert?

Rene Meier schrieb:
> warum man ein XOR und UND nutzt anstatt eine UND Verknüpfung mit
> negiertem Eingang.

Du hast die Wahrheitstabelle gehabt und das umgesetzt.

Der Autor hat vermutlich erst das Problem der Flanke gelöst und dann 
die richtige.

Und selbst wenn er anschließend retrospektiv auch Deine Lösung gefunden 
hat, gäbe es keinen Grund, das noch zu ändern. Beide sind gleich 
komplex.

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.