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