Ацп работает в режиме автоматического перезапуска с частотой 12 кГц и тактовая частотой АЦП 156 кГц (1 такт АЦП 64 такта процессора). Прерывания внутри АЦП разрешены для работы таймера. Приведённый ниже код работает, переключение каналов происходит. Буфер накапливается и значения АЦП по USART забирается (с периодом 300мс). Но примерно пару раз в минуту данные идут не с того канала в частности в обработке канала I2_MAIN проскакивают значения из канала I_42_MAIN почему такое происходит?
При убирании задержки в 200 тактов(для записи MUX) или запрет прерывания в обработчике АЦП, таких частых проскоков не наблюдается. Как это может быть связанно ? Без задержки в 200 тактов такое происходили но с периодичностью в минут 30.
CODE
////=============ADCinitialization==================================================
=================
////ADCSRA=0;
//ADMUX=2; //I1
//ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
//
//ADC_I42
//ADMUX=1; //slave in
//ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
////================================================================================
============
interrupt [ADC_INT] void adc_isr(void){
#asm("sei")
switch(adc_main){
case I1_MAIN:{
adc_main=I_42_MAIN; // Переход на измерения следующего канала
ADC_BUF->test_int[4]=ADCW; //записали в буфер(данный буфер выдаётся в UART по запросу)
ADMUX_TEMP=3; //I2 переключаемся на канал I2 через итерацию(для установления переходных процессов) с задержкой в 200 тактов
//ADC_I28
break;
}
case I_42_MAIN:{
adc_main=I2_MAIN; // Переход на измерения следующего канала
ADC_BUF->test_int[3]=ADCW; //записали в буфер(данный буфер выдаётся в USART по запросу)
ADMUX_TEMP=1; //I28 переключаемся на канал I28 через итерацию (для установления переходных процессов) с задержкой в 200 тактов
break;
}
case I2_MAIN:{
// Правильно значение АПЦ равно 647 в основном оно так и приходит но время от времени (пару раз в минуту)
// Проскакивает значение с АЦП c предыдущего канала.
// функция DEBUGER заносит в очередь ошибку(и значение АЦП) для отправки по USART
if(ADCW>700){DEBUGER("ADCW_HIGEST=",0,ADCW,var2);}
if(ADCW<600){
DEBUGER("ADC_INT_ADCW=",0,ADCW,var2);
LED_GREEN_DOWN();
test_I2[test_I2_index]=ADCH;
test_I2[test_I2_index+1]=ADCL;
test_I2_index++;
if(test_I2_index>14){test_I2_index=0;}
}
ADC_BUF->test_int[1]=ADCW;
adc_main=I28_SLAVE;
ADMUX_TEMP=2; //I
//ADC_I42
break;
}
case I28_SLAVE:{
adc_main=I1_MAIN;
ADC_BUF->test_int[5]=ADCW;
ADMUX_TEMP=1;
break;
}
default:{
adc_main=I1_MAIN;
DEBUGER("adc_main=error",0,0,MESEGER);
}
}
#include <nop2.c> // задержка 200 nop
ADMUX=ADMUX_TEMP;
}
=================
////ADCSRA=0;
//ADMUX=2; //I1
//ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
//
//ADC_I42
//ADMUX=1; //slave in
//ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
////================================================================================
============
interrupt [ADC_INT] void adc_isr(void){
#asm("sei")
switch(adc_main){
case I1_MAIN:{
adc_main=I_42_MAIN; // Переход на измерения следующего канала
ADC_BUF->test_int[4]=ADCW; //записали в буфер(данный буфер выдаётся в UART по запросу)
ADMUX_TEMP=3; //I2 переключаемся на канал I2 через итерацию(для установления переходных процессов) с задержкой в 200 тактов
//ADC_I28
break;
}
case I_42_MAIN:{
adc_main=I2_MAIN; // Переход на измерения следующего канала
ADC_BUF->test_int[3]=ADCW; //записали в буфер(данный буфер выдаётся в USART по запросу)
ADMUX_TEMP=1; //I28 переключаемся на канал I28 через итерацию (для установления переходных процессов) с задержкой в 200 тактов
break;
}
case I2_MAIN:{
// Правильно значение АПЦ равно 647 в основном оно так и приходит но время от времени (пару раз в минуту)
// Проскакивает значение с АЦП c предыдущего канала.
// функция DEBUGER заносит в очередь ошибку(и значение АЦП) для отправки по USART
if(ADCW>700){DEBUGER("ADCW_HIGEST=",0,ADCW,var2);}
if(ADCW<600){
DEBUGER("ADC_INT_ADCW=",0,ADCW,var2);
LED_GREEN_DOWN();
test_I2[test_I2_index]=ADCH;
test_I2[test_I2_index+1]=ADCL;
test_I2_index++;
if(test_I2_index>14){test_I2_index=0;}
}
ADC_BUF->test_int[1]=ADCW;
adc_main=I28_SLAVE;
ADMUX_TEMP=2; //I
//ADC_I42
break;
}
case I28_SLAVE:{
adc_main=I1_MAIN;
ADC_BUF->test_int[5]=ADCW;
ADMUX_TEMP=1;
break;
}
default:{
adc_main=I1_MAIN;
DEBUGER("adc_main=error",0,0,MESEGER);
}
}
#include <nop2.c> // задержка 200 nop
ADMUX=ADMUX_TEMP;
}