1 | ;*-------------------------------------------------
|
2 | ;* Analog-Digital-Wandlung
|
3 | ;* mit Analog-Komparator
|
4 | ;* - - - - - - - - - - - - - - - - - - - - - - - -
|
5 | ;* Port B Bit 0 RC-Glied 1uF/10 kOhm
|
6 | ;* Port B Bit 1 Mess-Spannung
|
7 | ;* Port B Bit 3 Timer-PWM-Ausgang
|
8 | ;* MCU ATTiny4313, Takt 4 MHz
|
9 | ;* PortD LCD Ausgabe: R/W=GND
|
10 | ;* PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
|
11 | ;* n/a LED ena rs D7 D6 D5 D4
|
12 | ;* Adapter auf LCD-Port:
|
13 | ;* PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
|
14 | ;* D7 D6 D5 D4 LED n/a ena rs
|
15 | ; ATtiny4313 memory use summary [bytes]:
|
16 | ; Segment Begin End Code Data Used Size Use%
|
17 | ;--------------------------------------------------
|
18 | ;[.cseg] 0x000000 0x0002a6 650 28 678 4096 16.6%
|
19 | ;[.dseg] 0x000060 0x000060 0 0 0 256 0.0%
|
20 | ;[.eseg] 0x000000 0x000000 0 0 0 256 0.0%
|
21 | ;Assembly complete, 0 errors. 0 warnings
|
22 | ;--------------------------------------------------
|
23 | ;
|
24 | .nolist
|
25 | .include "tn4313def.inc"
|
26 | .list
|
27 | ;
|
28 | .def temp = r16 ; Temporaerregister 1
|
29 | .def temp1 = r17 ; Temporaerregister 2
|
30 | .def temp2 = r18 ; Temporaerregister 3
|
31 | .def temp3 = r19 ; Temporaerregister 4
|
32 | .equ daten = portd ; PortD nur 7 Bit Breite, Bit 7 fehlt
|
33 | .equ rs = 4 ; 0bn00x0000 Portbit Register Select
|
34 | .equ ena = 5 ; 0bn0x00000 Portbit Enable
|
35 | .equ licht = 6 ; 0bnx000000 Portbit LCD-Beleuchtung
|
36 | .equ zeit0 = 200 ; Zeitschleifen Ladewerte
|
37 | .equ zeit1 = 65535
|
38 | .cseg
|
39 | .org 0x0000
|
40 | rjmp main ; zum Hauptprogramm
|
41 | ;
|
42 | main:
|
43 | ldi temp, low(ramend) ; Stackpointer initialisieren
|
44 | out spl, temp
|
45 | ldi temp, high(ramend)
|
46 | out sph, temp ;
|
47 | ldi temp, 0xFF ; Ports einrichten
|
48 | out ddrb, temp ; PortB A/D
|
49 | out portb, temp ; Pullups setzen
|
50 | out ddrd, temp ; PortD Ausgabe LCD
|
51 | out portd, temp ; Pullups setzen
|
52 | rcall lcdinit
|
53 | ldi temp, 0x18 ; Watchdog enable (1<<WDCE)|(1<<WDE);=dec24 change-ena/+enable
|
54 | out WDTCR, temp
|
55 | ori temp, (1<<WDE)|(1<<WDP2)|(1<<WDP1);0x0E; Prescaler Set (1<<WDE)|(1<<WDP2)|(1<<WDP1)
|
56 | out WDTCR, temp ; ca. 1 sec timeout ;=dec30
|
57 | wdr
|
58 | ;
|
59 | rcall ad_init ; A/D-Konverter initialisieren
|
60 | rcall legende1
|
61 | rcall legende2
|
62 | rjmp endlos1
|
63 | ;
|
64 | endlos1:
|
65 | wdr
|
66 | rcall adc_on1
|
67 | lsr temp
|
68 | push temp1
|
69 | push temp
|
70 | ldi temp, 0x8D
|
71 | rcall comd2lcd
|
72 | pop temp
|
73 | mov temp1, temp
|
74 | rol temp1 ; Max. Anzeige 255 statt 127
|
75 | rcall bin2dec
|
76 | push temp
|
77 | ldi temp, 0xCD
|
78 | rcall comd2lcd
|
79 | pop temp
|
80 | mov temp1, temp
|
81 | rol temp1 ; Max. Anzeige 255 statt 127
|
82 | rcall bin2dec
|
83 | mov temp1, temp
|
84 | pop temp1
|
85 | clr temp
|
86 | rjmp endlos1
|
87 | ;
|
88 | legende1: ; Festtext: "Messwert_1 ="
|
89 | ldi temp, 0x80 ; Positionierung Anfang
|
90 | rcall comd2lcd ; Zeile 1, Spalte 1
|
91 | rcall wait2
|
92 | ldi ZL, LOW(text1*2) ; Adresse des Strings in den
|
93 | ldi ZH, HIGH(text1*2) ; Z-Pointer laden
|
94 | rcall print ; Funktion print aufrufen
|
95 | rcall wait3
|
96 | ret
|
97 | ;
|
98 | print:
|
99 | lpm ; erstes Byte des Strings nach R0 lesen
|
100 | mov temp, r0 ; R0 auf 0 testen
|
101 | cpi temp, 0x00 ; alternativer Befehl
|
102 | breq print_end ; wenn 0, dann zu print_end
|
103 | mov temp1, temp ; Datenausgabe hier nur ueber temp1
|
104 | rcall char2lcd
|
105 | adiw ZL:ZH, 1 ; Adresse des Z-Pointers um 1 erhoehen
|
106 | rjmp print ; zum Anfang springen, um naechstes
|
107 | ; ; Byte aus dem cseg-Label text1;zu holen
|
108 | print_end:
|
109 | rcall wait3
|
110 | ret
|
111 | ;
|
112 | text1:
|
113 | .db "Messwert_1 = ",0
|
114 | ;
|
115 | legende2: ; Festtext: "Messwert_2 ="
|
116 | ldi temp, 0xC0 ; Positionierung Anfang
|
117 | rcall comd2lcd ; Zeile 1, Spalte 1
|
118 | rcall wait2
|
119 | ldi ZL, LOW(text2*2) ; Adresse des Strings in den
|
120 | ldi ZH, HIGH(text2*2) ; Z-Pointer laden
|
121 | rcall print1 ; Funktion print aufrufen
|
122 | rcall wait3
|
123 | ret
|
124 | ;
|
125 | print1:
|
126 | lpm temp, Z+ ; erstes Byte des Strings nach temp lesen
|
127 | tst temp ; temp auf 0 testen
|
128 | breq print_end ; wenn 0, dann zu print_end
|
129 | mov temp1, temp ; Datenausgabe hier nur ueber temp1
|
130 | rcall char2lcd
|
131 | rjmp print1 ; zum Anfang springen, um naechstes
|
132 | ; ; Byte aus dem cseg-Label text1;zu holen
|
133 | text2:
|
134 | .db "Messwert_2 = ",0
|
135 | ;
|
136 | ad_init:
|
137 | wdr
|
138 | push temp
|
139 | ;ldi temp, 0x00
|
140 | ;out ddrb, temp
|
141 | cbi ddrb, 0
|
142 | ;out portb, temp
|
143 | cbi portb, 0
|
144 | cbi ddrb, 1
|
145 | cbi portb, 1
|
146 | ;ldi temp, 0b00001000
|
147 | ;out ddrb,temp
|
148 | sbi ddrb, 3
|
149 | clr temp
|
150 | out OCR1AH, temp
|
151 | out OCR1AL, temp
|
152 | ldi temp, 0x81
|
153 | out TCCR1A, temp
|
154 | ldi temp, 0x01
|
155 | out TCCR1B, temp
|
156 | ldi temp, 0x13
|
157 | out ACSR, temp
|
158 | pop temp
|
159 | ret
|
160 | ;
|
161 | adc_on1:
|
162 | wdr
|
163 | push temp1
|
164 | push temp2
|
165 | clr temp1
|
166 | out OCR1AH, temp1
|
167 | out OCR1AL, temp1
|
168 | cbi portb, 0
|
169 | sbi ddrb, 0
|
170 | clr temp
|
171 | rjmp pause_
|
172 | ;
|
173 | pause_:
|
174 | wdr
|
175 | nop
|
176 | dec temp
|
177 | brne pause_
|
178 | cbi ddrb, 0
|
179 | ldi temp, 0x00
|
180 | rjmp adc_on2
|
181 | ;
|
182 | adc_on2:
|
183 | wdr
|
184 | in temp2, TIFR
|
185 | sbrs temp2, 7
|
186 | rjmp adc_on2
|
187 | ori temp2, 0x80
|
188 | out TIFR, temp2
|
189 | out OCR1AH, temp1
|
190 | out OCR1AL, temp
|
191 | sbic ACSR, ACO
|
192 | rjmp adc_on3
|
193 | cpi temp, 0xFF
|
194 | breq adc_on3
|
195 | inc temp
|
196 | rjmp adc_on2
|
197 | ;
|
198 | adc_on3:
|
199 | wdr
|
200 | out OCR1AH, temp1
|
201 | out OCR1AL, temp1
|
202 | pop temp2
|
203 | pop temp1
|
204 | ret
|
205 | ;
|
206 | ;**LCD-Initialisierung - LCD - Ausgabe-Routinen**
|
207 | lcdinit:
|
208 | rcall wait1 ; LCD Power On Self Reset abwarten
|
209 | push temp ; Sicherung Temporaer- und
|
210 | push temp1 ; Statusregister auf Stapel
|
211 | in temp1,SREG
|
212 | push temp1
|
213 | rcall lcd_reset ; LCD-Bus-Reset
|
214 | rcall lcd_achtbit ; LCD-Init: acht Bit
|
215 | rcall lcd_acht_vier ; LCD-Init: acht zu vier Bit
|
216 | rcall lcd_vier_zwei ; LCD-Init: vier Bit, zwei Zeilen
|
217 | rcall lcd_on_off ; LCD-Init: Displaypuffer aus
|
218 | rcall lcd_clear ; LCD-Init: Anzeige löschen
|
219 | rcall lcd_entrymode ; LCD-Init: Entry Mode Set
|
220 | pop temp1 ; Wiederherstellung Temporaer-
|
221 | out SREG,temp1 ; und Statusregister
|
222 | pop temp1
|
223 | pop temp
|
224 | ret
|
225 | ;
|
226 | lcd_reset: ; LCD-Bus Reset
|
227 | push temp ; Temporaerregister auf Stack retten
|
228 | cbi daten, rs ; RS=0
|
229 | ldi temp,0x00 ; Reset des LCD-Ausgabeports
|
230 | out daten,temp
|
231 | rcall enable ; Enable-Impuls toggeln
|
232 | rcall wait3
|
233 | pop temp ; Temporaerregister wiederherstellen
|
234 | ret
|
235 | ;
|
236 | lcd_achtbit: ; Acht-Bit-Init
|
237 | push temp ; an folgende Portbelegung angepasst:
|
238 | ; ; PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
|
239 | ; ; n/a LED ena rs D7 D6 D5 D4
|
240 | ldi temp,0x03 ; dreimal hex 0x03
|
241 | cbi daten, rs ; RS=0
|
242 | out daten,temp ; immer notwendig, wenn
|
243 | rcall enable ; einmal 8/4-Bit-Modus
|
244 | rcall wait3 ; gewechselt wurde, dabei
|
245 | ldi temp, 0x03 ; jedesmal
|
246 | cbi daten, rs ; RS=0
|
247 | out daten,temp ; auf Port ausgeben
|
248 | rcall enable ; Enable-Impuls senden, dann
|
249 | rcall wait3 ; Pausen folgen lassen
|
250 | ldi temp, 0x03
|
251 | cbi daten, rs
|
252 | out daten,temp
|
253 | rcall enable
|
254 | rcall wait3
|
255 | pop temp
|
256 | ret
|
257 | ;
|
258 | lcd_acht_vier: ; Acht-zu-Vier-Bit-Modus-Wechsel
|
259 | push temp
|
260 | cbi daten, rs ; RS=0
|
261 | ldi temp,0x02 ; zunaechst nur 4-Bit-Modus
|
262 | out daten,temp ; obere vier Bit werden
|
263 | rcall enable ; ignoriert, aber immer noch
|
264 | rcall wait3 ; 8-Bit-Befehlsbreite
|
265 | pop temp
|
266 | ret
|
267 | ;
|
268 | lcd_vier_zwei: ; Vier-Bit_modus, zwei Zeilen
|
269 | push temp
|
270 | cbi daten,rs ; RS=0
|
271 | ldi temp,0x28 ; dann Vier-Bit-Modus, zweizeilig
|
272 | rcall comd2lcd ; ab hier werden Steuerbefehle
|
273 | rcall wait3 ; auch im Vier-Bit-Modus ueber
|
274 | pop temp ; Unterprogramm "comd2lcd" gesendet
|
275 | ret
|
276 | ;
|
277 | lcd_on_off: ; On-off-Control
|
278 | push temp ; Displaypuffer ein-, ausschalten
|
279 | cbi daten, rs ; RS=0
|
280 | ldi temp, 0x08 ; Displaypuffer aus, Blinken aus,
|
281 | rcall comd2lcd ; kein Cursor
|
282 | rcall wait3
|
283 | pop temp
|
284 | ret
|
285 | ;
|
286 | lcd_clear: ; Anzeige loeschen
|
287 | push temp
|
288 | cbi daten, rs ; RS=0
|
289 | ldi temp,0x01 ; Anzeige wird im Space-Modus
|
290 | rcall comd2lcd ; geloescht, dauert laenger...
|
291 | rcall wait3 ; ... Pause laenger
|
292 | rcall wait3
|
293 | pop temp
|
294 | ret
|
295 | ;
|
296 | lcd_entrymode: ; Entry/Shift Mode Set
|
297 | push temp
|
298 | cbi daten, rs ; RS=0
|
299 | ldi temp,0x06 ; Cursor von rechts nach links
|
300 | rcall comd2lcd ; kein Schieben
|
301 | rcall wait3
|
302 | cbi daten, rs ; RS=0
|
303 | ldi temp,0x10 ; kein Schieben, Cursorbewegung
|
304 | rcall comd2lcd ; nach rechts
|
305 | rcall wait3
|
306 | cbi daten, rs ; RS=0
|
307 | ldi temp,0x0C ; Anzeige wieder einschalten
|
308 | rcall comd2lcd ; Cursor aus, Blinken aus
|
309 | rcall wait3
|
310 | cbi daten, rs ; RS=0
|
311 | ldi temp,0x01 ; Anzeige nochmals loeschen
|
312 | rcall comd2lcd
|
313 | rcall wait3
|
314 | pop temp
|
315 | ret
|
316 | ;
|
317 | char2lcd: ; gibt Charakter auf "temp" ueber LCD aus
|
318 | cbi daten,licht ; LCD-Hintergrundbeleuchtung aus
|
319 | push temp ; rettet temps auf Stapel
|
320 | push temp1
|
321 | mov temp, temp1
|
322 | mov temp1, temp ; Kopie fuer Nachfolge-Operation
|
323 | andi temp, 0xF0 ; unteres Daten-Nibble ausblenden
|
324 | swap temp ; an Portbelegung anpassen...
|
325 | andi temp, 0x0F ; oberes Portbit-Nibble ausblenden
|
326 | ori temp, 0b00010000 ; RS=high
|
327 | out daten,temp ; Ausgabe D4-D7-Daten-Nibble auf Port D0-D3
|
328 | rcall enable ; Enableimpuls
|
329 | andi temp1, 0x0F ; oberes Portbit-Nibble ausblenden
|
330 | ori temp1, 0b00010000 ; RS=high
|
331 | out daten,temp1 ; Ausgabe D0-D3-Daten-Nibble auf D0-D3
|
332 | rcall enable ; Enableimpuls
|
333 | sbi daten,licht ; Hintergrundbeleuchtung ein
|
334 | pop temp1 ; Zurueckholen von temps
|
335 | pop temp
|
336 | rcall wait2 ; Verarbeitungszeit LCD abwarten
|
337 | ret
|
338 | ;
|
339 | comd2lcd: ; sendet Steuerzeichen auf "temp" an LCD
|
340 | push temp ; rettet "temps" auf Stapel
|
341 | push temp1
|
342 | mov temp1,temp ; Kopie fuer Nachfolge-Operation
|
343 | andi temp, 0xF0 ; unteres Daten-Nibble ausblenden
|
344 | swap temp ; an Portbelegung anpassen...
|
345 | andi temp, 0x0F ; oberes Portbit-Nibble ausblenden; RS=0
|
346 | out daten,temp ; Ausgabe D4-D7-Daten-Nibble auf Port D0-D3
|
347 | rcall enable ; Enableimpuls
|
348 | andi temp1, 0x0F ; oberes Portbit-Nibble ausblenden; RS=0
|
349 | out daten,temp1 ; Ausgabe D0-D3-Daten-Nibble auf D0-D3
|
350 | rcall enable ; Enableimpuls senden
|
351 | pop temp1 ; Zurueckholen von temps
|
352 | pop temp
|
353 | rcall wait2 ; Verarbeitungszeit LCD abwarten
|
354 | ret
|
355 | ;
|
356 | enable: ; Enableimpuls-Generierung
|
357 | nop
|
358 | sbi daten, ena ; Portbit "Enable" auf high
|
359 | nop ; Zeitverzoegerung mindestens
|
360 | nop ; 1000 ns laut Datenblatt LCD
|
361 | nop
|
362 | nop
|
363 | nop
|
364 | nop
|
365 | cbi daten, ena ; Portbit "Enable" auf low zuruecksetzen
|
366 | nop
|
367 | ret
|
368 | ;
|
369 | bin2dec: ; Umwandlung "temp1" 8 bit binaer auf
|
370 | wdr ; ASCII dezimal, 3 Stellen mit fuehrenden
|
371 | push temp ; Nullen
|
372 | push temp1
|
373 | push temp2
|
374 | mov temp2, temp1 ; Anzahl Hunderter abzaehlen
|
375 | ldi temp1, 0x30 ; ASCII "Ziffer Null" vorladen
|
376 | rjmp num_1
|
377 | ;
|
378 | num_1:
|
379 | subi temp2, 100 ; zieht Wert 100 von temp2 ab
|
380 | brcs num_2 ; springt zur Ausgabe, wenn negativer
|
381 | inc temp1 ; Uebertrag entstanden
|
382 | rjmp num_1 ; Ausgabe Anzahl Schleifendurchlaeufe
|
383 | ;
|
384 | num_2:
|
385 | rcall char2lcd
|
386 | subi temp2, -100; zaehlt 100 wieder dazu, da die
|
387 | ldi temp1, 0x30 ; Schleife davor 100 zuviel abzog
|
388 | ; ; Anzahl Zehner abzaehlen
|
389 | num_3:
|
390 | subi temp2, 10 ; zieht Wert 10 ab
|
391 | brcs num_4 ; springt zur Ausgabe, wenn negativer
|
392 | inc temp1 ; Uebertrag entstanden
|
393 | rjmp num_3 ; Ausgabe Anzahl Schleifendurchlaeufe
|
394 | ;
|
395 | num_4:
|
396 | rcall char2lcd
|
397 | subi temp2, -10 ; zaehlt 10 wieder dazu, da die
|
398 | ; ; Schleife davor 10 zuviel abzog
|
399 | ldi temp1, 0x30 ; addiert ASCII-Code zu Einer hinzu
|
400 | add temp1, temp2
|
401 | rcall char2lcd ; Ausgabe Einer
|
402 | pop temp2
|
403 | pop temp1
|
404 | pop temp
|
405 | ret
|
406 | ;
|
407 | wait1: ; Verzoegerungsschleifen fuer LCD
|
408 | rcall wait3
|
409 | rcall wait3
|
410 | rcall wait3
|
411 | ret
|
412 | ;
|
413 | wait2: ;Verzoegerungsschleife 2
|
414 | push xl
|
415 | push xh
|
416 | push temp ;Register sichern auf Stapel
|
417 | push temp1 ;Sicherung von Temporaerregistern
|
418 | in temp1, SREG ;und Statusregister auf Stapel
|
419 | push temp1 ;bei Interrupts notwendig
|
420 | ldi xl, low(zeit0) ;laedt Zaehlregisterpaar mit
|
421 | ldi xh, high(zeit0) ;oben deklariertem Wert "Zeit0"
|
422 | rjmp repeatx
|
423 | ;
|
424 | wait3: ;Verzoegerungsschleife 3
|
425 | push xl
|
426 | push xh
|
427 | push temp ;Register sichern auf Stapel
|
428 | push temp1 ;Sicherung von Temporaerregistern
|
429 | in temp1, SREG ;und Statusregister auf Stapel
|
430 | push temp1 ;bei Interrupts notwendig
|
431 | ldi xl, low(zeit1) ;laedt Zaehlregisterpaar mit
|
432 | ldi xh, high(zeit1) ;oben deklariertem Wert "Zeit1"
|
433 | rjmp repeatx
|
434 | ;
|
435 | repeatx: ;16-Bit-Subtraktionsschleife:
|
436 | sbiw xl:xh, 1 ;decrementiert Doppelregister
|
437 | brne repeatx ;zaehlt bis Null
|
438 | pop temp1 ;Wiederherstellung von
|
439 | out SREG, temp1 ;geretteten"Registern
|
440 | pop temp1
|
441 | pop temp
|
442 | pop xh
|
443 | pop xl
|
444 | ret
|
445 | ;
|