Gast
#2240878
Hi, für eine Anwendung soll der µC drei Spannungen umwandeln und verarbeiten können. Als Test sollten diese nurmal auf ein LCD Display ausgegeben werden. Ich hab den Code aus dem AVR-Tutorial dieser Seite dafür umgeschrieben, allerdings funktioniert die Anwendung nicht, da die angezeigten Werte nicht stimmen, bzw. sich gegenseitig beeiflussen. Hier der Code: .include "m8def.inc" ; .def definiert ein Synonym (Namen) für ein µC Register .def temp1 = r16 ; allgemeines temp Register, zur kurzfristigen Verwendung .def temp2 = r17 .def adlow = r20 ; Ergebnis des ADC' .def adhigh = r21 ; Ergebnis des ADC' .def ztausend = r23 ; Zehntausenderstelle des ADC Wertes .def tausend = r24 ; Tausenderstelle des ADC Wertes .def hundert = r25 ; Hunderterstelle des ADC Wertes .def zehner = r26 ; Zehnerstelle des ADC Wertes .def temp5 = r28 ; LCD-Routines .def temp6 = r29 ; LCD-Routines .def temp7 = r30 ; LCD-Routines ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse out SPL, temp1 ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse out SPH, temp1 ldi temp1, 0xFF ; Port D = Ausgang out DDRD, temp1 rcall lcd_init ; Display initialisieren rcall lcd_clear ; Display löschen ; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128 ldi temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V out ADMUX, temp1 ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) out ADCSRA, temp1 Main: rcall lcd_clear rcall ADI_1 rcall ADW rcall ADI_2 rcall ADW rcall ADI_3 rcall ADW rjmp Main ADW: clr temp1 clr temp5 clr ztausend clr tausend clr hundert clr zehner clr adlow clr adhigh rcall sample_adc rcall wait_adc ; ADC einlesen: in adlow, ADCL ; immer zuerst LOW Byte lesen in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte ldi ztausend, '0'-1 ; Ziffernzähler direkt als ASCII Code ; bzgl. '0'-1 siehe Beitrag "Hilfe zu AVR-Tutorial ADC" rcall Z_ztausend rcall Z_tausend rcall Z_hundert rcall Z_zehner rcall Print ret delay: ; 5ms Pause (bei 4 MHz) ldi temp1, $21 WGLOOP0_: ldi temp2, $C9 WGLOOP1_: dec temp2 brne WGLOOP1_ dec temp1 brne WGLOOP0_ ret ; wieder zurück ADI_1: ldi temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V out ADMUX, temp1 ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) out ADCSRA, temp1 ret ADI_2: ldi temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V ldi temp1,2 out ADMUX, temp1 ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) out ADCSRA, temp1 ret ADI_3: ldi temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V ldi temp1,3 out ADMUX, temp1 ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) out ADCSRA, temp1 ret sample_adc: sbi ADCSRA, ADSC ; den ADC starten ret wait_adc: sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht rjmp wait_adc ret Z_ztausend: inc ztausend subi adlow, low(10000) ; -10,000 sbci adhigh, high(10000) ; 16 Bit brcc Z_ztausend subi adlow, low(-10000) ; nach Unterlauf wieder einmal addieren sbci adhigh, high(-10000); +10,000 ldi tausend, '0'-1 ; Ziffernzähler direkt als ASCII Code ret Z_tausend: inc tausend subi adlow, low(1000) ; -1,000 sbci adhigh, high(1000) ; 16 Bit brcc Z_tausend subi adlow, low(-1000) ; nach Unterlauf wieder einmal addieren sbci adhigh, high(-1000) ; +1,000 ldi hundert, '0'-1 ; Ziffernzähler direkt als ASCII Code ret Z_hundert: inc hundert subi adlow, low(100) ; -100 sbci adhigh, high(100) ; 16 Bit brcc Z_hundert subi adlow, low(-100) ; nach Unterlauf wieder einmal addieren sbci adhigh, high(-100) ; +100 ldi zehner, '0'-1 ; Ziffernzähler direkt als ASCII Code ret Z_zehner: inc zehner subi adlow, low(10) ; -10 sbci adhigh, high(10) ; 16 Bit brcc Z_zehner subi adlow, low(-10) ; nach Unterlauf wieder einmal addieren sbci adhigh, high(-10) ; +10 subi adlow, -'0' ; adlow enthält die Einer, Umwandlung in ASCII ret Print: mov temp5, ztausend ; Zeichen anzeigen rcall lcd_data mov temp5, tausend ; Zeichen anzeigen rcall lcd_data mov temp5, hundert ; Zeichen anzeigen rcall lcd_data mov temp5, zehner ; Zeichen anzeigen rcall lcd_data mov temp5, adlow ; Zeichen anzeigen rcall lcd_data ldi temp5, $0A rcall lcd_data rcall delay ret .include "lcd-routines.asm" ; LCD-Routinen werden hier eingefügt Lässt man bei Main, den Tail für die dritte und zweite Wandlung weg, klappt es. Wo liegt denn der Fehler, oder kann man mit dem Atmeg8 einfach keine drei ADC-Pins in einer Anwendung benutzen? Mfg Vaio