📄 adc_driver.s
字号:
#define ENABLE_BIT_DEFINITIONS
#define __SFR_OFFSET 0 /* GCC 3.2 needs this for direct low I/O access */
#include <avrx-io.h>
#include <avrx-signal.h>
#include <avrx.inc>
/*
interrupt driven ADC conversion drivers.
Does continuous conversions of all 8 channels, starting with #7, then
decrementing to 0 and rolling over to 7 again.
53 cycles/interrupt. At 8mhz it is roughly 432/900*8 or ~6% load.
Uses a 1/64 clock. On an 8mhz machine each conversion takes roughly
100us for a total conversion time of ~.9ms or roughly 8% load.
*/
_MODULE(adc_driver)
_DATASECTION
_STATIC(adc_channel, 1) ; Internal: current channel number
_STATIC(adc, 16) ; Results
_CODESECTION
_FUNCTION(SIG_ADC)
SIG_ADC:
push R28
in R28, SREG
push R28
push R30
push R31
ldi R30, lo8(adc)
ldi R31, hi8(adc)
lds R28, adc_channel
add R28, R28
add R30, R28
sbci R31, lo8(-0) ; Add channel # to index
in R28, ADCL
std Z+0, R28 ; store ADC results little endien for C
in R28, ADCH
std Z+1, R28
lds R28, adc_channel
subi R28, 1 ; If < 0, then wrap to 7
brcc continue
ldi R28, lo8(7)
continue:
out ADMUX, R28
sts adc_channel, R28
sbi ADCSRA, ADSC ; Get next channel results
pop R31
pop R30
pop R28
out SREG, R28
pop R28
reti
_ENDFUNC
;
; void ADC_StartConversion(void)
;
; Initializes Channel to 7, then starts a conversion
; Enable the interrupt flag (never disabled afterwards)
;
_FUNCTION(ADC_Init)
ADC_Init:
ldi tmp0, (1<<ADEN) | (1<<ADSC) | (1<<ADPS1) | (1<<ADPS2)
out ADCSRA, tmp0
adc0:
sbic ADCSRA, ADSC ; Wait until dummy conversion done.
rjmp adc0
ldi tmp0, lo8(7)
sts adc_channel, tmp0
out ADMUX, tmp0
sbi ADCSRA, ADSC
sbi ADCSRA, ADIE
ret
_ENDFUNC
/*
unsigned short ADC_Channel(unsigned char)
Atomic read of a word from the ADC data array
*/
_FUNCTION(GetADC)
GetADC:
ldi R30, lo8(adc)
ldi R31, hi8(adc)
add p1l, p1l
add R30, p1l
sbci R31, -(0)
in tmp0, SREG
cli
ldd p1l, Z+0
ldd p1h, Z+1
out SREG, tmp0
ret
_ENDFUNC
_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -