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