adc_jeudi.asm


1
.include "m8def.inc"       ;Definitionsdatei einbinden
2
3
; single ADC
4
.def  temp  =R18      ;temporary storage register 
5
.def  Txbyte  =R19      ;Data to be transmitted 
6
.def  Rxbyte  =R20      ;Received data 
7
.DEF rmp = R21 ; als Vielzweckregister verwendet für Umwandlung
8
.def temp1 = r25
9
.def temp2 = r26
10
.def temp3 = r22
11
.def temp4 = r23
12
.def rxbyte = r24
13
14
15
16
17
                           
18
.org 0x0000
19
20
  ldi r16, low(RAMEND)
21
  out SPL, r16
22
  ldi r16, high(RAMEND)
23
  out SPH, r16
24
25
  ldi r16, 0b00000011  ; 110.. = Internal Ref 2.56V  letzen 3 stellen für analog eingang
26
  out ADMUX, r16    ; 010.. = AVCC , ca 5.07V
27
  ldi r16, 0b10001111
28
  out ADCSR, r16
29
30
    ldi temp1, 0xFF    ;Port D = Ausgang
31
    out DDRD, temp1
32
33
    rcall lcd_init     ;Display initialisieren
34
    rcall lcd_clear    ;Display l?schen
35
36
37
loop:
38
  rcall delay
39
  rcall delay
40
  rcall delay
41
  rcall delay
42
        
43
    sbi ADCSR,ADSC
44
    rcall delay
45
  rcall delay
46
  rcall delay
47
  rcall delay
48
        
49
         
50
loop2:  
51
  sbis ADCSR,ADIF
52
  rjmp loop2
53
 
54
  in r16, ADCL
55
  in r17, ADCH
56
57
  com r16      ;für Convertierung Invert aus 5V->0V 0V->5V
58
  mov temp1, r16
59
  rcall  lcd_data
60
61
62
  com r17
63
  mov temp1, r17
64
  rcall  lcd_data
65
66
67
  andi r17,$03
68
  mov rmp,r17 ; Wandle um ADC-Wert um
69
  mov R2,rmp
70
  mov rmp,r16
71
  mov R1,rmp
72
  rcall fpconv10 ; Rufe die Umwandlungsroutine
73
74
start:
75
    ldi     temp1,0x80   ; Set DDRAM Adress to 0x40
76
      rcall   lcd_command
77
    
78
  ldi ZL, LOW(text*2)     ; Adresse des Strings in den
79
  ldi ZH, HIGH(text*2)         ; Z-Pointer laden
80
  rcall print
81
82
83
84
85
  ldi temp1, 0x85
86
  rcall  lcd_command
87
88
  mov temp1, r5  ; ASCII-Ergebnis steht in R5-R10
89
  rcall  lcd_data
90
  mov temp1, r6
91
  rcall  lcd_data
92
  mov temp1, r7
93
  rcall  lcd_data
94
  mov temp1, r8
95
  rcall  lcd_data
96
  mov temp1, r9
97
  rcall  lcd_data
98
  mov temp1, r10
99
  rcall  lcd_data
100
  
101
  
102
  rcall lcd_Cursor_home
103
  rjmp loop
104
105
    rjmp  start
106
    ret  
107
108
109
print:
110
        lpm r16,z+          ; Erstes Byte des Strings nach R0 lesen
111
        tst R16                    ; R0 auf 0 testen
112
        breq print_end             ; wenn 0, dann zu print_end
113
        rcall lcd_data             ; LCD-Sendefunktion aufrufen
114
        rjmp print               ; wieder zum Anfang springen
115
print_end:
116
        ret
117
118
119
delay:
120
  push r16
121
  push r17
122
  in r16,SREG
123
  push r16
124
  ldi  r16, $FF;$84    ; 132 - 1,604,1,1=607  =  +1=80125Takte
125
126
dloop0:  ldi  r17, $FF;$C9    ; 201 - 1,1,1 = 603+1=604
127
128
dloop1: dec  r17
129
        brne dloop1    ; 0.02003 sec , ca 20 msec
130
        dec  r16
131
        brne dloop0
132
        pop r16
133
        out SREG,r16
134
        pop r17
135
        pop r16
136
    ret
137
138
;UMWANDLUNGSROUTINE
139
140
fpconv10:
141
    rcall fpconv10m ; Multipliziere mit 320.313
142
  rcall fpconv10r ; Runden und Division mit 65536
143
  rcall fpconv10a ; Umwandlung in ASCII-String
144
  rjmp fpconv10f ; Setze Dezimalpunkt und Nullabschluss
145
146
fpconv10f:
147
  ldi rmp,'.' ; Setze Dezimalpunkt
148
  mov R6,rmp
149
  ldi rmp, 86 ;V
150
  mov R10,rmp
151
  ret ; Alles fertig
