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