; +-----------------------------------------------------+ ; | 8-Bit-Analog-Digital-Converter mit ATMEL AT90S8515 | ; | auf dem STK500 board, Ausgabe über LEDs | ; | (C)2003 by http://www.avr-asm-tutorial.net | ; | Verwendete Anschlüsse: Ausgang PWM-Rechteckspannung | ; | OC1A an Port D, Bit 5; über dreifach RC-Filter an| ; | invertierienden Analogeingang AIN1 entsprechend | ; | Port B Bit 3; Anschluss der zu messenden Analog- | ; | spannung an nichtinvertierenden Analogeingang | ; | Port B Bit 2; Ausgabe für die LEDs an Port C | ; +-----------------------------------------------------+ ; ; Geschrieben für und getestet mit AT90S8515 auf STK500 ; .NOLIST .INCLUDE "8515def.inc" .LIST ; ; Konstanten ; .EQU CycLen = 128 ; Anzahl PWM-Zyklen zum Einschwingen .EQU CycLen0 = 128 ; Anzahl PWM-Zyklen vor der ersten Messung ; ; Register ; .DEF rRes = R1 ; Endwert des ADC .DEF rTmp = R14 ; Temporärwert für ADC .DEF rSrg = R15 ; Temporärregister für SREG .DEF rmp = R16 ; Universalregister ohne Int .DEF rimp = R17 ; Universalregister bei Int .DEF rFlg = R18 ; Flagregister, Bit 0=ADC fertig .DEF rBlc = R19 ; Bitlevel-Counter für ADC .DEF rCcL = R24 ; Cycle Counter für ADC, LSB .DEF rCcH = R25 ; dto., LSB ; ; Reset- und Interrupt-Vektoren ; rjmp main ; Reset reti ; INT0 reti ; INT1 reti ; TC1-Capt reti ; TC1-CompA reti ; TC1-CompB rjmp Tc1Ovflw ; TC1-Ovflw reti ; TC0-Ovflw reti ; SPI STC reti ; UART RX reti ; UART UDRE reti ; UART TX reti ; Ana-Comp ; ; TC1-Overflow am PWM-Zyklusende ; Tc1Ovflw: in rSrg,SREG ; Sichern von SREG sbiw rCcL,1 ; Erniedrige Zykluszähler brne Tc1OvflwR ; bei <>0 fertig ldi rCcH,HIGH(CycLen) ; Setze Zyklenzähler ldi rCcL,LOW(CycLen) sbis ACSR,ACO ; prüfe Analogcomp-Ausgang eor rTmp,rBlc ; U zu hoch, lösche letztes Bit lsr rBlc ; Aktives Bit eins rechts brcc Tc1OvflwA ; noch nicht fertig mov rRes,rTmp ; Kopiere das Ergebnis sbr rFlg,0x01 ; Setze Fertig-Flag ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn ldi rCcL,LOW(CycLen0) clr rTmp ; Leeres Ergebnis ldi rBlc,0x80 ; Setze Bitzähler Tc1OvflwA: or rTmp,rBlc ; setze nächstes Bit clr rimp ; Setze TC1-PWM-Zyklus out OCR1AH,rimp out OCR1AL,rTmp Tc1OvflwR: ; Rückkehr vom Interupt out SREG,rSrg ; SREG wieder herstellen reti ; ; Hauptprogramm-Schleife ; main: ldi rmp,HIGH(RAMEND) ; Definiere Stack out SPH,rmp ldi rmp,LOW(RAMEND) out SPL,rmp ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn ldi rCcL,LOW(CycLen0) ldi rBlc,0x80 ; Setze Bitzähler mov rTmp,rBlc ; Leeres Ergebnis ldi rmp,0xFF ; Port C auf Output, treibt die LEDs out DDRC,rmp ; alle Datenrichtungsregister = 1 sbi DDRD,PD5 ; PWM-Ausgang OC1A auf Ausgang setzen ldi rmp,0b00100000 ; Sleep-mode idle einstellen out MCUCR,rmp ldi rmp,0b10000001 ; TC1 auf PWM8 non-invertiert out TCCR1A,rmp ; in TC1-Kontrollregister A ldi rmp,0b00000001 ; TC1-clock=System clock out TCCR1B,rmp ; in TC1-Kontrollregister B clr rmp ; Pulsweite Rechtecksignal einstellen out OCR1AH,rmp ; erst das HIGH Byte! ldi rmp,0x80 ; dann das LOW Byte! out OCR1AL,rmp ldi rmp,0b10000000 ; TC1 Overflow Int einschalten out TIMSK,rmp ; in Timer Int Mask Register sei ; Reaktion auf Interrupts durch CPU ermöglichen ; ; Hauptprogramm-Loop ; main1: sleep ; CPU schlafen legen nop sbrs rFlg,0 ; Ready flag Bit 0 abfragen rjmp main1 ; Nicht ready, schlaf weiter cbr rFlg,0x01 ; Setze Bit 0 zurück mov rmp,rRes ; Kopiere Ergebnis in Universalregister com rmp ; Invertiere alle bits (Lampe invers!) out PortC,rmp ; an LED Port ausgeben rjmp main1 ; fertig, schlafen legen ; ; Ende des Programms ;