Hallo zusammen. Folgend ein (typisches) Anfängerproblem; Macro für einfache Tastenentprellung. Vom main() wird Port und Pin an Macro übergeben. Hier soll ausgewertet, und im Anschluss 1 oder 0 zurück gegeben werden. Klappt aber nicht! (siehe Anhang) Vermutlich die Variablen-Deklaration im Macro "Entprell" und die Rückgabe der 1 oder 0 im main().
Du musst an dein "Macro" (was keins ist) den PIN übergeben nicht den PORT. Du willst doch Eingänge entprellen.... Gruß Dennis P.S.: Warum konvertierst du Text in Grafik? Ist doch unsinnig.
:
Bearbeitet durch User
Dennis S. schrieb: > P.S.: Warum konvertierst du Text in Grafik? Damits größer, schlecht lesbar, nicht zitierbar und nicht compilierbar ist.
Peter D. schrieb: > Damits größer, schlecht lesbar, nicht zitierbar und nicht compilierbar > ist. Ich nehme alles zurück! Das sind natürlich nachvollziehbare Gründe. :-D
Dennis S. schrieb: > P.S.: Warum konvertierst du Text in Grafik? Ist doch unsinnig. Noch unsinniger ist nur noch, das dann auch noch als JPG zu konvertieren.
Dennis S. schrieb: > Du musst an dein "Macro" (was keins ist) den PIN übergeben nicht den > PORT. Du willst doch Eingänge entprellen.... OK, das wars! Jetzt flackert der Ausgang - werde ich mich später mit beschäftigen. Dennis S. schrieb: > P.S.: Warum konvertierst du Text in Grafik? Ist doch unsinnig. Graphik? Was genau meinst du?
Forist schrieb: > Noch unsinniger ist nur noch, das dann auch noch als JPG zu > konvertieren. Datentyp char und die delay in der Entprellroutine liegt aber auch ganz weit vorne!
__Son´s B. schrieb: > OK, das wars! > Jetzt flackert der Ausgang - werde ich mich später mit beschäftigen. Bitte, gern geschehen. > Dennis S. schrieb: > Graphik? Was genau meinst du? Quelltext = Text; Anhang = Grafik. Gruß Dennis
Bitte langsam lesen: xxx.txt ist Text xxx.jpg ist Bild, damit im Gegensatz zu Text eine Grafik Entprellen mit delay ist die Luxusversion. Nicht, daß sie besonders gut wäre, sondern besonders verschwenderisch. Aber es hat auch einen Vorteil: Es ist simpel.
__Son´s B. schrieb: > Dennis S. schrieb: >> Du musst an dein "Macro" (was keins ist) den PIN übergeben nicht den >> PORT. Du willst doch Eingänge entprellen.... > > OK, das wars! > Jetzt flackert der Ausgang - werde ich mich später mit beschäftigen. > > Dennis S. schrieb: >> P.S.: Warum konvertierst du Text in Grafik? Ist doch unsinnig. > > Graphik? Was genau meinst du? Das was du als ANhang angehängt hast. Da kann man sich so wunderbar auf Codestellen beziehen oder auch einmal Codestellen von deinem Code herausnahmen und für seine Antwort benutzen. <Sarkasmus aus> Häng doch einfach dein C-File als Anhang an. Du hast keine Arbeit damit, wir haben keine Arbeit damit. Und wenn jemand meint, er will in seine Antwort Codeausschnitte von dir einbauen um einen Punkt zu verdeutlichen, dann ist auch das kein Problem und keiner hat unmässig viel Arbeit damit. Eine Win-Win-Win Situation. Aber was will man von der Generation Selfie schon erwarten.
Dennis S. schrieb: >> Dennis S. schrieb: >> Graphik? Was genau meinst du? > Quelltext = Text; Anhang = Grafik. Ohje - der Anhang - scheint ein echt, ernsthaftes Problem zu sein ;-/
__Son´s B. schrieb: > Ohje - der Anhang - scheint ein echt, ernsthaftes Problem zu sein ;-/ Es ist eine Sache des respektvollen Umgangs miteinander. Die Gründe wurden dir ja oben schon ausführlich erklärt. Gruß Dennis
:
Bearbeitet durch User
Respektvoll, wenn keine Bilddatei zur Ansicht angeboten wird? Eventuell ungewohnt oder unsauber - das hat aber nichts mit "Respekt" zu tun! Wie würdet ihr den Quelltext zur Ansicht übertragen? --1-- copy/paste aus AtmelStudio direkt hier in das Forum-Textfeld? Habe ich ausprobiert, sieht sehr unübersichtlich aus. --2-- Oder copy/paste aus AtmelStudio in neue txt-Datei und diese Anhängen? Habe ich ausprobiert, sieht durch Tab-Verschiebungen unsauber aus.
Dann hast Du aber ein defizit, alles wissenswerte steht unter Formatierung (mehr Informationen...) __Son´s B. schrieb: > Respektvoll, wenn keine Bilddatei zur Ansicht angeboten wird? > Eventuell ungewohnt oder unsauber - das hat aber nichts mit "Respekt" zu > tun! > > Wie würdet ihr den Quelltext zur Ansicht übertragen? > --1-- > copy/paste aus AtmelStudio direkt hier in das Forum-Textfeld? > Habe ich ausprobiert, sieht sehr unübersichtlich aus. > --2-- > Oder copy/paste aus AtmelStudio in neue txt-Datei und diese Anhängen? > Habe ich ausprobiert, sieht durch Tab-Verschiebungen unsauber aus.
__Son´s B. schrieb: > Respektvoll, wenn keine Bilddatei zur Ansicht angeboten wird? respektvoll, weil du deinen Helfern Prügel zwischen die Beine wirfst Ein Programm ist in erster Linie einfach nur ein Text. Wenn es daher Probleme gibt, was liegt näher als ganz einfach diesen Text so wie er ist zu posten. > Wie würdet ihr den Quelltext zur Ansicht übertragen? Ganz einfach das C-File als Anhang anhängen. Niemand muss dazu irgendwas Copy&Paste machen. "Datei auswählen" - C-File auswählen - OK - Fertig. Was ist da jetzt so schwer drann?
Karl H. schrieb: >> Wie würdet ihr den Quelltext zur Ansicht übertragen? > > Ganz einfach das C-File als Anhang anhängen. Niemand muss dazu irgendwas > Copy&Paste machen. "Datei auswählen" - C-File auswählen - OK - Fertig. > > Was ist da jetzt so schwer drann? Ok, geht natürlich auch. Dank dir für den Hinweis!
Frank schrieb: > Datentyp char und die delay in der Entprellroutine liegt aber auch ganz > weit vorne! --1-- Tastenentprellung mit delay ist erst mal super einfach - natürlich wir die Zeit verschwendet. Andere Lösungen kommen später! --2-- Was ist an der Variablendeklaration "char" veraltet, unsauber oder falsch? Währe "int8_t" besser? Wenn JA, warum?
__Son´s B. schrieb: > Frank schrieb: >> Datentyp char und die delay in der Entprellroutine liegt aber auch ganz >> weit vorne! > --1-- > Tastenentprellung mit delay ist erst mal super einfach Sooooo einfach ist das gar nicht. > --2-- > Was ist an der Variablendeklaration "char" veraltet, unsauber oder > falsch? Währe "int8_t" besser? Wenn JA, warum? Weil du bei char nicht weisst, ob es ein Vorzeichen hat oder nicht. Das kann sich von Compiler zu Compiler oder auch mit einem Compilerswitch ganz schnell ändern. In C gibt es 3(!) kleine Datentypen * char * signed char * unsigned char Natürlich muss char eines der beiden anderen entsprechen. Aber welchem weisst du nicht. Daher: char benutzt man bei Textverarbeitung. In allen anderen Fällen, also wenn du im weitesten Sinne rechnen musst, bist du explizit und benutzt entweder signed char oder unsigned char. Aber niemals einfach nur char. Die Datentypen int8_t bzw. uint8_t erfüllen den gleichen Zweck. Und nein. Der Datentyp für 'Bytes' ist unsigned char (oder uint8_t), aber sicher nicht einfach nur char. Beispiel:
1 | char c; |
2 | |
3 | c = 0xAC; |
4 | |
5 | if( c == 0xAC ) |
6 | sind gleich |
7 | else
|
8 | sind ungleich |
Sieht dein Compiler einen char als unsigned char an, dann lautet das Ergebnis 'sind gleich'. Sieht dein Compiler einen char aber als signed char an, dann lautet das Ergebnis 'sind ungleich' (*). Um zu verstehen, warum das so ist, müsste man allerdings die C Regeln kennen. Etwas das heutzutage im Zeitalter der Chatrooms und des Erfragens von Achtelwissen (denn die meisten haben ja noch nicht einmal Halbwissen) in Foren leider immer weniger als erforderlich erachtet wird. (*) unter der Voraussetzung, dass 2-er Komplement Arithmetik benutzt wird. Also etwas was heutzutage praktisch in 99.9% aller Fälle der Fall sein wird.
:
Bearbeitet durch User
Karl H. schrieb: > Häng doch einfach dein C-File als Anhang an. Ogott - NEIN, bloß nicht - wozu auch? Aus der vom TO bereits geschilderten völligen Planlosigkeit wird auch dann nichts besseres, wenn er es als Text postet. __Son´s B. schrieb: > Folgend ein (typisches) Anfängerproblem; > > Macro für einfache Tastenentprellung. > Vom main() wird Port und Pin an Macro übergeben. Hier soll ausgewertet, > und im Anschluss 1 oder 0 zurück gegeben werden. Nein, das typische Anfängeproblem besteht darin, für irgendwelche interaktiven Vorgänge (Taste drücken) sich nicht den geringsten Gedanken gemacht zu haben, wie das Ganze auf rein logischer Ebene stattfinden soll. Stattdessen wird gleich mit Ports und Pins losgelegt, am besten noch dazu das Schreiben eines Makros angezielt. W.S.
Karl H. schrieb: > Weil du bei char nicht weisst, ob es ein Vorzeichen hat oder nicht. Das > kann sich von Compiler zu Compiler oder auch mit einem Compilerswitch > ganz schnell ändern. > > In C gibt es 3(!) kleine Datentypen > * char > * signed char > * unsigned char > > Natürlich muss char eines der beiden anderen entsprechen. Aber welchem > weisst du nicht. > Daher: char benutzt man bei Textverarbeitung. In allen anderen Fällen, > also wenn du im weitesten Sinne rechnen musst, bist du explizit und > benutzt entweder signed char oder unsigned char. Aber niemals einfach > nur char. > Die Datentypen int8_t bzw. uint8_t erfüllen den gleichen Zweck. > > Und nein. Der Datentyp für 'Bytes' ist unsigned char (oder uint8_t), > aber sicher nicht einfach nur char. Vielen Dank!!! Ich hangel mich via FRANZIS-Lernprogramm durch die uC-Prog. Daher sind mir solch wichtigen Praxistips sehr willkommen. Werde daher ab sofort kein "char" einsetzen (ausser bei Texten). Welche Var-Definition ist heute Standarisiert(er); int8_t oder signed char?
__Son´s B. schrieb: > Welche Var-Definition ist heute Standarisiert(er); int8_t oder signed > char? Beide sind standartisiert... ich persönlich empfinde die (u)intn_t-Typen als übersichtlicher und wird zum Beispiel auch in den MISRA-Regeln verlangt. Gruß Dennis
__Son´s B. schrieb: > Welche Var-Definition ist heute Standarisiert(er); int8_t oder signed > char? (u)int8_t gibt es offiziell erst seit 15 Jahren, aber es war schon vorher üblich, sich solche Typen für Nicht-Zeichen zu definieren. "(un)signed char" ist unüblich und deshalb unklarer.
:
Bearbeitet durch User
Die [u]int{8|16|32|64}_t-Typen ermöglichen die exakte Kontrolle der Größe und bieten sich im Mikrocontroller-Umfeld an. Für die Werte eines 8-Bit-Ports bietet sich uint8_t an. -------------------- Deine Entprell()-Funktion tut übrigens nicht das, was der Name suggeriert. Der Inhalt des if-Blocks mit _delay_ms() usw. bringt nichts, da sich der Wert von pinx im Lauf eines Funktionsaufrufs nicht ändert. Hierbei ist anzumerken, dass der annähernd gleiche Code als Macro durchaus entprellende Wirkung hätte.
Konrad S. schrieb: > Die [u]int{8|16|32|64}_t-Typen ermöglichen die exakte Kontrolle der > Größe und bieten sich im Mikrocontroller-Umfeld an. Dank für die Tips und Klarheit. In der Literatur und im Netz arbeitet man immer noch gerne mit den (alten) Datentypen. Sollte/könnte "int main()" auch in "int16_t main()" umbezeichnet werden? Konrad S. schrieb: > Hierbei ist anzumerken, dass der annähernd gleiche Code als Macro > durchaus entprellende Wirkung hätte. Währe sehr praktisch! Wie genau sollte das Macro aussehen?
__Son´s B. schrieb: > Sollte/könnte "int main()" auch in "int16_t main()" umbezeichnet werden? Nein. Hier wird vom Standard verlangt, dass es sich um einen int handelt. Im allgemeinen Fall weisst du nicht, ob es sich dabei um einen 16 Bit int handelt oder einen 32 Bit int oder gar noch höher. Da main nicht von deinem Code aufgerufen wird, sondern von extern (im allgemeinen Fall), musst du dich an die vorgegebene und definierte Schnittstelle halten, die du nicht beeinflussen kannst. Und die verlangt nun mal einen int.
__Son´s B. schrieb: > Sollte/könnte "int main()" auch in "int16_t main()" umbezeichnet werden? Nein, denn auf einer 32-Bit Maschine wird erwartet, daß int main() einen 32-Bit Wert zurückgibt.
__Son´s B. schrieb: > Konrad S. schrieb: >> Hierbei ist anzumerken, dass der annähernd gleiche Code als Macro >> durchaus entprellende Wirkung hätte. > Währe sehr praktisch! Nicht nur das. Im allgemeinen ist es ganz gut, wenn man die Dinge richtig macht, denn dann funktionieren sie auch. Wo hast du eigentlich diesen (gelinde gesagt) Code-Unsinn her? Entprellung > Wie genau sollte das Macro aussehen? Der Zweck des Macros ist es, dass es eben keine Funktion gibt, sondern dass der Code direkt an der Stelle der Codeverwendung eingesetzt wird. Wobei ein Macro auch aus mehreren Zeilen bestehen kann. WEnn man sich also mal den Funktionskörper an der aufrufenden Stelle eingesetzt denkt oder das tatsächlich einmal macht, wie sieht der Code dann aus? (Wenn man Makros macht, ist es gerade für Neulinge eine ziemlich gute Idee, das ganze einfach einmal ohne Makros so hinzuschreiben, wie es eigentlich aussehen sollte. Und erst dann überlegt man sich, wie eine Textersetzung wohl aussehen müsste, damit nach der Textersetzung genau das rauskommt, was man haben möchte. Dazu muss mann aber wissen, was man eigentlich haben möchte, wodurch sich die Katze in den Schwanz beisst. Ergo: Erst einmal muss klar sein, wie eigentlich das Endergebnis nach all den Makroersetzungen aussehen soll. Und dann arbeitet man sich davon ausgehend rückwärts um zu bestimmten, wie das zugehörige Makro aussehen soll)
:
Bearbeitet durch User
Karl H. schrieb: > Wo hast du eigentlich diesen (gelinde gesagt) Code-Unsinn her? "Das Franzis Lernprogramm (ISBN9783645650687)" - allerdings nicht als Funktion. Hier wollte ich eine Vereinfachung durch eine "Entprell-Funktion" mit Variablen, in denen die Eingangszuweisung übergeben wird, schaffen. Mit der Funktion wird der main-Code wesentlich übersichtlicher. Ich möchte nicht ausschliessen, dass im weiteren Verlauf des Buchse ein sauberer Entprell-Programmiercode vorgestellt wird.
__Son´s B. schrieb: > Karl H. schrieb: >> Wo hast du eigentlich diesen (gelinde gesagt) Code-Unsinn her? > "Das Franzis Lernprogramm (ISBN9783645650687)" - allerdings nicht als > Funktion. Hier wollte ich eine Vereinfachung durch eine > "Entprell-Funktion" mit Variablen, in denen die Eingangszuweisung > übergeben wird, schaffen. Gratulation. Du hast damit die Funktionalität lahmgelegt Wenn es im Buch als Makro geschrieben ist, dann würde das auch erstmal funktionieren. Aber so wie du das umgeändert hast, hast du es unbrauchbar gemacht.
:
Bearbeitet durch User
Karl H. schrieb: > Wenn es im Buch als Makro geschrieben ist, Nein! Weder Macro noch Funktion - steht auch nirgens. Folgend die Original-Zeilen; int main() ... while(1) { if((PIND & (1<<PD2)) == 1) { _delay_ms(50); if((PIND & (1<<PD2)) == 1) { PORTD ^= (1<<PD6); while(PIND & (1<<PD2)); } ...
__Son´s B. schrieb: > Karl H. schrieb: >> Wenn es im Buch als Makro geschrieben ist, > Nein! > Weder Macro noch Funktion - steht auch nirgens. > > Folgend die Original-Zeilen; > int main() > ... > while(1) > { > if((PIND & (1<<PD2)) == 1) > { > _delay_ms(50); > if((PIND & (1<<PD2)) == 1) > { > PORTD ^= (1<<PD6); > while(PIND & (1<<PD2)); > } > ... Ja, so wäre das ok. Wenn man den Teil als Makro extrahiert, ist es immer noch ok, denn ein Makro ist ja vom Prinzip her nichts anderes als eine Textersetzung. Aber so wie du das in eine Funktion gepackt hast, ist es nicht mehr ok. Denn
1 | void foo( int i ) |
2 | {
|
3 | int k, l; |
4 | |
5 | if( i == 5 ) |
6 | k = 8; |
7 | |
8 | if( i == 5 ) |
9 | l = 9; |
10 | }
|
die zweite Abfrage, ob i gleich 5 ist, ist überflüssig. Denn i kann sich nicht von der ersten Abfrage bis zur zweiten Abfrage verändern. Wenn es bei der ersten gleich 5 war, dann muss es auch bei der zweiten 5 sein. Und umgekehrt: wenn es bei der ersten nicht 5 war, dann kann es auch bei der zweiten nicht 5 sein. D.h. in deiner Funktion ...... tja. und jetzt wärs halt gut, wenn man den Code in Textform hätte und nicht nur als Bild ..... liefern die beiden Abfragen
1 | if( pinx & (1<<px) ) |
jeweils dasselbe Resultat. Denn weder pinx noch px können sich in der Zwischenzeit, während der _delay_ms verändert haben. Fazit: Du hast die Funktionalität ruiniert. Die zweite Abfrage wird immer dasselbe Ergebnis bringen wie die erste. Da die zweite Abfrage nur dann gemacht wird, wenn die erste TRUE ergeben hat, wird die zweite auch immer TRUE ergeben.
:
Bearbeitet durch User
Karl H. schrieb: > __Son´s B. schrieb: >> Karl H. schrieb: >>> Wenn es im Buch als Makro geschrieben ist, >> Nein! >> Weder Macro noch Funktion - steht auch nirgens. >> >> Folgend die Original-Zeilen; >> int main() >> ... >> while(1) >> { >> if((PIND & (1<<PD2)) == 1) >> { >> _delay_ms(50); >> if((PIND & (1<<PD2)) == 1) >> { >> PORTD ^= (1<<PD6); >> while(PIND & (1<<PD2)); >> } >> ... > > Ja, so wäre das ok. muss mich korrigieren. Nein das ist natürlich nicht ok. Denn egal ob der Pin PD2 auf 0 oder aus 1 ist, es wird nie der Fall sein, dass
1 | PIND & (1<<PD2) |
den Wert 1 ergibt. Das ist unmöglich. Wenn der Pin auf 0 ist, dann liefert der Ausdruck 0, wenn der Pin auf 1 ist, dann ergibt der Ausdruck ausgewertet den Wert 4 (oder eben 1<<PD2). Aber 1 wird er in keinem Fall. Daher interessiert es im Normalfall überhaupt nicht, was dieser Ausdruck konkret für einen Wert ergibt. Hauptsache er ist nicht 0. Das reicht dann schon
1 | if( PIND & (1<<PD2) ) // nicht 0? |
2 | ....
|
In C ist weniger oft mehr. Insbesondere ist
1 | if( irgendwas != 0 ) |
und
1 | if( irgendwas == 1 ) |
nicht dasselbe.
:
Bearbeitet durch User
Karl H. schrieb: > jeweils dasselbe Resultat. Denn weder pinx noch px können sich in der > Zwischenzeit, während der _delay_ms verändert haben. Klar! Hier wird nicht die Taste erneut abgefragt, sondern die gleiche Variable vom Funktionseingang Entprell(pinx,px), noch einmal aufgerufen. Variablen habe ich eingesetzt, damit diese Funktion allgemeingültig für alle Tasten verwendbar ist. Wie würde ein Makro hierzu aus sehen? Karl H. schrieb: > es wird nie der Fall sein, dass PIND & (1<<PD2) > den Wert 1 ergibt. Das ist unmöglich. Wenn der Pin auf 0 ist, dann > liefert der Ausdruck 0, wenn der Pin auf 1 ist, dann ergibt der Ausdruck > ausgewertet den Wert 4 (oder eben 1<<PD2) mit der "4" verstehe ich leider nicht. Karl H. schrieb: > Hauptsache er ist nicht 0. Das reicht > dann schon > if( PIND & (1<<PD2) ) // nicht 0? > .... das ist klar! So habe ich es auch später umgesetzt.
__Son´s B. schrieb: > mit der "4" verstehe ich leider nicht. ... meinst du "00000100" = 4 ? __Son´s B. schrieb: > Wie würde ein Makro hierzu aus sehen? ... vor allem alles in eine Zeile, ohne geschweifte Klammern?
__Son´s B. schrieb: > __Son´s B. schrieb: >> mit der "4" verstehe ich leider nicht. > ... meinst du "00000100" = 4 ? ganz genau. Das ist das, was übrig bleibt, wenn der Eingang auf 1 ist und du die Operation
1 | PIND & ( 1 << PD2 ) |
darauf anwendest. Der Ausdruck ergibt das Bitmuster 00000100. ALs Dezimalzahl ist das dann eben die Zahl 4. > __Son´s B. schrieb: >> Wie würde ein Makro hierzu aus sehen? > ... vor allem alles in eine Zeile, ohne geschweifte Klammern? Warum? Man kann ein Makro auch über mehrere Zeilen schreiben. Alles was dazu nötig ist, ist ein \ als letztes Zeichen der Zeile
1 | #define MAX(a,b) \
|
2 | (a) < (b) ? \
|
3 | (a) \
|
4 | : \
|
5 | (b)
|
Man kann das natürlich auch alles in einer Zeile schreiben
1 | #define MAX(a,b) (a) < (b) ? (a) : (b)
|
und in diesem Fall wird man das auch tun. Aber man muss es nicht und in deinem Fall wird man genau das (alles in einer Zeile schreiben) nicht tun. Siehe .... eigentlich jedes halbwegs brauchbare C-Lehrbuch.
:
Bearbeitet durch User
Den Arikel kennst du schon? Entprellung Du findest darin Verfahren, die dann auch tatsächlich funktionieren und auch noch ein bischen mehr machen, als diese simple Entprellung. Denn mit der Entprellung alleine ist es ja normalerweise nicht getan. Da muss ja auch noch eine Flankenerkennung mit dazu.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.