1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2 | ;; LCD-Routinen für das Pollin Addon-Board ;;
|
3 | ;; ======================================= ;;
|
4 | ;; 4bit-Interface ;;
|
5 | ;; DB4-DB7: PA4-PA7 ;;
|
6 | ;; RS: PB2 ;;
|
7 | ;; R/W: PB1 ;;
|
8 | ;; E: PB0 ;;
|
9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
10 |
|
11 | ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
|
12 | lcd_init:
|
13 | push temp1
|
14 | push temp2
|
15 | ldi temp1, 0b11110000
|
16 | ldi temp2, 0b00000111
|
17 | out DDRA, temp1
|
18 | out DDRB, temp2
|
19 | ldi temp3,6
|
20 | powerupwait:
|
21 | rcall delay5ms
|
22 | dec temp3
|
23 | brne powerupwait
|
24 | ldi temp1, 0b00000011 ; muss 3mal hintereinander gesendet
|
25 | ldi temp2, 0b00000000 ; Berechnung der Bytes für PORTA und PORTB
|
26 | swap temp1
|
27 | bst temp1,0
|
28 | bld temp2,2
|
29 | bst temp1,2
|
30 | bld temp2,0
|
31 | andi temp1, 0b11110000
|
32 | andi temp2, 0b00000101
|
33 | out PORTA, temp1 ; Initialisierung
|
34 | out PORTB, temp2
|
35 | rcall lcd_enable ; 1
|
36 | rcall delay5ms
|
37 | rcall lcd_enable ; 2
|
38 | rcall delay5ms
|
39 | rcall lcd_enable ; und 3!
|
40 | rcall delay5ms
|
41 | ldi temp1, 0b00000010 ; 4bit-Modus einstellen
|
42 | ldi temp2, 0b00000000 ; Berechnung der Bytes für PORTA und PORTB
|
43 | swap temp1
|
44 | bst temp1,0
|
45 | bld temp2,2
|
46 | bst temp1,2
|
47 | bld temp2,0
|
48 | andi temp1, 0b11110000
|
49 | andi temp2, 0b00000101
|
50 | out PORTA, temp1
|
51 | out PORTB, temp2
|
52 | rcall lcd_enable
|
53 | rcall delay5ms
|
54 | ldi temp1, 0b00101000 ; 4 Bit, 2 Zeilen
|
55 | rcall lcd_command
|
56 | ldi temp1, 0b00001111 ; Display on, Cursor off
|
57 | rcall lcd_command
|
58 | ldi temp1, 0b00000110 ; endlich fertig
|
59 | rcall lcd_command
|
60 |
|
61 | pop temp2
|
62 | pop temp1
|
63 | ret
|
64 |
|
65 | ;sendet ein Datenbyte an das LCD
|
66 | lcd_data:
|
67 | push temp2
|
68 | push temp3
|
69 | mov temp2, temp1 ; "Sicherungskopie" für
|
70 | ; die Übertragung des 2.Nibbles
|
71 | andi temp1, 0b11110000 ; unteres Nibble auf Null setzen
|
72 | out PORTA, temp1 ; ausgeben
|
73 | sbi PORTB, 2 ; RS auf 1
|
74 | rcall lcd_enable ; Enable-Routine aufrufen
|
75 | ; 2. Nibble, swap
|
76 | swap temp2
|
77 | andi temp2, 0b11110000 ; untere Hälfte auf Null setzen
|
78 | out PORTA, temp2 ; ausgeben
|
79 | sbi PORTB, 2 ; RS auf 1
|
80 | rcall lcd_enable ; Enable-Routine aufrufen
|
81 | rcall delay50us ; Delay-Routine aufrufen
|
82 |
|
83 | pop temp3
|
84 | pop temp2
|
85 | ret ; zurück zum Hauptprogramm
|
86 |
|
87 | ; sendet einen Befehl an das LCD
|
88 | lcd_command: ; wie lcd_data, nur ohne RS zu setzen
|
89 | push temp2
|
90 | push temp3
|
91 | mov temp2, temp1 ; "Sicherungskopie" für
|
92 | ; die Übertragung des 2.Nibbles
|
93 | andi temp1, 0b11110000 ; unteres Nibble auf Null setzen
|
94 | out PORTA, temp1 ; ausgeben
|
95 | cbi PORTB, 2 ; RS auf 0
|
96 | rcall lcd_enable ; Enable-Routine aufrufen
|
97 | ; 1. Nibble, kein swap da es schon
|
98 | swap temp2 ; an der richtigen stelle ist
|
99 | andi temp2, 0b11110000 ; untere Hälfte auf Null setzen
|
100 | out PORTA, temp2 ; ausgeben
|
101 | cbi PORTB, 2 ; RS auf 0
|
102 | rcall lcd_enable ; Enable-Routine aufrufen
|
103 | rcall delay50us ; Delay-Routine aufrufen
|
104 |
|
105 | pop temp3
|
106 | pop temp2
|
107 | ret ; zurück zum Hauptprogramm
|
108 |
|
109 | ; Kurze Pause
|
110 | delay50us: ; 50us Pause
|
111 | push temp1
|
112 | ldi temp1, ( XTAL * 50 / 3 ) / 1000000
|
113 | delay50us_:
|
114 | dec temp1
|
115 | brne delay50us_
|
116 | pop temp1
|
117 | ret
|
118 |
|
119 | ; Längere Pause für manche Befehle
|
120 | delay5ms: ; 5ms Pause
|
121 | push temp1
|
122 | push temp2
|
123 | ldi temp1, ( XTAL * 5 / 607 ) / 1000
|
124 | WGLOOP0: ldi temp2, $C9
|
125 | WGLOOP1: dec temp2
|
126 | brne WGLOOP1
|
127 | dec temp1
|
128 | brne WGLOOP0
|
129 | pop temp2
|
130 | pop temp1
|
131 | ret
|
132 |
|
133 | ; Enable senden
|
134 | lcd_enable:
|
135 | sbi PORTB, 0 ; Enable high
|
136 | nop ; 3 Taktzyklen warten
|
137 | nop
|
138 | nop
|
139 | cbi PORTB, 0 ; Enable wieder low
|
140 | ret
|
141 |
|
142 | ; Sendet den Befehl zur Löschung des Displays
|
143 | lcd_clear:
|
144 | push temp1
|
145 | ldi temp1, 0b00000001 ; Display löschen
|
146 | rcall lcd_command
|
147 | rcall delay5ms
|
148 | pop temp1
|
149 | ret
|
150 |
|
151 | ; Cursor Home
|
152 | lcd_home:
|
153 | push temp1
|
154 | ldi temp1, 0b00000010 ; Cursor Home
|
155 | rcall lcd_command
|
156 | rcall delay5ms
|
157 | pop temp1
|
158 | ret
|
159 |
|
160 | ; Einen konstanten Text aus dem Flash Speicher
|
161 | ; ausgeben. Der Text wird mit einer 0 beendet
|
162 | lcd_flash_string:
|
163 | push temp1
|
164 |
|
165 | lcd_flash_string_1:
|
166 | lpm temp1, Z+
|
167 | cpi temp1, 0
|
168 | breq lcd_flash_string_2
|
169 | rcall lcd_data
|
170 | rjmp lcd_flash_string_1
|
171 |
|
172 | lcd_flash_string_2:
|
173 | pop temp1
|
174 | ret
|
175 |
|
176 | ; Eine Zahl aus dem Register temp1 dezimal ausgeben
|
177 | lcd_number:
|
178 | push temp1
|
179 | push temp2
|
180 | push temp3
|
181 |
|
182 | mov temp2, temp1
|
183 | ; abzählen wieviele Hunderter
|
184 | ; in der Zahl enthalten sind
|
185 | ldi temp1, '0'
|
186 | lcd_number_1:
|
187 | subi temp2, 100
|
188 | brcs lcd_number_2
|
189 | inc temp1
|
190 | rjmp lcd_number_1
|
191 | ; die Hunderterstelle ausgeben
|
192 | lcd_number_2:
|
193 | rcall lcd_data
|
194 | subi temp2, -100 ; 100 wieder dazuzählen, da die
|
195 | ; vorherhgehende Schleife 100 zuviel
|
196 | ; abgezogen hat
|
197 |
|
198 | ; abzählen wieviele Zehner in
|
199 | ; der Zahl enthalten sind
|
200 | ldi temp1, '0'
|
201 | lcd_number_3:
|
202 | subi temp2, 10
|
203 | brcs lcd_number_4
|
204 | inc temp1
|
205 | rjmp lcd_number_3
|
206 |
|
207 | ; die Zehnerstelle ausgeben
|
208 | lcd_number_4:
|
209 | rcall lcd_data
|
210 | subi temp2, -10 ; 10 wieder dazuzählen, da die
|
211 | ; vorhergehende Schleife 10 zuviel
|
212 | ; abgezogen hat
|
213 |
|
214 | ; die übrig gebliebenen Einer
|
215 | ; noch ausgeben
|
216 | ldi temp1, '0'
|
217 | add temp1, temp2
|
218 | rcall lcd_data
|
219 |
|
220 | pop temp3
|
221 | pop temp2
|
222 | pop temp1
|
223 | ret
|
224 |
|
225 | ; eine Zahl aus dem Register temp1 hexadezimal ausgeben
|
226 | lcd_number_hex:
|
227 | push temp1
|
228 |
|
229 | swap temp1
|
230 | andi temp1, $0F
|
231 | rcall lcd_number_hex_digit
|
232 |
|
233 | pop temp1
|
234 | push temp1
|
235 |
|
236 | andi temp1, $0F
|
237 | rcall lcd_number_hex_digit
|
238 |
|
239 | pop temp1
|
240 | ret
|
241 |
|
242 | lcd_number_hex_digit:
|
243 | cpi temp1, 10
|
244 | brlt lcd_number_hex_digit_1
|
245 | subi temp1, -( 'A' - '9' - 1 )
|
246 | lcd_number_hex_digit_1:
|
247 | subi temp1, -'0'
|
248 | rcall lcd_data
|
249 | ret
|