Forum: Mikrocontroller und Digitale Elektronik Drehgeber auswertung und lcd ausgabe


von Manu (Gast)


Angehängte Dateien:

Lesenswert?

Hi!

Das angehängte Programm soll erstmal 0 auf nem Display ausgeben.
Das macht es auch...

Danach sollen mittels interrupts die impulse von einer
drehencoderschaltung abgefangen werden.
Die Drehencoderschaltung ist mit T Flipflops aufgebaut, und es gibt
zwei ausgänge, einen für links und einen für rechts drehen.
Also die entprellung ist kein Thema, hab ich auch schon durchgemessen.
Sind sehr saubere Signale.

Nun sollen wie gesagt die Signale abgefangen werden und in ein
zählregister incrementiert bzw decrementiert werden.
danach wird das zählregister durch 100, 10 und 1 geteilt und die
jeweilige anzahl der stellen in einzelne register (hunderter, zehner,
einer) gezählt werden.
Danach werden diese drei register jeweils mit 30 dezimal addiert und
somit zu ASCII zeichen gemacht und auf ein LCD ausgegeben werden.

Jedoch zeigt das LCD durchgehend 0.
Ich kann mir, zumindest bis jetz noch nicht erklären wo das problem
liegt.
vielleicht könnt ihr mir ja helfen.

MfG
Manuel

von Hannes L. (hannes)


Lesenswert?

Also ich weiß jetzt nicht, wie Du die Ausgabeposition auf dem LCD
fixierst. Auch verstehe ich nicht, warum Du in Main den Zähler mir dem
ASCII-Wert von '0' lädtst. Zählen tut man binär, die Umwandlung in
ASCII erfolgt erst bei der Ausgabe an das LCD. Hierzu schreibt man sich
Ausgaberoutinen, das macht man nicht in der Mainloop.

Hier ein Beispiel für eine Ausgaberoutine für ein Register:
Zuerst das Macro, das die Routine aufruft:

.macro print8 ;Registername
                        ;Gibt Zahl im Register 2- oder 3-stellig am LCD
aus.
                        ;Parameter bestimmt das Register, in dem die
Zahl liegt.
                        ;Dieses Register wird nicht verändert.
                        ;Kopie der Zahl temporär in xl,
 push xl                    ;verwendete Register sichern
 mov xl,@0                  ;Kopie vom Quellregister
 rcall lcd_printb           ;Aufruf von "Print Byte"...
 pop xl                     ;verwendete Register wiederherstellen
.endmacro               ;

Das Macro ruft dann diese Routine auf:

lcd_printb:             ;Wird vom Makro aufgerufen. Gibt Byte als 2
                        ;oder 3 Ziffern an LCD aus.
 push wl                    ;Reg sichern
 ldi wl,-1+'0'              ;Hunderter-Stelle als ASCII-Zeichen,
                            ;Zahl ist positiv
 inc wl                     ;Hunderter hoch und
 subi xl,100                ;100 subtrahieren bis zum Unterlauf
 brsh pc-2                  ;Unterlauf? nein, 2 Zeilen hoch
; cpi wl,'0'                 ;ja, ist Ziffer = "0"?
; breq pc+2                  ;ja, nicht ausgeben...
 rcall lcd_data             ;Hunderter ausgeben...
 ldi wl,10+'0'              ;Zehner-Stelle als ASCII-Zeichen,
                            ;Zahl ist jetzt unter 0
 dec wl                     ;Zehner runter und
 subi xl,-10                ;10 addieren bis Überlauf
 brlo pc-2                  ;Überlauf? nein, 2 Zeilen hoch...
 rcall lcd_data             ;ja, Zehner Stelle ausgeben...
 ldi wl,'0'                 ;ASCII-0
 add wl,xl                  ;Einer addieren (Rest war ja über 0)
 rcall lcd_data             ;Einer ausgeben...
 pop wl                     ;Reg wiederherstellen
 ret                        ;zurück

Die Unterdrückung der ersten Führungsnull ist in diesem Beispiel
deaktiviert (auskommentiert). Die Zahl wird also dreistellig
ausgegeben.
Das Temp-Register zur Übergabe an LCD_Data heißt bei mir 'wl', Du
musst den Code also an Deine Variablennamen in Deinem LCD-Treiber
anpassen.

Um die Ausgabeposition vor jeder Ausgabe neu einzustellen, solltest Du
Dir mal im Datenblatt des LCDs das Kommando 'SET DD-RAM-Address'
ansehen. Von LCD_Clear und LCD_Home rate ich ab, das dauert recht
lange. Ausgabecursor positionieren und Leerzeichen ausgeben ist
bedeutend schneller.

Aus dem Hauptprogramm heraus kann nun mit
 print8 zaehler
der Inhalt des Registers namens 'zaehler' am LCD ausgegeben werden.

Eine Sammlung weiterer LCD-Ausgaberoutinen findest Du z.B. in der Datei
LCDprinta.inc auf folgender Seite:
http://www.hanneslux.de/avr/stopuhr/index.html
Dort siehst Du auch, wie einfach die LCD-Ausgabe auch in Assembler sein
kann.

...

von Manu (Gast)


Lesenswert?

Nicht schlecht!

Jetz, als ich das ne stunde auf mich wirken lies, steig ich auch durch
wie es viel eleganter zu machen ist!
Da sieht man halt die unterschiede zwischen einem anscheinend
erfahrenen programmierer und einem Anfänger ganz deutlich!

Ist es vielleicht möglich das mein Programm trozdem wegen eines
Interruptproblems nicht ging, denn es müsste ja zumindest die 30, die
aufgrund meines bugs nach dem ersten schleifendurchgang geladen wird
angezeigt werden.
Es ist doch schon so, dass mit "sei" die Interrupts komplett
aktiviert sind und ich die dann benutzen kann oder?

Vielen dank,
Manuel

von Hannes L. (hannes)


Lesenswert?

Du musst zusätzlich zu SEI jeden benutzten Interrupt einzeln
freischalten. Bei den Timern sind das die "timsk"-Register (alte AVRs
haben nur eins, einige neue AVRs für jeden Timer ein separates), bei den
externen Interrupts das GIMSK. Am besten im Datenblatt des benutzten
AVRs nachschlagen, mache ich auch nicht anders.

So "erfahren" bin ich übrigens auch nicht, ich gebe mir nur Mühe, den
Code lesbar zu schreiben.

Viel Erfolg...

...

von Manu (Gast)


Angehängte Dateien:

Lesenswert?

Ok, funktioniert alles wie ich es will...
Nur mal der vollständigkeit halber der fertige code angehängt

Gruß
Manu

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
Noch kein Account? Hier anmelden.