1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2 | ; Hauptprogramm ;
|
3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
4 |
|
5 | .include "m328Pdef.inc"
|
6 |
|
7 |
|
8 | .def temp1 = r16
|
9 | .def temp2 = r17
|
10 | .def temp3 = r18
|
11 |
|
12 |
|
13 | ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
|
14 | out SPL, temp1
|
15 | ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
|
16 | out SPH, temp1
|
17 |
|
18 | ldi temp1, 0xFF ;Port D = Ausgang
|
19 | out DDRD, temp1
|
20 |
|
21 | rcall lcd_init ;Display initialisieren
|
22 | rcall lcd_clear ;Display löschen
|
23 |
|
24 | ldi temp1, 'T' ;Zeichen anzeigen
|
25 | rcall lcd_data
|
26 |
|
27 | ldi temp1, 'e' ;Zeichen anzeigen
|
28 | rcall lcd_data
|
29 |
|
30 | ldi temp1, 's' ;Zeichen anzeigen
|
31 | rcall lcd_data
|
32 |
|
33 | ldi temp1, 't' ;Zeichen anzeigen
|
34 | rcall lcd_data
|
35 |
|
36 | loop:
|
37 | rjmp loop
|
38 |
|
39 |
|
40 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
41 | ;; LCD-Routinen ;;
|
42 | ;; ============ ;;
|
43 | ;; (c)andreas-s@web.de ;;
|
44 | ;; ;;
|
45 | ;; 4bit-Interface ;;
|
46 | ;; DB4-DB7: PD0-PD3 ;;
|
47 | ;; RS: PD4 ;;
|
48 | ;; E: PD5 ;;
|
49 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
50 |
|
51 | .def temp2 = r22
|
52 | .def temp3 = r23
|
53 |
|
54 | .equ LCD_PORT = PORTD
|
55 | .equ LCD_DDR = DDRD
|
56 | .equ PIN_RS = 4
|
57 | .equ PIN_E = 5
|
58 |
|
59 | .ifndef XTAL
|
60 | .equ XTAL = 4000000
|
61 | .endif
|
62 |
|
63 | ;sendet ein Datenbyte an das LCD
|
64 | lcd_data:
|
65 | push temp2
|
66 | push temp3
|
67 | mov temp2, temp1 ; "Sicherungskopie" für
|
68 | ; die Übertragung des 2.Nibbles
|
69 | swap temp1 ; Vertauschen
|
70 | andi temp1, 0b00001111 ; oberes Nibble auf Null setzen
|
71 | sbr temp1, 1<<PIN_RS ; entspricht 0b00010000
|
72 | in temp3, LCD_PORT
|
73 | andi temp3, 0x80
|
74 | or temp1, temp3
|
75 | out LCD_PORT, temp1 ; ausgeben
|
76 | rcall lcd_enable ; Enable-Routine aufrufen
|
77 | ; 2. Nibble, kein swap da es schon
|
78 | ; an der richtigen stelle ist
|
79 | andi temp2, 0b00001111 ; obere Hälfte auf Null setzen
|
80 | sbr temp2, 1<<PIN_RS ; entspricht 0b00010000
|
81 | or temp2, temp3
|
82 | out LCD_PORT, temp2 ; ausgeben
|
83 | rcall lcd_enable ; Enable-Routine aufrufen
|
84 | rcall delay50us ; Delay-Routine aufrufen
|
85 |
|
86 | pop temp3
|
87 | pop temp2
|
88 | ret ; zurück zum Hauptprogramm
|
89 |
|
90 | ; sendet einen Befehl an das LCD
|
91 | lcd_command: ; wie lcd_data, nur ohne RS zu setzen
|
92 | push temp2
|
93 | push temp3
|
94 |
|
95 | mov temp2, temp1
|
96 | swap temp1
|
97 | andi temp1, 0b00001111
|
98 | in temp3, LCD_PORT
|
99 | andi temp3, 0x80
|
100 | or temp1, temp3
|
101 | out LCD_PORT, temp1
|
102 | rcall lcd_enable
|
103 | andi temp2, 0b00001111
|
104 | or temp2, temp3
|
105 | out LCD_PORT, temp2
|
106 | rcall lcd_enable
|
107 | rcall delay50us
|
108 |
|
109 | pop temp3
|
110 | pop temp2
|
111 | ret
|
112 |
|
113 | ; erzeugt den Enable-Puls
|
114 | lcd_enable:
|
115 | sbi LCD_PORT, PIN_E ; Enable high
|
116 | nop ; 3 Taktzyklen warten
|
117 | nop
|
118 | nop
|
119 | cbi LCD_PORT, PIN_E ; Enable wieder low
|
120 | ret ; Und wieder zurück
|
121 |
|
122 | ; Pause nach jeder Übertragung
|
123 | delay50us: ; 50us Pause
|
124 | ldi temp1, ( XTAL * 50 / 3 ) / 1000000
|
125 | delay50us_:
|
126 | dec temp1
|
127 | brne delay50us_
|
128 | ret ; wieder zurück
|
129 |
|
130 | ; Längere Pause für manche Befehle
|
131 | delay5ms: ; 5ms Pause
|
132 | ldi temp1, ( XTAL * 5 / 607 ) / 1000
|
133 | WGLOOP0: ldi temp2, $C9
|
134 | WGLOOP1: dec temp2
|
135 | brne WGLOOP1
|
136 | dec temp1
|
137 | brne WGLOOP0
|
138 | ret ; wieder zurück
|
139 |
|
140 | ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
|
141 | lcd_init:
|
142 | push temp1
|
143 | in temp1, LCD_DDR
|
144 | ori temp1, (1<<PIN_E) | (1<<PIN_RS) | 0x0F
|
145 | out LCD_DDR, temp1
|
146 |
|
147 | ldi temp3,6
|
148 | powerupwait:
|
149 | rcall delay5ms
|
150 | dec temp3
|
151 | brne powerupwait
|
152 | ldi temp1, 0b00000011 ; muss 3mal hintereinander gesendet
|
153 | out LCD_PORT, temp1 ; werden zur Initialisierung
|
154 | rcall lcd_enable ; 1
|
155 | rcall delay5ms
|
156 | rcall lcd_enable ; 2
|
157 | rcall delay5ms
|
158 | rcall lcd_enable ; und 3!
|
159 | rcall delay5ms
|
160 | ldi temp1, 0b00000010 ; 4bit-Modus einstellen
|
161 | out LCD_PORT, temp1
|
162 | rcall lcd_enable
|
163 | rcall delay5ms
|
164 | ldi temp1, 0b00101000 ; 4 Bot, 2 Zeilen
|
165 | rcall lcd_command
|
166 | ldi temp1, 0b00001100 ; Display on, Cursor off
|
167 | rcall lcd_command
|
168 | ldi temp1, 0b00000100 ; endlich fertig
|
169 | rcall lcd_command
|
170 |
|
171 | pop temp1
|
172 | ret
|
173 |
|
174 | ; Sendet den Befehl zur Löschung des Displays
|
175 | lcd_clear:
|
176 | push temp1
|
177 | ldi temp1, 0b00000001 ; Display löschen
|
178 | rcall lcd_command
|
179 | rcall delay5ms
|
180 | pop temp1
|
181 | ret
|
182 |
|
183 | ; Cursor Home
|
184 | lcd_home:
|
185 | push temp1
|
186 | ldi temp1, 0b00000010 ; Cursor Home
|
187 | rcall lcd_command
|
188 | rcall delay5ms
|
189 | pop temp1
|
190 | ret
|
191 |
|
192 | ; Einen konstanten Text aus dem Flash Speicher
|
193 | ; ausgeben. Der Text wird mit einer 0 beendet
|
194 | lcd_flash_string:
|
195 | push temp1
|
196 |
|
197 | lcd_flash_string_1:
|
198 | lpm temp1, Z+
|
199 | cpi temp1, 0
|
200 | breq lcd_flash_string_2
|
201 | rcall lcd_data
|
202 | rjmp lcd_flash_string_1
|
203 |
|
204 | lcd_flash_string_2:
|
205 | pop temp1
|
206 | ret
|
207 |
|
208 | ; Eine Zahl aus dem Register temp1 dezimal ausgeben
|
209 | lcd_number:
|
210 | push temp1
|
211 | push temp2
|
212 | push temp3
|
213 |
|
214 | mov temp2, temp1
|
215 | ; abzählen wieviele Hunderter
|
216 | ; in der Zahl enthalten sind
|
217 | ldi temp1, '0'
|
218 | lcd_number_1:
|
219 | subi temp2, 100
|
220 | brcs lcd_number_2
|
221 | inc temp1
|
222 | rjmp lcd_number_1
|
223 | ;
|
224 | ; die Hunderterstelle ausgeben
|
225 | lcd_number_2:
|
226 | rcall lcd_data
|
227 | subi temp2, -100 ; 100 wieder dazuzählen, da die
|
228 | ; vorherhgehende Schleife 100 zuviel
|
229 | ; abgezogen hat
|
230 |
|
231 | ; abzählen wieviele Zehner in
|
232 | ; der Zahl enthalten sind
|
233 | ldi temp1, '0'
|
234 | lcd_number_3:
|
235 | subi temp2, 10
|
236 | brcs lcd_number_4
|
237 | inc temp1
|
238 | rjmp lcd_number_3
|
239 |
|
240 | ; die Zehnerstelle ausgeben
|
241 | lcd_number_4:
|
242 | rcall lcd_data
|
243 | subi temp2, -10 ; 10 wieder dazuzählen, da die
|
244 | ; vorhergehende Schleife 10 zuviel
|
245 | ; abgezogen hat
|
246 |
|
247 | ; die übrig gebliebenen Einer
|
248 | ; noch ausgeben
|
249 | ldi temp1, '0'
|
250 | add temp1, temp2
|
251 | rcall lcd_data
|
252 |
|
253 | pop temp3
|
254 | pop temp2
|
255 | pop temp1
|
256 | ret
|
257 |
|
258 | ; eine Zahl aus dem Register temp1 hexadezimal ausgeben
|
259 | lcd_number_hex:
|
260 | push temp1
|
261 |
|
262 | swap temp1
|
263 | andi temp1, $0F
|
264 | rcall lcd_number_hex_digit
|
265 |
|
266 | pop temp1
|
267 | push temp1
|
268 |
|
269 | andi temp1, $0F
|
270 | rcall lcd_number_hex_digit
|
271 |
|
272 | pop temp1
|
273 | ret
|
274 |
|
275 | lcd_number_hex_digit:
|
276 | cpi temp1, 10
|
277 | brlt lcd_number_hex_digit_1
|
278 | subi temp1, -( 'A' - '9' - 1 )
|
279 | lcd_number_hex_digit_1:
|
280 | subi temp1, -'0'
|
281 | rcall lcd_data
|
282 | ret
|