Ich stell das Thema jetzt nochmal unter meinem Login und unter nem
besseren Titel rein. Also ich habe für mein 4x40 Display mit assembler
nen bissl was geschrieben in Anlehnung an das Tutorial hier. Das Problem
ist jetzt, dass ich jetzt immer Abwechselnd oben oder Unten nen
schwarzen Balken aufm Display habe und an der Jeweils anderen Seite 2x
hintereinander Test. hier der Code:
1
.include "m32def.inc"
2
3
.def temp1 = r16
4
.def temp2 = r17
5
.def temp3 = r18
6
.def lcdno = r19
7
8
9
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten
10
RAM-Adresse
11
out SPL, temp1
12
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten
13
RAM-Adresse
14
out SPH, temp1
15
16
ldi temp1, 0xFF ; Port D = Ausgang
17
out DDRD, temp1
18
19
cbr lcdno, 0
20
rcall lcd_init ; Display initialisieren
21
rcall lcd_clear ; Display löschen
22
sbr lcdno, 0
23
rcall lcd_init ; Display initialisieren
24
rcall lcd_clear ; Display löschen
25
26
27
cbr lcdno, 1
28
ldi temp1, 'T' ; Zeichen anzeigen
29
rcall lcd_data
30
31
ldi temp1, 'e' ; Zeichen anzeigen
32
rcall lcd_data
33
34
ldi temp1, 's' ; Zeichen anzeigen
35
rcall lcd_data
36
37
ldi temp1, 't' ; Zeichen anzeigen
38
rcall lcd_data
39
40
41
42
sbr lcdno, 1
43
ldi temp1, 'T' ; Zeichen anzeigen
44
rcall lcd_data
45
46
ldi temp1, 'e' ; Zeichen anzeigen
47
rcall lcd_data
48
49
ldi temp1, 's' ; Zeichen anzeigen
50
rcall lcd_data
51
52
ldi temp1, 't' ; Zeichen anzeigen
53
rcall lcd_data
54
55
loop:
56
rjmp loop
57
58
.include "lcd-routines.asm" ; LCD-Routinen werden hier eingefügt
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;; LCD-Routinen ;;
3
;; ============ ;;
4
;; (c)andreas-s@web.de ;;
5
;; ;;
6
;; 4bit-Interface ;;
7
;; DB4-DB7: PD0-PD3 ;;
8
;; RS: PD4 ;;
9
;; E: PD5 ;;
10
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11
12
13
.equ LCD_PORT = PORTD
14
.equ LCD_DDR = DDRD
15
.equ PIN_E = 5
16
.equ PIN_E2 = 6
17
.equ PIN_RS = 4
18
.equ XTAL = 16000000
19
20
;sendet ein Datenbyte an das LCD
21
lcd_data:
22
mov temp2, temp1 ; "Sicherungskopie" für
23
; die Übertragung des 2.Nibbles
24
swap temp1 ; Vertauschen
25
andi temp1, 0b00001111 ; oberes Nibble auf Null setzen
26
sbr temp1, 1<<PIN_RS ; entspricht 0b00010000
27
out LCD_PORT, temp1 ; ausgeben
28
rcall lcd_enable ; Enable-Routine aufrufen
29
; 2. Nibble, kein swap da es
30
schon
31
; an der richtigen stelle ist
32
andi temp2, 0b00001111 ; obere Hälfte auf Null setzen
33
sbr temp2, 1<<PIN_RS ; entspricht 0b00010000
34
out LCD_PORT, temp2 ; ausgeben
35
rcall lcd_enable ; Enable-Routine aufrufen
36
rcall delay50us ; Delay-Routine aufrufen
37
ret ; zurück zum Hauptprogramm
38
39
40
; sendet einen Befehl an das LCD
41
42
lcd_command: ; wie lcd_data, nur RS=0
43
mov temp2, temp1
44
swap temp1
45
andi temp1, 0b00001111
46
out LCD_PORT, temp1
47
rcall lcd_enable
48
andi temp2, 0b00001111
49
out LCD_PORT, temp2
50
rcall lcd_enable
51
rcall delay50us
52
ret
53
54
55
56
; erzeugt den Enable-Puls
57
lcd_enable:
58
sbrs lcdno, 1
59
sbi LCD_PORT, PIN_E ; Enable high
60
sbrc lcdno, 1
61
sbi LCD_PORT, PIN_E2 ; Enable high
62
nop ; 3 Taktzyklen warten
63
nop
64
nop
65
cbi LCD_PORT, PIN_E ; Enable wieder low
66
cbi LCD_PORT, PIN_E2
67
ret
68
; Und wieder zurück
69
70
71
72
; Pause nach jeder Übertragung
73
delay50us: ; 50us Pause
74
ldi temp1, ( XTAL * 50 / 4 ) / 1000000
75
delay50us_:
76
dec temp1
77
nop ; tu nichts
78
brne delay50us_
79
ret
80
81
; Längere Pause für manche Befehle
82
delay5ms: ; 5ms Pause
83
ldi temp1, ( XTAL * 5 / 607 ) / 1000
84
WGLOOP0: ldi temp2, $C9
85
WGLOOP1: dec temp2
86
brne WGLOOP1
87
dec temp1
88
brne WGLOOP0
89
ret ; wieder zurück
90
; wieder zurück
91
92
; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
cbr und sbr arbeiten jeweils mit Bitmasken, anstatt mit Bitnummern.
Um z.B. Bit 0 zu löschen musst du schreiben:
cbr flags, 1<<0
setzen erfolgt nach gleichem Schema
sbr flags, 1<<0
Ändere das mal bei dir.
Ich schätze mal, hier liegt der Hund im Pfeffer:
.equ PIN_E = 5
.equ PIN_E2 = 6
.equ PIN_RS = 4
Das sollten alles Zweierpotenzen sein, wenn du einzelne Pins selektieren
willst.
Ja, du hast recht.
Du setzt/löscht Bit 0 und prüfst auf Bit 1.
Wenn du dir das bit als Konstante definierst wird das ganze auch besser
lesbar.
.equ SELECT = 0
sbr lcdno, 1<<SELECT
cbr lcdno, 1<<SELECT
bzw.
sbrs lcdno, SELECT
sbrc lcdno, SELECT
Namen kannst Du dir ja nen passenenden ausdenken.
Du könntest dir im SRAM ein Speicherbereich nehmen, der so groß wie die
Zeichenanzahl auf deinem LCD ist.
Alle ausgaben die aufs LCD gehen sollen biegst du dann so um, dass sie
ins SRAM an die gewünschte Position schreiben.
Den Inhalt vom SRAM gibts du dann von einem Timer gesteuert z.B. alle
paar ms komplett auf das Display aus. So besteht das Display für dein
Programm aus einem linear zusammenhängenen Bereich.
Die Aufteilung in Zeilen und Controller macht dann die Routine, die
alles aufs Display schaufelt.
z.B.
Display mit 4x27 Zeichen (5€-Teil bei Pollin)
Speicher im SRAM ist dann 4x27 = 108 Bytes groß.
Die Schreibroutine selektiert dann zuerst Controller 1, Zeile 1 und
schaufelt die ersten 27 Bytes raus.
Dann wird auf Zeile 2 umgeschaltet. Addresse und Befehl dafür steht im
Datenblatt vom Display und raus gehen die nächsten 27 Byte.
gleiches Spiel dann mit Controller 2
Ui...timer so weit bin ich im tutorial noch gar nicht...ich werde wohl
das Display erstmal 2 Zeilig betreiben und dann später wenn ich mehr
kann hier weiter machen...