Допустим три канала измеряют напряжение от 0 до 2,5В, подключен от внешний ИОН на 2,5В
Мое понимание:
Мультиплексором переключать каждые 200 мс по прерыванию таймера входа?
И как усреднять по выборкам?
Буду благодарен любой помощи.
Код: Выделить всё
volatile uint8_t adc_result[8];
volatile uint8_t input = 0;
void ADC_init(void);
int main(void) {
DDRB = 0xFF;
ADC_init();
sei();
ADCSRA |= (1 << ADSC);
while (1) {
if (adc_result[0] > 150) {
PORTB = 0x01;
} else if (adc_result[0] < 150) {
PORTB = 0x00;
}
if (adc_result[1] > 150) {
PORTB = 0x02;
} else if (adc_result[1] < 150) {
PORTB = 0x00;
}
}
return 0;
}
ISR( ADC_vect ) {
adc_result[input] = ADCH;
if (input < 8)
input++;
else
input = 0;
ADMUX |= input;
ADCSRA |= ( 1 << ADSC );
}
void ADC_init() {
ADMUX |= (1 << ADLAR) | (1 << REFS0);
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2);
}
и усреднять это значение по 3 выборкам.
Код: Выделить всё
#include <mega88.h>
#include <delay.h>
#define ADC_VREF_TYPE 0xC0
volatile unsigned int A_adc[9];
...
// ADC initialization
// ADC Clock frequency: 250,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: On
// ADC4: On, ADC5: On
DIDR0=0x07;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA1;
ADCSRB&=0xF8;
.6;.
main{...}
Код: Выделить всё
{
static unsigned char n_zam=8;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
A_adc[n_zam]=ADCW;
//next conversion
n_imp++;
if (n_imp>8) n_imp=0;
ADMUX=(n_imp%3) | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}
Код: Выделить всё
unsigned int read_3_adc(unsigned char adc_input)
{
if (adc_input<3)
{
adc_input*=3;
return ((A_adc[adc_input]+A_adc[adc_input+1]+A_adc[adc_input+2])/3);
}else{return 0;};
}
Этот код например можно подсунуть в ISR(TIMER0_OVF_Vect) ?этот код вызывать каждые 66мс (3 раза за 200мс)
он заполняет массив
Код: Выделить всё
ISR( TIMER0_OVF_vect )
{
// 66 us oveflow
TCNT0=BE;
}
Код: Выделить всё
ISR( TIMER0_OVF_vect )
{
// 66 us oveflow
TCNT0=BE;
static unsigned char n_zam=8;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
A_adc[n_zam]=ADCW;
//next conversion
n_imp++;
if (n_imp>8) n_imp=0;
ADMUX=(n_imp%3) | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}
// ADC interrupt service routine
ISR (ADC_vect)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(100);
ADCSRA|=(1<<ADSC); //ADCSRA|=0x40
}
Код: Выделить всё
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
ADC Auto Trigger Source: Timer0 Overflow
Код: Выделить всё
ISR (ADC_vect)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(100);
ADCSRA|=(1<<ADSC); //ADCSRA|=0x40
}