152
; Startbedingung:
153
; +---+---+
154
; | R2+ R1|  Eingabezahl
155
; +---+---+
156
; +---+---+---+---+
157
; | R6| R5| R4| R3| Multiplikant 320.313 = $00 04 E3 38 (00 02 80 A0) bei 2,56V
158
; | 00| 04| E3| 38| 328.000 (05 01 40) bei 5.12V
159
; +---+---+---+---+
160
; +---+---+---+---+
161
; |R10| R9| R8| R7| Resultat
162
; | 00| 00| 00| 00|
163
; +---+---+---+---+
164
;
165
fpconv10m:
166
  clr R6 ; Setze den Multiplikant auf 320.313
167
  ldi rmp,$04
168
  mov R5,rmp
169
  ldi rmp,$E3
170
  mov R4,rmp
171
  ldi rmp,$38
172
  mov R3,rmp
173
  clr R10 ; leere Ergebnisregister
174
  clr R9
175
  clr R8
176
  clr R7
177
fpconv10m1:
178
  mov rmp,R1 ; Prüfe ob noch Bits zu multiplizieren
179
  or rmp,R2 ; Irgendein Bit Eins?
180
  brne fpconv10m2 ; Noch Einsen, mach weiter
181
  ret ; fertig, kehre zurück
182
fpconv10m2:
183
  lsr R2 ; Schiebe MSB nach rechts (teilen durch 2)
184
  ror R1 ; Rotiere LSB rechts und setze Bit 7
185
  brcc fpconv10m3 ; Wenn das niedrigste Bit eine 0 war,
186
;    dann überspringe den Additionsschritt
187
    add R7,R3 ; Addiere die Zahl in R6:R5:R4:R3 zum Ergebnis
188
  adc R8,R4
189
  adc R9,R5
190
  adc R10,R6
191
fpconv10m3:
192
  lsl R3 ; Multipliziere R6:R5:R4:R3 mit 2
193
  rol R4
194
  rol R5
195
  rol R6
196
  rjmp fpconv10m1 ; Wiederhole für das n?chste Bit
197
;
198
; Runde die Zahl in R10:R9 mit dem Wert von Bit 7 von R8
199
;
200
fpconv10r:
201
  clr rmp ; Null nach rmp
202
  lsl R8 ; Rotiere Bit 7 ins Carry
203
  adc R9,rmp ; Addiere LSB mit ?bertrag
204
  adc R10,rmp ; Addiere MSB mit ?bertrag
205
  mov R2,R10 ; Kopiere den Wert nach R2:R1 (durch 65536 teilen)
206
  mov R1,R9
207
  ret
208
;
209
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8:R9:R10
210
;
211
; +---+---+
212
; + R2| R1| Eingangswert 0..5.000
213
; +---+---+
214
; +---+---+
215
; | R4| R3| Dezimalteiler
216
; +---+---+
217
; +---+---+---+---+---+---+
218
; | R5| R6| R7| R8| R9|R10| Ergebnistext (für Einmgangswert 5,000)
219
; |'5'|'.'|'0'|'0'|'0'|$00| mit Null-Abschluss
220
; +---+---+---+---+---+---+
221
;
222
fpconv10a:
223
  ldi rmp,HIGH(1000) ; Setze Dezimalteiler auf 1.000
224
  mov R4,rmp
225
  ldi rmp,LOW(1000)
226
  mov R3,rmp
227
  rcall fpconv10d ; Hole ASCII-Ziffer durch wiederholtes Abziehen
228
  mov R5,rmp ; Setze Tausender Zeichen
229
  clr R4 ; Setze Dezimalteiler auf 100
230
  ldi rmp,100
231
  mov R3,rmp
232
  rcall fpconv10d ; Hole die n?chste Ziffer
233
  mov R7,rmp ; Setze Hunderter Zeichen
234
  ldi rmp,10 ; Setze Dezimalteiler auf 10
235
  mov R3,rmp
236
  rcall fpconv10d ; Hole die n?chste Ziffer
237
  mov R8,rmp ; Setze Zehner Zeichen
238
  ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
239
  add rmp,R1
240
  mov R9,rmp ; Setze Einer Zeichen
241
  ret
242
;
243
; Wandle Bin?rwort in R2:R1 in eine Dezimalziffer durch fortgesetztes
244
; Abziehen des Dezimalteilers in R4:R3 (1000, 100, 10)
245
;
246
fpconv10d:
247
  ldi rmp,'0' ; Beginne mit ASCII-0
248
fpconv10d1:
249
  cp R1,R3 ; Vergleiche Wort mit Teiler
250
  cpc R2,R4
251
  brcc fpconv10d2 ; Carry nicht gesetzt, subtrahiere Teiler
252
  ret ; fertig
253
fpconv10d2:
254
  sub R1,R3 ; Subtrahiere Teilerwert
255
  sbc R2,R4
256
  inc rmp ; Ziffer um eins erh?hen
