Pfad: Home => AVR-overview => 8-bit-ADC with STK500 => adc8 software

Assembler source code for the conversion of an analogue voltage to an 8-bit-number


; +-----------------------------------------------------+
; | 8-Bit-Analog-Digital-Converter for ATMEL AT90S8515  |
; | on the STK500 board, Output by LEDs                 |
; | (C)2003 by http://www.avr-asm-tutorial.net          |
; | Used ports:                                         |
; |   Output PWM pulse = OC1A on Port D, Bit 5, via     |
; |      triple RC-filter to                            |
; |   Inverted analog input AIN1 on Port B Bit 3,       |
; |   Non-inverted analog input AIN0 on Port B Bit 2    |
; |      connected to voltage to be measured            |
; |   Output Port C connected to LEDs displays result   |
; +-----------------------------------------------------+
;
; Written for and tested with AT90S8515 on STK500
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU CycLen = 128 ; Number of PWM-cycles to filter before sensing
.EQU CycLen0 = 128 ; Number of PWM-cycles before first sensing
;
; Register
;
.DEF rRes = R1 ; final value of the ADC
.DEF rTmp = R14 ; Temporary value for ADC
.DEF rSrg = R15 ; Temporary register für SREG interim storage in ints
.DEF rmp  = R16 ; Universal register outside ints
.DEF rimp = R17 ; Universal register within ints
.DEF rFlg = R18 ; Flag register, Bit 0 = ADC ready
.DEF rBlc = R19 ; Bit-level-counter for ADC
.DEF rCcL = R24 ; Cycle counter for ADC, LSB
.DEF rCcH = R25 ; dto., MSB
;
; Reset- and Interrupt-vectors
;
	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 on each PWM-cycle end
;
Tc1Ovflw:
	in	rSrg,SREG ; Save SREG
	sbiw rCcL,1 ; decrement cycle counter word
	brne Tc1OvflwR ; if word<>0: int ready
	ldi rCcH,HIGH(CycLen) ; Set cycle counter for next bit
	ldi rCcL,LOW(CycLen)
	sbis ACSR,ACO ; check analogue comparator output
	eor rTmp,rBlc ; voltage too high, clear last bit
	lsr rBlc ; shift active bit one position right
	brcc Tc1OvflwA ; if carry<>0: not ready yet
	mov rRes,rTmp ; copy the result
	sbr rFlg,0x01 ; set ready-flag
	ldi rCcH,HIGH(CycLen0) ; set cycle counter for restart
	ldi rCcL,LOW(CycLen0)
	clr rTmp ; clear result
	ldi rBlc,0x80 ; set bit counter
Tc1OvflwA:
	or rTmp,rBlc ; set next bit to one
	clr rimp ; set TC1-PWM pulse width
	out OCR1AH,rimp ; high byte first!
	out OCR1AL,rTmp ; then low byte!
Tc1OvflwR: ; return from Int
	out SREG,rSrg ; restore SREG to original content
	reti ; set int flag, return
;
; Main program loop
;
main:
	ldi rmp,HIGH(RAMEND) ; define stack
	out SPH,rmp
	ldi rmp,LOW(RAMEND)
	out SPL,rmp
	ldi rCcH,HIGH(CycLen0) ; set cycle length before first measurement
	ldi rCcL,LOW(CycLen0)
	ldi rBlc,0x80 ; set bit counter to highest bit value
	mov rTmp,rBlc ; clear result
	ldi rmp,0xFF ; port C all bits output, drives LEDs
	out DDRC,rmp ; all data direction bits = 1
	sbi DDRD,PD5 ; PWM-output bit OC1A as output pin
    ldi rmp,0b00100000 ; define sleep-mode idle
	out MCUCR,rmp
    ldi rmp,0b10000001 ; TC1 as 8-bit-PWM, non-invertet
	out TCCR1A,rmp ; to TC1 control register A
	ldi rmp,0b00000001 ; TC1-clock = system clock
	out	TCCR1B,rmp ; to TC1 control register B
    clr rmp ; puls-width of PWM to $0080
	out OCR1AH,rmp ; first the HIGH byte!
	ldi rmp,0x80 ; then the LOW byte!
	out OCR1AL,rmp
	ldi rmp,0b10000000 ; TC1 overflow interrupt enable
	out TIMSK,rmp ; to Timer Int Mask Register
	sei ; enable CPU reaction to interrupts
;
; Main loop
;
main1:
	sleep ; CPU sleeps
	nop ; dummy instruction, loaded before sleep
	sbrs rFlg,0 ; check ready flag bit 0 if ADC is ready
	rjmp main1 ; not ready, sleep on
	cbr rFlg,0x01 ; clear ready bit 0
	mov rmp,rRes ; copy result of ADC
	com rmp ; invert all bits (LED active low)
	out PortC,rmp ; to LED port
	rjmp main1 ; done, go to sleep again
;
; End of program
;


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