Hallo,
Gleich zu Anfang. Ich bin neu in der Microcontroller-Welt und stehe noch
ganz am Anfang. Ich bringe mir die Programmierung von Microcontrollern
durch lesen und mein Vorwissen in Java und C++ selbst bei.
Zu meinem "Problem". Ich habe einen ATMega 88P Microcontroller, an dem
eine LED (PD4) und ein Taster (PD2) angeschlossen sind. Ich habe es
hinbekommen zu programmieren, dass die LED blinkt, wenn ich den Taster
drücke und, wenn ich den Taster dann wieder los lasse, dass dann die LED
ebenfalls aus ist.
Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine
Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und
daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in
dem Beispiel 5 mal).
Könnt ihr mir ein paar hilfreiche Tipps geben, mit welchen ich dann auf
den richtigen Pfad komme?
Hier mal den Code, den ich geschrieben habe, dass das blinken auf den
Tastenhalt reagiert:
Patrick H. schrieb:> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde
Die Beschreibung ist unvollständig oder unlogisch und kann daher nicht
programmiert werden: woher soll der arme Controller denn wissen, dass
nicht noch Tastendrücke folgen?
Du kannst natürlich nach jedem Tastendruck die LED 1mal blinken lassen,
dann stimmt die Zahl - aber das ist trivial und wohl nicht das was du
dir gedacht hast.
Georg
Du könntest nach dem ersten detektierten Tastendruck einen Timer bzw.
den Watchdog starten, der nach x Zeit z.B. einer Sekunde das Ende der
Eingabe festlegt.
Allerdings wirst du dich dafür noch mit Tastenentprellung auseinander
setzen müssen da es sonnst zu Fehlern kommt.
Taste betätigt ->
Timer \ Watchdog starten ->
Taste innerhalb einer Sekunde betätigt ->
Timer \ Watchdog zurücksetzen ->
Taste innerhalb einer Sekunde nicht betätigt ->
Blinken ausführen.
P.S. : Die "wait(65535);" Funktion sieht ein wenig merkwürdig aus ?!
Patrick H. schrieb:> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in> dem Beispiel 5 mal).
Wenn der Taster entprellt ist, kann das Programm die Anzahl der
Tastendrücke in einer Variablen speichern und fürs Blinken benutzen.
Aber wait/delay können in diesem Programm nicht mehr benutzt werden.
Hi,
Du machst die Tastatureingabe mit dem Code von Peter Danneger in einem
Interrupt. Dort zählst Du die Tastendrücke in einer Variable x.
Im Hauptprogramm kannnst Du die LED blinken lassen, indem Du in einer
Endlosschleife diese Variable x abfragst: Ist diese Null, dann tust Du
nichts. Größer Null läßt einmal blinken und zählt die Variable x
herunter.
Hauptschleife:
While (1){
if (x>0) {
LEDON;
Wait(500);
LEDOFF;
Wait(500);
x--;
}
}
Patrick H. schrieb:> Zu meinem "Problem
Du hast keine Ahnung von Logik.
Wenn die LED an ist wenn man den Taster niederdrückt und aus ist wenn
man ihn loslässt (braucht man keinen uC) leuchtete die LED genau so oft
wie man den Taster drückte, dein Problem ist also schon gelöst.
Wenn du jedoch meintest, du drückst innerhalb einer Zeitspanne von sagen
wir 10 Sekunden den Taster 1 bis 100 mal, dann soll nach dem Ablauf der
10 Sekunden die LED ebenso oft an und aus gehen, z.B. mit einem Zeittakt
von 0.5 Sekunden, dann ist dad eine ganz andere Aufgabenstellung.
Kaum denkt man selber richtig, löst sich ein Problem von alleine.
Kann man auch mit einem up/down Counter, wie z.B. dem 74(HC)193
realisieren. Den (entprellten) Taster zum Befüllen des Zählers nutzen
und sowie ein Zählerstand ungleich Null erkannt wird, wird ein
Logikgatter freigegeben, das den Takt zum Abwärtszählen liefert. Bei
Null stoppt sich das Konstrukt dann von selber.
Wenn mehr als 15 Impulse zu erwarten sind, dann 2 Zähler kaskadieren.
Der freigegebene Takt zum Abwärtszählen steuert gleichzeitig die Lampe
an ;-)
georg schrieb:> Die Beschreibung ist unvollständig oder unlogisch und kann daher nicht> programmiert werden: woher soll der arme Controller denn wissen, dass> nicht noch Tastendrücke folgen?
Muß er auch nicht.
Er fängt einfach das Blinken an, sobald der Zähler >0 ist.
MaWin schrieb:> Patrick H. schrieb:>> Zu meinem "Problem>> Du hast keine Ahnung von Logik.
Vielleicht hast du es auch nur nicht richtig gelesen?
> Wenn du jedoch meintest, du drückst innerhalb einer Zeitspanne von sagen> wir 10 Sekunden den Taster 1 bis 100 mal, dann soll nach dem Ablauf der> 10 Sekunden die LED ebenso oft an und aus gehen, z.B. mit einem Zeittakt> von 0.5 Sekunden, dann ist dad eine ganz andere Aufgabenstellung.
Also irgendwie lese ich (abgesehen von den von dir eingefügten
Beispielwerten) genau das aus folgenden Abschnitt:
Patrick H. schrieb:> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in> dem Beispiel 5 mal).
Der µC soll sich also zuerst merken, wieviele Tastendrücke kamen, und
dann die LED so oft blinken lassen. Und nicht:
MaWin schrieb:> Wenn die LED an ist wenn man den Taster niederdrückt und aus ist wenn> man ihn loslässt (braucht man keinen uC) leuchtete die LED genau so oft> wie man den Taster drückte, dein Problem ist also schon gelöst.
Rolf M. schrieb:> Vielleicht hast du es auch nur nicht richtig gelesen?
Ja, Ratestunde. Oder andersrum: ohne eine definierte Aufgabenstellung
(am besten mit einem Timingdiagramm, das mehrere Beispiele enthält) ist
jeder Vorschlag gleich gültig.
Patrick H. schrieb:> Ich bringe mir die Programmierung von Microcontrollern durch lesen und> mein Vorwissen in Java und C++ selbst bei.
Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn
die blockieren den uC und verhindern, dass du mehrere Sachen "parallel"
machen kannst. Am Vorhandensein solcher
Verzögerungen/Rechenzeitvernichter erkennt man ein schlechtes Programm.
Lothar M. schrieb:> Rolf M. schrieb:>> Vielleicht hast du es auch nur nicht richtig gelesen?> Ja, Ratestunde. Oder andersrum: ohne eine definierte Aufgabenstellung> (am besten mit einem Timingdiagramm, das mehrere Beispiele enthält) ist> jeder Vorschlag gleich gültig.
Soll er gleich noch ein 50-seitiges Lastenheft schreiben, um hier eine
Frage stellen zu dürfen? Ich finde die Frage hinreichend klar.
> Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn> die blockieren den uC und verhindern, dass du mehrere Sachen "parallel"> machen kannst. Am Vorhandensein solcher Verzögerungen/Rechenzeitvernichter >
erkennt man ein schlechtes Programm.
Prinzipiell ja, aber für die ersten "Gehversuche" ist es ok. Interrupts
und Timer müssen nicht unbedingt die allerersten Dinge sein, mit denen
man sich beim Erlernen der Grundlagen der µC-Programmierung beschäftigt.
Ein bischen "Pinwackeln" geht auch noch mit Delays.
Für diesen Fall bietet sich ein Timer Interrupt aber wirklich an.
Z.B. 10ms Timer.
Darin lassen sich durch einfache Variablen und if Abfragen sowohl die
Tastenentprellung, Zählung der Tastendrücke und auch Leuchtdauer der LED
durch Nachdenken realisieren.
Rolf M. schrieb:>> Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn>> die blockieren den uC und verhindern, dass du mehrere Sachen "parallel">> machen kannst. Am Vorhandensein solcher Verzögerungen/Rechenzeitvernichter >> erkennt man ein schlechtes Programm.>> Prinzipiell ja, aber für die ersten "Gehversuche" ist es ok. Interrupts> und Timer müssen nicht unbedingt die allerersten Dinge sein, mit denen> man sich beim Erlernen der Grundlagen der µC-Programmierung beschäftigt.> Ein bischen "Pinwackeln" geht auch noch mit Delays.
Daher habe ich die LED in meinem Beispiel auch mit wait (bzw. Delay)
blinken lassen damit es für den Anfang etwas einfacher wird.Nächster
Schritt wäre dann ein Blinken mittels extra Timer. Wenn das klappt, das
Blinken in den Timer für die Tastaturabfrage mit reinpacken.
Ganz ohne Timer geht es für dieses Beipiel auch nicht. Dafür braucht er
die Tastenentprellung von Peter D. nur hier aus dem Forum abzupinseln.
Also ehrlich gesagt, so unverständlich war die Anforderung des TO
wirklich nicht. Fals er es doch nicht sofort blinken lassen will,
sondern erst auf den letzten Tastendruck warten will, dann muß
allerdings noch definiert werden wie lange er auf den letzten
Tastendruck warten soll. Das kann man dann immer noch einbauen.
Also: Schöne Programmierübung. Mehr soll es vermutlich auch nicht sein.
Vielen Dank für eure hilfreichen Ansätze, damit kann ich auf jeden Fall
weiterversuchen.
Andreas B. schrieb:> Also: Schöne Programmierübung. Mehr soll es vermutlich auch nicht sein.
Genau das soll es sein.
Andreas B. schrieb:> Ganz ohne Timer geht es für dieses Beipiel auch nicht. Dafür braucht er> die Tastenentprellung von Peter D. nur hier aus dem Forum abzupinseln.
Doch, geht !
Auch wenn mit Timer und Interrupts das eine bessere Lösung ist, so kann
das einen Anfänger überfordern.
Im Anhang habe ich mir mal den Spaß gegönnt wie man die
"Aufgabenstellung" ohne Timer und Interrupt codieren kann.
Prinzipiell sollte man den funktionalen Teilen wie Taster und LEDs (und
später andere angeschlossene Hardware) Namen vergeben und im Programm
mit diesen Namen arbeiten.
Das angehängte Beispielprogramm ist absichtlich "zu ausführlich"
kommentiert, vllt. wollen andere Anfänger auch daraus lernen.
_delay_ms aus delay.h zählt ja nur Prozessortakte (meines Wissens).
prinzipiell hätte man auch so etwas machen können:
1
voiddelay(uint32_tanz)
2
{
3
volatileuint32_ti;
4
5
for(i=0;i<anz;i++);
6
}
Um sich dann selbst irgendeine Verzögerungszeit zu generieren.
Um es klar zu stellen, ich bin kein Freund und auch kein Feind von
delay, in vielen Fällen braucht es nicht immer zwingend Timer und
Interrupt und es ist einfacher etwas mit Verzögerungsschleifen zu
machen.
Wenn ich zu Beginn meinen Auszubildenden gleich etwas von Interrupts
erzähle wenn sie gerade erst am Anfang stehen, machen die gleich "zu".
Aber, um den Feinden des delays zu begegnen: Die Version des
Blinkprogramms mit Interruptbetrieb im Anhang.
(wird vllt. noch überarbeitet und von mir dann als Lehranschauung wohl
verwendet, von daher Danke an den Threaderöffner)
Ralph S. schrieb:> _delay_ms aus delay.h zählt ja nur Prozessortakte (meines Wissens).
Ja.
> prinzipiell hätte man auch so etwas machen können:> void delay(uint32_t anz)> {> volatile uint32_t i;>> for (i= 0; i< anz; i++);> }>> Um sich dann selbst irgendeine Verzögerungszeit zu generieren.
Ja, wobei das keinerlei Vorteil gegenüber der Nutzung vorhandener
Delay-Funktionen hat. Wenn man "irgendeine" Zeit will, reicht es aber.
Soll's dann einigermaßen genau sein, wird das in C aber schwierig.