Hallo,
ich versuche gerade, eine "Clear Display"-Routine für das DG12232 von
Pollin zu schreiben, einen sattsam bekannten, nicht ganz einfachen
Vertreter der LCDs... eigentlich klappt auch alles ganz gut:
- beide Displayhälften lassen sich ein- und ausschalten
- ich kann eine Page problemlos hin und her beschreiben und löschen
- ich kann EINE Page auswählen (beliebig 0-3) und dort was machen
Das Problem tritt auf, wenn ich versuche, ALLE Pages hintereinander über
eine Schleife anzusprechen und jeweils zu löschen (PORTC0-4:
Steuerbefehle, PORTA0-7: Daten):
; PA0..7: DB7..0, lcd_data byte for writing/lcd_command
18
.equ LCD_ON_PORTA= 0b10101111
19
.equ LCD_OFF_PORTA= 0b10101110
20
.equ LCD_STARTLINE_PORTA= 0b11000000 ; use with "OR line#" (0..31)
21
.equ LCD_SETPAGE_PORTA= 0b10111000 ; use with "OR page#" (0..3)
22
.equ LCD_SETCOLUMN_PORTA= 0b00000000 ; use with "OR column#" (0..79)
23
.equ LCD_SELECTADC_PORTA= 0b10100000 ; use with "OR ccw_output" (0/1)
24
.equ LCD_READMODIFYWRITE_PORTA=0b11100000 ; for updating small parts of LCD
25
.equ LCD_END_PORTA= 0b11101110 ; end the read-modify-write mode
26
.equ LCD_RESET_PORTA= 0b11100010 ; reset display
27
28
[...]
29
; Display an
30
ldi lcd_command, LCD_COMMAND_PORTC
31
out PORTC, lcd_command ; LCD ist im "command"-Modus...
32
ldi lcd_data, LCD_ON_PORTA
33
out PORTA, lcd_data ; ...und bekommt das Kommando "an"
34
cbi PORTC, CS1
35
sbi PORTC, CS1
36
cbi PORTC, CS2
37
sbi PORTC, CS2 ; jetzt sind beide Displayhälften an
38
39
; Reset
40
ldi lcd_command, LCD_RESET_PORTA
41
out PORTA, lcd_command
42
cbi PORTC, CS1
43
sbi PORTC, CS1
44
45
; clear display
46
rcall clear_display_LCD
47
48
;------------------------
49
clear_display_LCD:
50
push lcd_command
51
push lcd_page
52
53
ldi lcd_command, LCD_STARTLINE_PORTA
54
ori lcd_command, 0 ; start line is 0
55
rcall send_lcd_command_to_both_LCD ; diese Routine ist getestet und funktioniert
56
ldi lcd_command, LCD_SETPAGE_PORTA
57
ori lcd_command, 0 ; go to page 0 (a page is one set of eight lines)
58
rcall send_lcd_command_to_both_LCD
59
ldi lcd_command, LCD_SETCOLUMN_PORTA
60
ori lcd_command, 0 ; go to column 0 (now we should be at the top left pixel/byte)
61
rcall send_lcd_command_to_both_LCD
62
63
ldi lcd_page, 0
64
rcall clear_lcd_display_page
65
ldi lcd_page, 1
66
rcall clear_lcd_display_page
67
ldi lcd_page, 2
68
rcall clear_lcd_display_page
69
ldi lcd_page, 3
70
rcall clear_lcd_display_page
71
72
pop lcd_page
73
pop lcd_command
74
;-------------------------
75
clear_lcd_display_page:
76
; clear display page
77
push lcd_command
78
push lcd_data
79
ldi lcd_command, LCD_SETPAGE_PORTA
80
or lcd_command, lcd_page
81
rcall send_lcd_command_to_both_LCD_special
82
push counter
83
ldi counter, 0
84
clear_next_byte:
85
ldi lcd_data, 0x00
86
rcall send_lcd_data_to_both_LCD
87
inc counter
88
cpi counter, 61
89
brne clear_next_byte
90
pop counter
91
pop lcd_data
92
pop lcd_command
93
ret
Was passiert, ist, daß EINE Page gelöscht wird und danach nichts mehr
geschieht. Ich hab das Programm im Simulator getestet, alles wunderbar,
beide Schleifen laufen so durch wie gedacht. Ich hab gestern drei
Stunden an diesem Problem gesessen und vermute ein dickes Brett vorm
Kopf... sieht jemand den Fehler?
Dasselbe passiert auch, wenn ich folgende Routine verwende (hier ohne
die push/pop-Teile, die sind eigentlich nicht zwingend notwendig):
1
clear_display:
2
; Initialisierung: Start bei Page 0 (überflüssig, aber gründlich)
3
ldi lcd_command, LCD_SETPAGE_PORTA
4
ori lcd_command, 0 ; Page auf Start setzen
5
out PORTA, lcd_command
6
cbi PORTC, CS1
7
sbi PORTC, CS1
8
9
; Schleife über alle Pages
10
ldi tmp2, 0 ; Page counter, Schleife loop_tmp2 von 0 bis 3
11
12
loop_tmp2:
13
rcall wait1s ; damit ich sehen kann, was auf dem Display passiert
OK, gelöst... man sollte dran denken, daß nach einem Page-Wechsel im
Display der Column-Counter immer noch auf 61 steht... und ihn
entsprechend resetten. Jetzt geht alles freu