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