257
  rjmp fpconv10d1 ; und noch einmal von vorne
258
259
260
; Ende der Flie?komma-Umwandlungsroutinen
261
;
262
;
263
; Ende des Umwandlungstestprogramms
264
;
265
;.include "lcd-routines.asm"            ;LCD-Routinen werden hier eingefügt
266
267
268
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
269
;;                 LCD-Routinen                ;;
270
;;                 ============                ;;
271
;;                                             ;;
272
;;                                             ;;
273
;; 4bit-Interface                              ;;
274
;; DB4-DB7:       PD0-PD3                      ;;
275
;; RS:            PD4                          ;;
276
;; E:             PD5                          ;;
277
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
278
279
;.include "lcd-routines.asm"            ;LCD-Routinen werden hier eingefügt
280
 
281
 ;sendet ein Datenbyte an das LCD
282
lcd_data:
283
           mov temp2, temp1             ;"Sicherungskopie" für
284
                                        ;die Übertragung des 2.Nibbles
285
           swap temp1                   ;Vertauschen
286
           andi temp1, 0b00001111       ;oberes Nibble auf Null setzen
287
           sbr temp1, 1<<4              ;entspricht 0b00010000
288
           out PORTD, temp1             ;ausgeben
289
           rcall lcd_enable             ;Enable-Routine aufrufen
290
                                        ;2. Nibble, kein swap da es schon
291
                                        ;an der richtigen stelle ist
292
           andi temp2, 0b00001111       ;obere Hälfte auf Null setzen 
293
           sbr temp2, 1<<4              ;entspricht 0b00010000
294
           out PORTD, temp2             ;ausgeben
295
           rcall lcd_enable             ;Enable-Routine aufrufen
296
           rcall delay50us              ;Delay-Routine aufrufen
297
           ret                          ;zurück zum Hauptprogramm
298
299
 ;sendet einen Befehl an das LCD
300
lcd_command:                            ;wie lcd_data, nur ohne RS zu setzen
301
           mov temp2, temp1
302
           swap temp1
303
           andi temp1, 0b00001111
304
           out PORTD, temp1
305
           rcall lcd_enable
306
           andi temp2, 0b00001111
307
           out PORTD, temp2
308
           rcall lcd_enable
309
           rcall delay50us
310
           ret
311
312
 ;erzeugt den Enable-Puls
313
lcd_enable:
314
           sbi PORTD, 5                 ;Enable high
315
           nop                          ;3 Taktzyklen warten
316
           nop
317
           nop
318
           cbi PORTD, 5                 ;Enable wieder low
319
           ret                          ;Und wieder zurück                     
320
321
 ;Pause nach jeder Übertragung
322
delay50us:                              ;50us Pause
323
           ldi  temp1, $42
324
delay50us_:dec  temp1
325
           brne delay50us_
326
           ret                          ;wieder zurück
327
328
 ;Längere Pause für manche Befehle
329
delay5ms:                               ;5ms Pause
330
           ldi  temp1, $21
331
WGLOOP0:   ldi  temp2, $C9
332
WGLOOP1:   dec  temp2
333
           brne WGLOOP1
334
           dec  temp1
335
           brne WGLOOP0
336
           ret                          ;wieder zurück
337
338
 ;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
339
lcd_init:
340
           ldi  temp3,50
341
powerupwait:
342
           rcall  delay5ms
343
           dec  temp3
344
           brne powerupwait
345
           ldi temp1, 0b00000011        ;muss 3mal hintereinander gesendet
346
           out PORTD, temp1             ;werden zur Initialisierung
347
           rcall lcd_enable             ;1
348
           rcall delay5ms
349
           rcall lcd_enable             ;2
350
           rcall delay5ms
351
           rcall lcd_enable             ;und 3!
352
           rcall delay5ms
353
           ldi temp1, 0b00000010        ;4bit-Modus einstellen
354
           out PORTD, temp1
355
           rcall lcd_enable
356
           rcall delay5ms
357
       ldi temp1, 0b00000100
358
       rcall lcd_command
359
           ldi temp1, 0b00101000        ;noch was einstellen...
360
           rcall lcd_command
361
           ldi temp1, 0b00001100        ;...nochwas...
362
           rcall lcd_command
363
           ldi temp1, 0b00000100        ;endlich fertig
364
       rcall lcd_command
365
           ret
366
367
 ;Sendet den Befehl zur Löschung des Displays
368
lcd_clear:
369
           ldi temp1, 0b00000001   ;Display löschen
370
           rcall lcd_command
371
           rcall delay5ms
372
           ret
373
374
lcd_Cursor_home:
375
          ldi temp1, 0b00000010   ;Cursor Home                      
376
      rjmp lcd_command
377
          ret
378
379
text:
380
.db "Uss= ",0    ; Stringkonstante, durch eine 0 abgeschlossen