negative Flanke in C erkennen, Erklärung gesucht

Gast #6443012
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
Moderator (Firma: Titel) Persönliche Seite
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.
(Firma: @home)
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 ...
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.
(Firma: @home)
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!
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.
(Firma: @home)
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.
Gast
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
Gast
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.
Moderator (Firma: Titel) Persönliche Seite
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.
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.
Moderator (Firma: Titel) Persönliche Seite
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.
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.
Moderator (Firma: Titel) Persönliche Seite
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.
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 :-).
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.....
Gast
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.
Gast
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.
Gast
Rene, möchtest du über deinen Algorithmus diskutieren, oder über die 
Möglichkeiten der Hardware, Flanken zu erkennen? Oder noch etwas 
anderes?
Gast
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.
Gast
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
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
Gast
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
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.