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.
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
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
charc;
2
3
c=0xAC;
4
5
if(c==0xAC)
6
sindgleich
7
else
8
sindungleich
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.
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.
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)
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.
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
voidfoo(inti)
2
{
3
intk,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.
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
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.
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.