Habe Probleme beim Ansteuern eines LCD-Displays und keine Lösung dafür
......
Folgende Gegebenheiten :
- Atmega128 auf Tinyboard (übrigens mein erster ;-) )
- 16 MHz Takt + 32 kHz Quarz
- 64*128 Grafik Display
Ich möchte auf dem Display ein paar Werte anzeigen und habe dazu im
EEPROM folgendes hinterlegt:
- Textpositionen auf dem Display
- Grafiken der einzelnen Zeichen und Ziffern
- Langtexte
Bisher habe ich von extern nur das Display (Portb für Steuerbefehle +
Porte für Daten) sowie drei Tasten (Portc 0-2) angeschlossen.
Die Ausgabe hat auch wunderbar funktioniert, bis ich zum erzeugen einer
Uhr den Timer0 in Betrieb genommen habe. Seit dem habe ich sporadisch
auftretende Displaystörungen.
D.h. es erscheinen plötzlich (mittlerweile nicht einmal mehr
unerwartet) Daten aus dem EEPROM auf dem Display die dort nicht
hingehören.
Nun habe ich schon die Steuerbefehle auf Porta gewechselt da an b wohl
auch noch Timerausgänge mit dranne sind, welche das ganze beeinflussen
können - jedoch ohne Erfolg.
Der Timer kommt alle 10 ms und vor und nach jeder Displayansteuerung
habe ich schon Verzögerungen eingebaut (ca.50 Takte).
Der Hersteller des Displays gibt im großen und ganzen ca. 10 ns für die
Kommunikation an.Also kann es wohl an der Geschwindigkeit auch nicht
liegen.
Die Daten auf dem Display gehen auch immer über eine ganze Zeile, dh.
irgendwie passiert da was kontrolliert....... nur leider nicht von mir
!
Hat irgendwer eine Idee ????
Währe sehr dankbar.
Shorty
Werden in einer Interrupt-Routine Pins gesteuert? Wenn ja, müssen alle
alle Read-Modify-Write Operationen auf diesen Ports gegen Interrupts
abgesichert werden. SBI/CBI sind von Haus aus wasserdicht, erzeugt der
Compiler aber
in/load
operate
out/store
und es kommt ein Interrupt dazwischen der diesen Port bearbeitet, dann
hast Du Pech gehabt.
Hallo,
Alle Register die ich in der Routine benutze werden gesichert ...
In der Routine werden keine I/O's gesteuert.
Ich habe zuerst den Zähler für meine Uhr im Speicher abgelegt und mir
vorgestellt, das wenn ich die Anzeige der Uhrzeit starte ich beim
Zugriff über die Register (X,Y,Z) mir irgendetwas durcheinander bringe
wenn der Interrupt einsetzt, aber auch nachdem ich in der Routine nur
noch mit r6-r9 arbeite ändert sich nix.
Habe ich evtl. bei der Initialisierung was falsch gemacht ?
Timer1Init:
ldi r16,0x02
out TCCR0,r16
ldi r16,215
out TCNT0,r16
ldi r16,0b00001000
out ASSR,r16
ldi r16,0x01
out TIMSK,r16
ldi r16,0b10001000
out sfior,r16
sei
ret
Habe mir dir Werte ausschließlich aus den ATMEL-Beschreibungen
zurechtgebastelt.
Die IRQ-Routine für den Timer habe ich auf 0040 Platziert (jmp
Timer1).
Timer1:
push r16
push r17
mov r16,Var1 ;Variable für zehntl-Sec. (r6)
inc r16
mov Var1,r16
cpi r16,100
brlt Timer1End
ldi r16,0
mov Var1,r16
.......
hier kommen dann noch Var2-4 für Sec,Min,Std.
.......
Timer1End:
ldi r16,221
out TCNT0,r16
pop r17
pop r16
reti
Die Einstellung des Interrupts kann eigentlich gar nicht richtig sein,
da ich keine genaue Uhrzeit bekomme ....
Aber, jeder Anfang ist schwer ;-)
Und wie siehts aus mit
push r16
in r16,SREG
push r16
push r17
.....
.....
pop r17
pop r16
out SREG,r16
pop r16
Du hast einfach vergessen, das Statusregister (WICHTIG) zu sichern.
Geht auch kürzer, wenn man sich für das Statusregister eines der
Register reserviert:
.def StReg=r3
in StReg,SREG
...
out SREG,StReg
Gruß
Andi
Ach ja, gerade mit einem Mega128 würde ich das NICHT über Register
machen sondern soweit möglich die Variablen im SRAM speichern.
Man nimmt ja nicht einfach so einen Mega128 (nicht für kleine Dinge)
und irgend wann, bei einem größeren Projekt, ärgerst Du dich dann, das
Du für eine Funktion die viele Register benötigt (32Bit-Operationen und
Pointer) kein Register mehr frei hast und dauernd am pushen und poppen
bist.
Gruß
Andi
Das mit den Registern hab ich auch erst im nachhinein gemacht, als ich
keinen Ausweg mehr wusste ...
Hatte vorher auch über das Ram gespeichert.
Aber wie gesagt, dachte mir halt, das ich beim abrufen der Daten aus
dem Ram und dann auftretenden IRQ (welches die Daten ja denne auch
direkt ins Ram schreibt) Prob kriege.Erst daraufhin habe ich auf die
Register zurückgegriffen um sicher zu gehen .....
tüüttelüt .... nach sichern des SREG läuft es nun seit 10 min.
Kannst du mir sagen, was mit dem Register während dem IR passiert ?
warum ist das Ding mit sichern und wieder herstellen so wichtig ??
Im Statusregister 'SREG' sind die Ergebnisse nach CPI, ADD, SUB in
Binärform (C=Carry, Z=Zero, N=Negative, V=Overflow, H=Halfcarry,
T=Transport-Flag) gespeichert.
Wenn in Deinem Main z. B. ein Zähler mit 'dec Counter' runtergezählt
wird und darauf ein 'brne loop' kommt wird vom zufällig kommendem
Interrupt das Z-Flag durch ein weiteres CPI verändert und das
Main-Programm trifft nach dem Interrupt eine falsche Entscheidung.
Da es nur ein Statusregister gibt muß das im Interrupt gesichert werden
um das Main-Programm nicht zu irritieren.
Ne bessere Erklärung ist mir jetzt leider nicht eingefallen, klingt
vielleicht ein bißchen wirr :-)
Gruß
Andi
nee..
ist schon völlig ausreichend.
Jetzt gibt das ganze auch wieder Sinn..... (mehr oder weniger)
Danke.
Kann ich nun also den ganze Code wieder umschreiben (wech von den
Registern).
Die Anzeige sieht nun "fast" gut aus. Bemerke immer noch einige
Unregelmäßigkeiten (leider) die ich jedoch bei weiteren Anzeigen mit
überbügeln kann.
Bedanke mich .....
Shorty
Eine eigene Frage?
Dieser Thread ist über 21 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.