Hallo, ich habe einen Atmel Mega 8 und auch das myAVR USB Starterset. Leider funktioniert mein Programm nicht wie gewünscht. Ich habe den Port D (2) als Eingang eingestellt und an einen Taster angeschlossen. Der Taster liegt auf der Masse. Dann habe ich den Pullup aktiviert. Jetzt liegt der Eingang immer auf 0, wenn der Taster gedrückt wird. Mein kleines Programm soll am Ausgang B0, B1 und B2 binär zählen. Immer dann eine Stufe weiter, wenn der Taster gedrückt wird. Leider hat es nicht den gewünschten Effekt, zu zählen. Stattdessen liegt am Ausgang irgendwas an und nach jedem Tastendruck leuchtet eine andere Kombination von Leds, aber nicht so wie ich das gerne hätte. Was habe ich falsch gemacht: cbi DDRD, 2 sbi PORTD, 2 sbi DDRB,0 sbi DDRB,1 sbi DDRB,2 ;----------------------------------------------------------------------- - mainloop: ldi r16, 0b00000000 st: in r17, PIND sbrc r17,2 rjmp st inc r16 out PORTB, r16 rjmp st Liebe Grüße Jochen
hallo, so sollte es gehen glaub ich. ldi r16, 0xFB out DDRD, r16 ldi r16, 0x07 out DDRB, r16 ;----------------------------------------------------------------------- - mainloop: ldi r16, 0x00 st: in r17, PIND sbrc r17, 2 rjmp st inc r16 out PORTB, r16 rjmp st gruss fubu
hallo, ui da fällt mir ein du solltest die taster entprellen!! also: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ldi r16, 0xFB out DDRD, r16 ldi r16, 0x07 out DDRB, r16 ;----------------------------------------------------------------------- - mainloop: ldi r16, 0x00 st: in r20, PIND sbrc r20, 2 rjmp st inc r16 out PORTB, r16 rcall tastenwait rjmp st tastenwait: ;wartet ne halbe sek falls takt 1MHZ ; warte 499995 Zyklen: ldi R17, $0F WGLOOP0: ldi R18, $37 WGLOOP1: ldi R19, $C9 WGLOOP2: dec R19 brne WGLOOP2 dec R18 brne WGLOOP1 dec R17 brne WGLOOP0 ; ----------------------------- ; warte 3 Zyklen: ldi R17, $01 WGLOOP3: dec R17 brne WGLOOP3 ; ----------------------------- ; warte 2 Zyklen: nop nop ; ============================= ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; gruss fubu
Jochen, Dein Programm zählt hoch, solange der Taster gedrückt ist. Wenn Du Tastendrücke zählen willst, nützt Dir das nichts, da musst Du dann zählen, wenn der Übergang von unbetätigt auf betätigt erfolgt, also bei der entsprechenden Flanke (Pegelwechsel) am Eingang. Das genügt aber noch nicht, denn (mechanische) Taster prellen, was zur Folge hat, dass jeder Tastendruck mehrmals gezählt wird. Du brauchst also eine Kombination aus Entprellung und Flankenerkennung. Nachdem Du fubus Vorschlag analysiert und verstanden hast, solltest Du Dir mal Alternativen ansehen. Recht gut erklärt wird das z.B. hier: http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten Vermutlich werden da aber schon ein paar Dinge vorausgesetzt, die Du Dir noch nicht erarbeitet hast, weshalb es besser ist, wenn Du hier beginnst: http://www.mikrocontroller.net/articles/AVR-Tutorial ...
Vielen Dank für die Antworten ich werde mir das sofort ansehen! Aber wieso zählt es nicht dann hoch, wenn ich einen taster drücke: Wenn ich ihn drücke, wird das Register r16 erhöht und ausgegeben. Drücke ich ihn nicht, wird r16 nicht erhöht und das ausgegeben. Starte ich das Programm, ist r16 gleich null. Null wird ausgegeben. Drücke ich ihn, ist r16 gleich 00000001 und wird ausgegeben. Wenn der Taster jetzt nicht gedrückt wird, bleibt r16 unverändert und das vorherige wird ausgegeben, denn die Erhöhung wird übersprungen. Wird er jetzt gedrückt, wird r16 um eins erhöht usw. Was ist an diesem Denkstoß falsch?
Ich habe noch eien Frage. In dem ersten Link sind Pfeile verwendet. z.B. ldi temp1, 1<<LED in dem zweiten Link konnte ich nicht finden, was sie bedeuten. Könntet ihr mir das sagen?
Jochen wrote: > Vielen Dank für die Antworten ich werde mir das sofort ansehen! > Aber wieso zählt es nicht dann hoch, wenn ich einen taster drücke: Es zählt hoch, etwa eine Million mal pro Sekunde. Du bist halt nur zu langsam, das zu sehen. Peter
Jochen wrote: > Ich habe noch eien Frage. > In dem ersten Link sind Pfeile verwendet. > > z.B. > > ldi temp1, 1<<LED Im Endeffekt: Es wird das Bt mit dem Namen "LED" im Register "temp1" gesetzt und alle anderen Bits gelöscht. Aber eigentlich: Es wird eine "Eins" um "LED" Binärstellen nach links geschoben. Warum? Schau Dir die Unterschiede der Befehle ldi (sbr, andi, ori, cbr) und sbrs (sbrc) an (die F1-Taste im AVR-Studio ist Dein Freund), dann wirst Du merken, dass die eine Befehlsgruppe eine Bitmaske (Wert 0..255) erfordert, die andere Befehlsgruppe aber die Bitnummer (0..7). Um nun mit nur einem symbolischen Namen für das Bit auszukommen, macht man aus der Bitnummer die Bitmaske, indem man eine 1 um soviele Stellen nach links schiebt, wie die Wertigkeit der Bitnummer ist. ldi temp,3 ;setzt Bit 0 und 1, der Wert ist 3 ldi temp,1<<3 ;setzt Bit 3, der Wert ist 8 sbrs temp,3 ;überspringt den rjmp, wenn Bit 3 gesetzt ist rjmp weg_hier ;der Else-Zweig der IF-Abfrage... > > > in dem zweiten Link konnte ich nicht finden, was sie bedeuten. Doch, in irgendeinem Artikel des Tutorials wird das beiläufig angesprochen und ausführlich erklärt. Ich kann aber jetzt nicht sagen, wo, denn ich lese das Tutorial nicht intensiv (nicht als Wissensquelle), denn als ich anfing war es noch sehr dürftig und inzwischen habe ich mir das Wissen anderweitig erarbeitet. > Könntet ihr mir das sagen? Ich empfehle Dir, das gesamte Tutorial der Reihe nach abzuarbeiten, Du hast sogar die richtige Hardware dafür. Da werden sehr viele Missverständnisse schon im Vorfeld beseitigt. Viel Erfolg... ...
Ok danke für die Antworten. Ich habe das soweit verstanden. Nochmal zurück zu http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten Ich habe mir den ersten Abschnitt also die Lösung ohne Berücksichtigung der Prellung angesehen. Jetzt vergleich ich sie mit meiner Lösung. Inwiefern zählt meine Lösung eine Millionen mal pro Sekunde hoch wenn der Taster gedrückt ist, bei der Lösung vom Link dagegen jedoch nur exakt einmal pro Tastendruck?
> Inwiefern zählt meine Lösung eine Millionen mal pro Sekunde hoch wenn > der Taster gedrückt ist Deine Lösung (kopiert aus erstem Beitrag):
1 | ;Vorbereitungen: |
2 | cbi DDRD, 2 |
3 | sbi PORTD, 2 |
4 | sbi DDRB,0 |
5 | sbi DDRB,1 |
6 | sbi DDRB,2 |
7 | |
8 | mainloop: ;irreführede Bezeichnung, da dies nicht Teil der |
9 | ;Schleife ist!!! |
10 | |
11 | ldi r16, 0b00000000 ;r16 auf 0 setzen |
12 | |
13 | |
14 | st: ;Beginn der Schleife (Rücksprungmarke) |
15 | |
16 | in r17, PIND ;Eingangszustand (ganzes Byte) einlesen |
17 | sbrc r17,2 ;überspringe "rjmp st", wenn Taster gedrückt (L) |
18 | rjmp st ;Abbruch, wenn Taster nicht gedrückt |
19 | |
20 | inc r16 ;Zähler hoch, wenn Taster gedrückt ist, aber auch |
21 | ;in jeder bweiteren "Runde", solange der Taster gedrückt ist... |
22 | out PORTB, r16 ;Zählerstand anzeigen |
23 | rjmp st ;dasselbe nochmal... |
Deine Schleife (von st: bis rjmp st) wird voll durchlaufen, solange der Taster betätigt ist (L-Pegel) (sie wird verkürzt durchlaufen, wenn der Taster unbetätigt ist). Die Schleife ist aber so schnell, dass es Dir nicht gelingt, den Taster so kurz zu betätigen, dass ein Tastendruck nur einmal gezählt wird. Um bei jedem Tastendruck nur einen Schritt weiter zu zählen, musst Du eine Flankenerkennung bauen, die nur dann um 1 weiterzählt, wenn der Taster jetzt betätigt ist, vorher (in der vorhergehenden Runde der Schleife) aber unbetätigt war. Dazu muss man sich den vorherigen Zustand merken und den neuen Zustand damit vergleichen. Nur bei einem Unterschied hat sich der Pegel am Eingang geändert. Jetzt muss noch ermittelt werden, ob der Unterschied Auswirkung des Drückens oder des Loslassens war, denn man will ja nicht doppelt zählen. Wenn das alles klappt, dann funktioniert das zwar im Simulator, aber noch lange nicht mit einem mechanischen Taster, denn mechanische Taster oder Schalter prellen. Sie schalten also nicht einfach ein, sondern klappern eine Weile zwischen aus und ein hinundher, worauf der Mikrocontroller aufgrund seines enormen Arbeitstempos etliche Tastendrücke erkennt. Dies kann man vermindern, indem man den Taster einfach langsamer abfragt. Die einfachste, aber uneffizienteste Variante ist die Warteschleife (siehe oben). Effizienter ist es aber, in der Wartezeit andere Aufgaben zu erledigen, daher schafft man sich mittels Timer einen Teit-Takt von etwa 5..20ms, in dem man die Tasten abfragt und auch noch andere Dinge erledigt, wie das Hochzählen der Zeit für eine Uhr. Im Tutorial findest Du eine Routine, die vereint das Abfragen der Taster mit Flankenerkennung und Vierfach-Entprellung. Sie ist genial, aber recht komplex, also für den Anfänger etwas schwer verständlich. Such mal in der Artikelsammkung nach "entprellung", da gibt es einige Links auf weiterführende Diskussion über diese Routine. ...
Alles klar, ich habe jetzt das ganze durchgearbeitet und es funktioniert. Herzlichen Dank!
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.