include "m8def.inc" .def z0 = r1 ; Zahl für Integer -> ASCII Umwandlung .def z1 = r2 .def z2 = r3 .def z3 = r4 .def temp1 = r16 ; allgemeines Register, zur kurzfristigen Verwendung .def temp2 = r17 ; Register für 24 Bit Addition, niederwertigstes Byte (LSB) .def temp3 = r18 ; Register für 24 Bit Addition, mittlerers Byte .def temp4 = r19 ; Register für 24 Bit Addition, höchstwertigstes Byte (MSB) .def adlow = r20 ; Ergebnis vom ADC-Mittelwert der 256 Messungen .def adhigh = r21 ; Ergebnis vom ADC-Mittelwert der 256 Messungen .def messungen = r22 ; Schleifenzähler für die Messungen .def zeichen = r23 ; Zeichen zur Ausgabe auf den UART .def temp5 = r24 .def temp6 = r25 ; Faktor für Umrechung des ADC-Wertes in Spannung ; = (Referenzspannung / 1024 ) * 1000000 ; = 5V / 1024 * 1.000.000 = 4883 .equ Faktor = 1912 ; RAM .dseg .org 0x60 Puffer: .byte 10 ; hier geht das Programm los .cseg .org 0 ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren out SPL, temp1 ldi temp1, HIGH(RAMEND) out SPH, temp1 ;LCD Initalisierung rcall lcd_init rcall lcd_clear rcall lcd_home rcall delay5ms ; ADC initialisieren: Single Conversion, Vorteiler 128 ; Kanal 0, interne Referenzspannung AVCC ldi temp1, 0b00000000 out ADMUX, temp1 ldi temp1, (1< nächsten Wert einlesen ; Aus den 256 Werten den Mittelwert berechnen ; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte ; (im Register temp2) fällt einfach weg ; ; allerdings wird der Wert noch gerundet cpi temp2,128 ; "Kommastelle" kleiner als 128 ? brlo nicht_runden ; ist kleiner ==> Sprung ; Aufrunden subi temp3, low(-1) ; addieren von 1 sbci temp4, high(-1) ; addieren des Carry nicht_runden: ; Ergebnis nach adlow und adhigh kopieren ; damit die temp Register frei werden mov adlow, temp3 mov adhigh, temp4 ; in Spannung umrechnen ldi temp5,low(Faktor) ldi temp6,high(Faktor) rcall mul_16x16 ; in ASCII umwandeln ldi XL, low(Puffer) ldi XH, high(Puffer) rcall Int_to_ASCII ;an LCD Senden ldi ZL, low(Puffer+3) ldi ZH, high(Puffer+3) ldi temp1, 4 rcall lcd_ziffer ; eine Vorkommastelle ausgeben push zeichen ldi zeichen, ',' ; Komma ausgeben rcall lcd_data pop zeichen ldi temp1, 2 ; Drei Nachkommastellen ausgeben rcall lcd_ziffer push zeichen ldi zeichen, 'm' ; Milli Zeichen ausgeben rcall lcd_data pop zeichen push zeichen ldi zeichen, 'V' ; Volt Zeichen ausgeben rcall lcd_data pop zeichen rjmp Hauptschleife ; Ende des Hauptprogramms ; Unterprogramme ; 32 Bit Zahl in ASCII umwandeln ; Zahl liegt in temp1..4 ; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird ; Adressierung über X Pointer ; mehrfache Subtraktion wird als Ersatz für eine Division durchgeführt. Int_to_ASCII: ldi temp5, -1 + '0' _a1ser: inc temp5 subi temp1,BYTE1(1000000000) ; - 1.000.000.000 sbci temp2,BYTE2(1000000000) sbci temp3,BYTE3(1000000000) sbci temp4,BYTE4(1000000000) brcc _a1ser st X+,temp5 ; im Puffer speichern ldi temp5, 10 + '0' _a2ser: dec temp5 subi temp1,BYTE1(-100000000) ; + 100.000.000 sbci temp2,BYTE2(-100000000) sbci temp3,BYTE3(-100000000) sbci temp4,BYTE4(-100000000) brcs _a2ser st X+,temp5 ; im Puffer speichern ldi temp5, -1 + '0' _a3ser: inc temp5 subi temp1,low(10000000) ; - 10.000.000 sbci temp2,high(10000000) sbci temp3,BYTE3(10000000) brcc _a3ser st X+,temp5 ; im Puffer speichern ldi temp5, 10 + '0' _a4ser: dec temp5 subi temp1,low(-1000000) ; + 1.000.000 sbci temp2,high(-1000000) sbci temp3,BYTE3(-1000000) brcs _a4ser st X+,temp5 ; im Puffer speichern ldi temp5, -1 + '0' _a5ser: inc temp5 subi temp1,low(100000) ; -100.000 sbci temp2,high(100000) sbci temp3,BYTE3(100000) brcc _a5ser st X+,temp5 ; im Puffer speichern ldi temp5, 10 + '0' _a6ser: dec temp5 subi temp1,low(-10000) ; +10,000 sbci temp2,high(-10000) sbci temp3,BYTE3(-10000) brcs _a6ser st X+,temp5 ; im Puffer speichern ldi temp5, -1 + '0' _a7ser: inc temp5 subi temp1,low(1000) ; -1000 sbci temp2,high(1000) brcc _a7ser st X+,temp5 ; im Puffer speichern ldi temp5, 10 + '0' _a8ser: dec temp5 subi temp1,low(-100) ; +100 sbci temp2,high(-100) brcs _a8ser st X+,temp5 ; im Puffer speichern ldi temp5, -1 + '0' _a9ser: inc temp5 subi temp1, 10 ; -10 brcc _a9ser st X+,temp5 ; im Puffer speichern ldi temp5, 10 + '0' _a10ser: dec temp5 subi temp1, -1 ; +1 brcs _a10ser st X+,temp5 ; im Puffer speichern ret ; 16 Bit Wert in Spannung umrechnen ; ; = 16Bitx16Bit=32 Bit Multiplikation ; = vier 8x8 Bit Multiplikationen ; ; adlow/adhigh * temp5/temp6 mul_16x16: push zeichen clr temp1 ; 32 Bit Akku löschen clr temp2 clr temp3 clr temp4 clr zeichen ; Null, für Carry-Addition mul adlow, temp5 ; erste Multiplikation add temp1, r0 ; und akkumulieren adc temp2, r1 mul adhigh, temp5 ; zweite Multiplikation add temp2, r0 ; und gewichtet akkumlieren adc temp3, r1 mul adlow, temp6 ; dritte Multiplikation add temp2, r0 ; und gewichtet akkumlieren adc temp3, r1 adc temp4, zeichen ; carry addieren mul adhigh, temp6 ; vierte Multiplikation add temp3, r0 ; und gewichtet akkumlieren adc temp4, r1 pop zeichen ret .equ LCD_PORT = PORTD .equ PIN_E = 5 .equ LCD_DDR = DDRD .equ PIN_RS = 4 .equ XTAL = 1000000 ;sendet ein Datenbyte an das LCD lcd_data: push zeichen push temp2 mov temp2, zeichen ; "Sicherungskopie" für ; die Übertragung des 2.Nibbles swap zeichen ; Vertauschen andi zeichen, 0b00001111 ; oberes Nibble auf Null setzen sbr zeichen, 1<