negative Flanke in C erkennen, Erklärung gesucht

Gast #6443012
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
Moderator (Firma: Titel) Persönliche Seite #6443031
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.
(Firma: @home) #6443079
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 ...
#6443136
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.
(Firma: @home) #6443142
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!
#6443162
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.
(Firma: @home) #6443196
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.
Gast #6443214
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
Gast #6443215
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.
Moderator (Firma: Titel) Persönliche Seite #6443232
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.
#6443245
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.
Moderator (Firma: Titel) Persönliche Seite #6443251
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.
Beitrag #6443259 wurde von einem Moderator gelöscht.
Moderator (Firma: Titel) Persönliche Seite #6443262
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.
#6443265
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 :-).
#6443267
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.....
Gast #6443308
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.
Gast #6443313
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.
Gast #6445262
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
#6445274
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
Gast #6445285
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
Gast #6445310
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.

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