www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik erstes Programm, Binärzähler. Frage (Mega8)


Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: fubu1000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 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

Autor: fubu1000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

...

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

...

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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):
;Vorbereitungen:
  cbi DDRD, 2
  sbi PORTD, 2
  sbi DDRB,0
  sbi DDRB,1
  sbi DDRB,2

mainloop:             ;irreführede Bezeichnung, da dies nicht Teil der
;Schleife ist!!!

ldi r16, 0b00000000   ;r16 auf 0 setzen


st:                   ;Beginn der Schleife (Rücksprungmarke)

in r17, PIND          ;Eingangszustand (ganzes Byte) einlesen
sbrc r17,2            ;überspringe "rjmp st", wenn Taster gedrückt (L)
rjmp st               ;Abbruch, wenn Taster nicht gedrückt

inc r16               ;Zähler hoch, wenn Taster gedrückt ist, aber auch
;in jeder bweiteren "Runde", solange der Taster gedrückt ist...
out PORTB, r16        ;Zählerstand anzeigen
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.

...

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar, ich habe jetzt das ganze durchgearbeitet und es 
funktioniert. Herzlichen Dank!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.