Hallo Mikrocontroller-Community,
da ich jetzt schon seit sehr langer Zeit am verzweifeln bin auf Grund
meines nicht funktionierenden LCD, wende ich mich nun hier an euch, auch
wenn ich weiß dass es bereits haufenweise Threads gibt. Jedoch brachte
keine der Lösungsansätze Erfolg bei mir, Erstmal zur Beschreibung:
Ich nutze ein STK 500 mit ATMega8L und habe an PORTD mein LCD vom Typ
Displaytech 162C, welches einen KS0070B Controller besitzt. An PORTB
habe ich die LED-reihen, um Rückmeldungen über den Programmverlauf zu
machen (erwies sich aber als sinnlos, Erklärung folgt). Poti als
Kontrast, PD0-3 als DB4-7, RS auf PD4, E auf PD5, wie im Tutorial hier.
Nun das Problem:
Ich will das Display als 4 Bit ansteuern und habe das Datenblatt des
Displays mit der lcd-routine von hier verglichen und sie scheint
identisch. Trotzdem funktioniert die initialisierung nicht. Das einzige
was je erschienen ist waren die Balken in der 1. Zeile. Egal welche
Lösungsvorschläge es im Internet gab, nichts wollte funktionieren, auch
Fleurys Library hat nicht funktioniert. Bin hier echt am verzweifeln.
Was mich zudem verwirrt ist:
1
rcall life
2
rcall lcd_init ; Display initialisieren
3
rcall life
4
rcall lcd_clear ; Display löschen
5
6
...
7
8
delay1s: ; 1s Pause (bei 4 MHz)
9
ldi r16, 200
10
loop2:
11
rcall delay5ms
12
dec r16
13
brne loop2
14
15
ret
16
17
life:
18
push r16
19
20
ldi r16,0x00
21
out PORTB, r16
22
23
rcall delay1s
24
25
ldi r16,0xFF
26
out PORTB, r16
27
28
rcall delay1s
29
30
pop r16
31
ret
Hier scheinen irgendwelche Fehler abzulaufen, denn die LEDs gehen erst
gar nicht aus, warum? Sie leuchten dauerhaft durch, obwohl ich ja zum
schluss 0xFF auf PORTB ausgebe was sie ja eigentlich ausschalten sollte.
(LED6 und LED7 leuchten auch nicht, keine Ahnung warum)
Mfg Bernhard
Das PB6 und PB7 dauerhaft leuchten könnte ein Oszillator Problem sein,
wenn du auf dem STK500 testest. Welche Oszillator-Einstellungen für das
STK 500 hast du gewählt?
Evtl. läuft das ganze viel zu schnell oder zu langsam.
Ist noch wie im Auslieferungszustand, d.h XTAL ist gesetzt und OSCSEL
auf On-Board Software Clock Signal
Einen externen Quarz habe ich moment leider nicht hier, weil ich den
Paketboten gestern verpasst habe.
Hat keiner eine Ahnung? Habe mir ein anderes LCD bestellt. Vlt bringt
dass ja Abhilfe, koennte ich eigentlich auf dem Breadboard zwischen
PD0-3 je eine LED mit Widerstand setzen um zu pruefen ob Signale
durchkommen? Oder wuerde eine LED zu viel Strom ziehen? Tut mir leid
falls die Frage einfach ist, bin noch Neuling im Elektronikbereich.
Bernhard Drescher schrieb:> Hier scheinen irgendwelche Fehler abzulaufen, denn die LEDs gehen erst> gar nicht aus, warum?
Du musst dir in Assembler angewöhnen, auf die Register zu achten
Wenn du hier
1
delay1s: ; 1s Pause (bei 4 MHz)
2
ldi r16, 200
3
loop2:
4
rcall delay5ms
5
dec r16
6
brne loop2
7
8
ret
die delay5ms aufrufst, dann darf delay5ms das Register r16 nicht
verändern! Denn ansonsten decrementierst du irgendwas, was du nicht mehr
unter Kontrolle hast.
Daher die Frage: macht die delay5ms irgendwas mit dem r16?
1
; Längere Pause für manche Befehle
2
delay5ms: ; 5ms Pause (bei 4 MHz)
3
ldi temp1, $21
4
WGLOOP0: ldi temp2, $C9
5
WGLOOP1: dec temp2
6
brne WGLOOP1
7
dec temp1
8
brne WGLOOP0
9
ret ; wieder zurück
Da werden die Register temp1 und temp2 verändert:
1
.def temp1 = r16
2
.def temp2 = r17
3
.def temp3 = r18
Daher: Ja! delay5ms verändert das Register r16!
Und zwar so, dass es 0 ist, wenn delay5ms wieder zurückkommt nach
delay1s! WEnn aber hier
1
rcall delay5ms
nach dem Aufruf in r16 eine 0 steht, und zwar IMMER, dann wird dir
gleich danach
1
dec r16
2
brne loop2
mit Sicherheit niemals 0 rauskommen, sondern immer 255. D.h. der brne
wird IMMER springen. Du hast also in deiner Wartefunktion eine
Endlosschleife gebaut.
Und damit kommt dein Programm hier
1
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
2
out SPL, temp1
3
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
4
out SPH, temp1
5
6
ldi temp1, 0xFF ; Port D = Ausgang
7
out DDRD, temp1
8
9
ldi temp1, 0xFF ; Port B = Ausgang
10
out DDRB, temp1
11
12
rcall life
13
14
rcall lcd_init ; Display initialisieren
gar nicht über den ersten Aufruf von 'life' drüber und damit nie zu
lcd_init.
Wenn du Code veränderst oder erweiterst UND du andere Funktionen
aufrufst, dann musst du immer darauf achten, was diese aufgerufenen
FUnktionen mit den Registern machen!
Das ist nun mal das Los der Assembler-Programmierer, sich um solchen
Kleinkram kümmern zu müssen und es ist einer der Gründe, warum Assembler
programmieren generell als schwieriger gilt, eben weil man sich auch
noch um zig kleine Details kümmern muss und man sich ganz schnell
unbemerkt ein Eigentor schiesst.
Vielen Dank für die schnelle Antwort. Ja, da hab ich wohl einiges
übersehen. Ich will aber lieber in Assembler programmieren, da ich von C
und C++ aus gestartet habe und anstatt Software momentan
Hardware-Programmierung testen will, um mich für ein Studiumsfach
entscheiden zu können.
Blinklicht funktioniert jetzt nach push / pop bei delay5ms. Vielen Dank
nochmal, jetzt muss nur noch die Init-Routine fehlerfrei ablaufen
können...
Hinweis:
LCD Timing ist nur insofern kritisch, als du nicht zu kurz werden
darfst. Aber länger darfst du werden so viel du willst.
Wenn in der Init die 0x03 angelegt sind, kannst du auch 10 Sekunden
warten ehe du dann mal den E Pin langsam mal auf 1 ziehst, eine halbe
Stunde wartest und den Pin wieder auf 0 fallen lässt. Und in der Zeit
kann man mal direkt am LCD nachmessen, was da eigentlich ankommt.
ok, habe jetzt LEDs mit je 1k Vorwiderstand an die Pins parallel
gehängt, die Sigale kommen durch und auch in der richtigen Reihenfolge,
zwischen jedem Signal warte ich 1 Sekunde. Trotzdem bleibt es bei den
schwarzen Blöcken in der ersten Zeile...
Neuen Quellcode reiche ich gleich nach