Hey Leute,
bin noch ein echter Newbie in Sachen µC. Nach dem Lauflichter und
solchen Scherzen, wollte ich mir folgenden Programmcode von Peter
Danneger zum entprellen mal nachvollziehen.
Leider habe komme ich an einigen Stellen nicht wirklich weiter. Unter
dem Code stehen einige Fragen die IHR mir mit Sicherheit beantworten
könnt.
Bin über jeden Kommentar dankbar! Ihr braucht euch nicht genötigt fühlen
gleich alle Fragen zu beantworten (sind doch mehr geworden als ich
dachte).
DANKE!!
1.Was bedeutet das static vor der dem uint8_t flag=0 gleich am Anfang
der Funktion debounce? Kann die Variable den Zustand vielleicht
automatisch ändern?? Sonst würde in der ersten if-Abfrage immer nur der
erste Teil des Programmcodes verwendet werden können.
2.Welche Auswirkungen hat das break in der Funktion debounce? Wird die
Funktion unterbrochen und der aktuelle Wert den i hat zurück gegeben?
Ach ja, warum steht vor dem Rückgabewert i kein return am ende der
Funktion?
3. Bei der Funktion _delay_us (98); dachte ich das ich nur auf die
folgende Randbedingung achten muss: maximal mögliche Delay-Zeit:
262,14ms/F_CPU in MHz. D.h. bei dem ATmega8 (interner Takt
1MHz---262,14ms/1MHz=262,14ms)kann ich einfach _delay_ms(25) angeben
wenn ich 25ms warten möchte.
4.Was bedeutet das ^= in der main-Funktion?
5.Was passiert, wenn Eine Taste dauernd gedrückt wird? Toggelt der
Ausgang dann?
Puh, das reicht für den Anfang.
Danke für eure Hilfe!!
Markus
Hier ein paar Ansätze zum selbstständigen Durchdenken:
> 1.Was bedeutet das static vor der dem uint8_t flag=0 gleich am Anfang> der Funktion debounce?
Schau mal in ein C-Buch :-)
> 2.Welche Auswirkungen hat das break in der Funktion debounce?
Schau mal in ein C-Buch.
> Ach ja, warum steht vor dem Rückgabewert i kein return am ende der> Funktion?
'debounce' ist garkeine Funktion, sondern Textersatz, auch 'Makro'
genannt.
> 3. Bei der Funktion _delay_us (98); dachte ich das ich nur auf die> folgende Randbedingung achten muss: maximal mögliche Delay-Zeit:> 262,14ms/F_CPU in MHz.
Das dachten viele vor dir auch. Lies nochmal genauer nach.
> 4.Was bedeutet das ^= in der main-Funktion?
Schau mal in ein C-Buch oder in eine Operatorentabelle.
Ich möchte dir damit nicht halbherzig etwas an den Kopf knallen, versteh
das bitte nicht falsch. Aber ich bin mir sicher, du bist in der Lage,
die ersten vier Fragen nun selbst zu beantworten.
Hallo Sven,
haben noch mal gegoogelt:) Mit dem Vorsatz static behält die Variable
ihren Wert wenn die Funktion erneut aufgerufen wird.
So weit so gut!
Sie wird ein mal ganz am Anfang mit 0 definiert. Wie sieht es denn mit
der ersten if-Abfrage in der Funktion aus. Zunächst mal stört mich das
da kein gleich steht wie z.B. if(flag==1) nach was fragt die
if-Anweisung ab?
Eigentlich müsste die if-Abfrage negativ sein, weil sich der Zustand von
flag sonst nicht ändert. Nur in dem else Teil der Abrage wird der
Variablen Flag eine 1 zugeschrieben.
Wäre für ein paar mehr Infos dankbar!!
Markus
Markus schrieb:> Hallo Sven,> haben noch mal gegoogelt:) Mit dem Vorsatz static behält die Variable> ihren Wert wenn die Funktion erneut aufgerufen wird.
Jein, so erklärt man es mitunter.
'static' bewirkt globales Verlinken. Deine statische Variable
funktioniert eigentlich wie eine globale Variable (die du am
Programmanfang vereinbarst), die aber trotzdem nur dort sichtbar ist, wo
du sie vereinbart hast.
> Sie wird ein mal ganz am Anfang mit 0 definiert. Wie sieht es denn mit> der ersten if-Abfrage in der Funktion aus. Zunächst mal stört mich das> da kein gleich steht wie z.B. if(flag==1) nach was fragt die> if-Anweisung ab?
Schau mal in ein C-Buch, dort steht, was in C wahr, und was falsch ist.
OK! Also:
1= wahr
0=falsch
Man kann für die erste if-Abfrage auch schreiben
if(flag==1) //oder??!!
Und eine 1 liegt an wenn der Taster nicht betätigt ist (wegen den
PULL-down)
Im Prinzip verstehe ich das Programm, glaube ich. Mit dem Flag wird
gespeichert wie der Zustand des Eingangs war. Danach wird zunächst
geprüft ob das Signal toggelt. Und erst wenn ein sicher Zustand anliegt
wird geschaltet, aber es bleiben einfach noch immer viel zu viele von
meinen Fragen offen!!
Bevor ich den Code verwende möchte ich genau wissen wie alles
funktioniert und nicht einfach Sachen zusammen basteln und hoffen das
alles klappt.
Gruß Markus
Was ist mit dem ^= ? Ich weiß das es die Funktin eines Exklusiv-ODER
hat. Aber ich verstehe einfch nicht wie das zusammen passt!
Und warum braucht es kein return vor dem i am Ende der Funktion?
Wäre echt super wenn du mal was konkretes dazu schreiben würdest!!
Markus
Markus schrieb:> Wäre echt super wenn du mal was konkretes dazu schreiben würdest!!
Dann lernste aber nix.
> Was ist mit dem ^= ? Ich weiß das es die Funktin eines Exklusiv-ODER> hat. Aber ich verstehe einfch nicht wie das zusammen passt!
Mach dich mal schlau darüber, was eine Bitmaske ist. Dann wirds dir wie
Schuppen von den Augen fallen.
> Und warum braucht es kein return vor dem i am Ende der Funktion?
Es ist keine Funktion, sondern ein Makro!
Dort, wo du es verwendest ('aufrufst'), wird ganz primitiver Textersatz
vorgenommen: Statt 'debounce' steht der Rumpf des Makros dort.
Nun ist das ganze Makro ein Ausdruck. Das ist zugegebenermaßen etwas
hässlich und GCC-spezifisch, aber naja.
Informiere dich mal über den Kommaoperator, dann denk mal über folgendes
nach:
1
intx,y;
2
x=1,2,3;
3
y=(1,2,3);
Ist zwar nicht das gleiche, dürfte dir aber einen wichtigen Anstoß
geben.
Markus schrieb:> Und warum braucht es kein return vor dem i am Ende der Funktion?
Ein Return würde die Funktion verlassen, in der das Macro expandiert
wird (d.h. in der der Textersatz stattfindet).
In diesem Fall würde also das Main verlassen werden.
Ein Macro kann aber trotzdem einen Wert haben, den man zuweisen kann:
"The last thing in the compound statement should be an expression
followed by a semicolon; the value of this subexpression serves as the
value of the entire construct."
http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
Peter
Static:
In C werden Variable, die innerhalb von Funktionen declariert werden,
vom Compiler, bzw. dessen erzeugten Programmcode auf dem Stack erzeugt.
Das bedeutet natürlich beim Verlassen der Funktion, dass diese Variable
wieder gelöscht wird. (der nächste Funktionsaufruf benutzt ja wieder
diesen Stackbereich).
Will man haben, dass der Wert der Variablen beimn nächsten Aufruf wieder
verfügbar ist, benutzt man das Wort static. Jetzt reserviert der
Compiler Speicherplatz im Ram exclusiv für diese Variable, und wird
nicht von irgend einem anderen Programmteil überschrieben.
Diese Variable ist deshalb aber noch nicht global, also von anderen
Funktionen aufrufbar.
PORTB ^= 1<<PB2; ist glichbedeutend mit PORTB = POTRB ^ 1<<PB2;
vergleichbar wäre z.B. a += 5 -> a = a +5
ist also quasi eine abgekürzte Schreibweise.
Grundsätzlich zu Tastaturabfragen:
Der Prozessor fragt ein Port immer zu einem bestimmten Zeitpunkt ab,
also genau dann, wenn der Befehl kommt. Wenn man also auf einen
Tastendruck wartet, muss man diesen Port immer wieder abfragen. Ändert
sich nun etwas am Port, so wird das Programm wohl darauf mit irgend
einer Aktion reagieren. Diese Aktionen sind in der Regel in ein paar
Sekundebruchteilen abgehandelt, danach wird wieder der Port abgefragt um
eine neue Aktion zu starten.
Wenn die Taste immer noch gedrückt ist, was wohl meist der Fall ist,
würde diese Aktion erneut ausgeführt werden.
Um dies zu vermeiden, wird dann in einer Schleife gewartet, bis die
Taste wieder losgelassen wird. Erst nach erneutem Drücken wird dann
wieder di Aktion ausgelöst.
Übrigens Swen
Der Hinweis: "schau mal in ein Buch" ist nicht gerade Hilfreich. Da
können wir dieses Forum dann gleich zu machen.
Man kann Markus ja wirklich nicht nachsagen, dass er von uns ein
Programm geschrieben haben will.
Und C mit seinen kryptischen Abkürzungen ist ja nicht gerade leichte
Kost.
Oft weiß man als Anfänger eben nicht, wo man am beesten im Buch sucht.
Manche Bücher sind auch nicht für Anfänger geschrieben, wenigstens hat
man manchmal den Eindruck. Da werden oft Fachwörter gebrauht, die ein
Anfänger einfach noch nicht weiß.
Haderlump schrieb:> Übrigens Swen
vvvvvvvvvvvvvvvvvvv
> Der Hinweis: "schau mal in ein Buch" ist nicht gerade Hilfreich. Da
Ach bitte...
Der TO hat einfach mal gefragt, ohne vorher einen Finger krumm zu
machen, sondern will sich das vorkauen lassen.
Ganz einfach daran zu erkennen, dass er nach Svens Aufforderung doch
mal eine Suchmaschine bemüht und sich die ersten Antworten
zusammengesucht hat.
Davor nicht.
> können wir dieses Forum dann gleich zu machen.
Dazu braucht man ja eigentlich nichts sagen...
Für dich trotzdem: Es gibt Fragen von Faulheit und von Unwissenheit
motiviert gestellt. Hier geht es überwiegend um erstere.
> Man kann Markus ja wirklich nicht nachsagen, dass er von uns ein> Programm geschrieben haben will.
Das hat Peter schon erledigt.
> Oft weiß man als Anfänger eben nicht, wo man am beesten im Buch sucht.
Na gaaanz vorne. Wo denn sonst??
Jedes Buch dieser Art hat eine Sektion für die Grundlagen. Wenn ich mich
gar nicht auskenne, sind Grundlagen doch wohl das erste, oder?
> Manche Bücher sind auch nicht für Anfänger geschrieben, wenigstens hat> man manchmal den Eindruck. Da werden oft Fachwörter gebrauht, die ein> Anfänger einfach noch nicht weiß.
Dann schlägt man eben diese auch wieder nach! So viel
Konzentrationsspanne wird doch wohl noch aufbringbar sein.
Das ist mühsam? Ja, richtig. Aber genau so geht lernen!
Nur weil man etwas mal gehört oder gesagt bekommen hat, bleibt es noch
lange nicht so im Gedächtnis wie ein unter Konzentration selbst
erarbeitetes Wissen.
Ich bin ja bereit, jedem was zu erklären, so gut ich kann. Deshalb auch
prophylaktisch mein Hinweis, dass meine Antwort nicht halbherzig gedacht
war, sondern den TO zum Lernen motivieren sollte.
Aber nachzufragen, was '^=' ist, ist schon etwas...verwirrend. Ich hab
ja auch einen ganzen Stapel an C-Büchern gebraucht, bis ich glücklich
wurde. Aber allen gemeinsam war, dass die Operatoren so ziemlich das
Erste waren, was erklärt wurde.
Also nix für Ungut. Offenbar hats ja funktioniert, eine Reihe von Fragen
hat der TO sich nun selbst beantworten können.
Hallo an ALLE!!
Zunächst einmal möche ich Peter und Haderlump danken!!
Jetzt ist mir endlich klar was der Unterschied zwischen einer Funktion
und eines Marcos ist!! Der Unterschied zwischne static und globaler
Variable ist nun auch klar!!
Endlich mal Beiträge die mich wirklich voran bringen!
Und nun zu den Kritikern. Wenn in dem Betreff steht "Newbie-Fragen zum
Programmcode (entplellen)" dann ist denke ich klar das es auch mal
leichte Fragen auftauchen!! Deswegen steht da ja NEWBIE!!
Dann möchte ich noch klar machen das man als Newbie sich nicht gleich
zig c-Bücher zulegt. Ich habe gerade mal eins (Helmut Erlenkötter, C
Programmieren von Anfang an) und da steht dieser Operator leider nicht
drin!
Nun zu den Lenmethoden. Um die Grundlegenden Sachen zu lernen ist es
sinnvoll sich erst mal Programme von "den alten Hasen" anzusehen. So
verhindere ich das ich mir irgendetwas falsch aneigne. Ich glaube nicht
das das bei irgendeinem am Anfang anders war!! Manchmal kann es einfach
ungemein helfen wenn einem einfach etwas vorgesagt wird!! Auch wenn es
bei dem ein oder anderen lange her ist und er sich nicht mehr dran
erinnernt will. Von fremdem Programmcode konnte ich bis jetzt mehr
lernen als aus irgendwelchen Büchern!! Mir geht es hier darum den
geschriebenen Code zu verstehen!! Das ist für mich der erste Schritt zu
eigenen anspruchsvollen Programmen. Einfach nur kopieren und bei Fehlern
nicht wissen was los ist, ist nicht mien Ziel!
OK, mit dem static habe ich es mir etwas leicht gemacht. Das gebe ich
zu.
So, jetzt muss ich aber noch mal zu einer meiner eigentlichen Fragen
zurück kehren.
3. Bei der Funktion _delay_us (98); dachte ich das ich nur auf die
folgende Randbedingung achten muss: maximal mögliche Delay-Zeit:
262,14ms/F_CPU in MHz. D.h. bei dem ATmega8 (interner Takt
1MHz---262,14ms/1MHz=262,14ms)kann ich einfach _delay_ms(25) angeben
wenn ich 25ms warten möchte.
Das müsste doch soweit stimmen, oder nicht?! Da ich später mal
Zeitkritische Sachen programmieren möchte würde ich das noch gerne
wissen. (Ich weiß das man für Zeitkritische Prozesse mit Timern und
Interrupt programmiern sollte, aber so weit bin ich noch nicht)
Danke für Eure Hilfe!
Markus
Markus schrieb:> Und nun zu den Kritikern. Wenn in dem Betreff steht "Newbie-Fragen zum> Programmcode (entplellen)" dann ist denke ich klar das es auch mal> leichte Fragen auftauchen!! Deswegen steht da ja NEWBIE!!
Selbsterniedrigung ist aber der falsche Weg. Du bist gewiss nicht doof.
> Dann möchte ich noch klar machen das man als Newbie sich nicht gleich> zig c-Bücher zulegt. Ich habe gerade mal eins (Helmut Erlenkötter, C> Programmieren von Anfang an) und da steht dieser Operator leider nicht> drin!
Mag ja sein (auch wenn ich das kaum glauben mag), aber du bist gewiss
nicht doof. Ich würde wetten, mit zwei Minuten Nachdenken hättest du
deine Operatoren gefunden.
> Nun zu den Lenmethoden. Um die Grundlegenden Sachen zu lernen ist es> sinnvoll sich erst mal Programme von "den alten Hasen" anzusehen. So> verhindere ich das ich mir irgendetwas falsch aneigne.
Naja, dann würde ich mir die Entprell-Methode, die du da ausgegraben
hast, schnell wieder abgewöhnen. Sie funktioniert zwar und sieht hübsch
aus, ist aber weder portabel noch sonderlich Zeit- oder
Speichereffizient.
> 3. Bei der Funktion _delay_us (98); dachte ich das ich nur auf die> folgende Randbedingung achten muss: maximal mögliche Delay-Zeit:> 262,14ms/F_CPU in MHz. D.h. bei dem ATmega8 (interner Takt> 1MHz---262,14ms/1MHz=262,14ms)kann ich einfach _delay_ms(25) angeben> wenn ich 25ms warten möchte.>> Das müsste doch soweit stimmen, oder nicht?! Da ich später mal> Zeitkritische Sachen programmieren möchte würde ich das noch gerne> wissen. (Ich weiß das man für Zeitkritische Prozesse mit Timern und> Interrupt programmiern sollte, aber so weit bin ich noch nicht)
Ich habe dich bereits darauf hingewiesen: *Lerne lesen!*
Und jetzt komm bitte nicht nochmal mit Newbie, Anfänger, schwierig und
so weiter. Die gesuchte Information steht genau eine Zeile weiter.
> Danke für Eure Hilfe!
Bitte.
Ich hoffe das hier liest noch jemand:)
Habe mir den Code noch mal gut angesehen. Ich glaube ich weiß nun wies
funktioniert, aber ich brauche in einem Punkt noch eine Bestätigung
damit ich wirklich sicher sein kann.
Da es sich um beim Makro um einen Textersatz handelt, wird das debounce
zwei mal aufgeraufen und es entstehen zwei Variablen namens flag (mit
den oben beschriebenen static-Eigenschaften). Eine für den Eingang am
PB1 und die andere für PB0.
Dann passt nämlich alles mit dem restlichen Code überein und die
Entprellung funzt.
Ein ja oder nein als Antwort reicht aus:)
Markus
Ja, jede Taste braucht ihre eigene Variable für den alten Zustand.
Deshalb mußte es auch als Macro geschrieben werden, als Inline-Funktion
geht das nicht.
Peter