Pfad: Home => AVR-Übersicht => 8-Bit-ADC am STK500 => adc8 software

Assembler-Quelltext der Umwandlung einer Analogspannung in eine 8-Bit-Zahl


; +-----------------------------------------------------+
; | 8-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
;


©2003 by http://www.avr-asm-tutorial.net