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
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.
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.
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 ...
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... ;-)
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.
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)
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!
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.
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.
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.
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.
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.
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.
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?
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.....
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.
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.
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.
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.
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
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
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
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.
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.