Перейти к содержанию
    

ADC на 328 атмеге оцифровка с не тех входов

Привет всем! попытаюсь описать свою проблему. Есть 2 аналоговых канала. Оба замеряют напряжение и подключены на ADC7 и ADC0 контроллера.

обработчик прерывания написан так:

#define             ADC_VREF_TYPE         ((0<<REFS1) | (0<<REFS0) | (0<<ADLAR))   //AREF - reference
#define        ADMUX_0                (ADC_VREF_TYPE|0)
#define        ADMUX_7                (ADC_VREF_TYPE|7)
DIDR0  = (0<<ADC5D)|(0<<ADC4D)|(0<<ADC3D)|(0<<ADC2D)|(0<<ADC1D)|(0<<ADC0D); 
ADMUX  = ADMUX_0; //AREF pin
ADCSRA = (1<<ADEN) |(1<<ADSC) |(1<<ADATE)|(0<<ADIF) |(1<<ADIE) |(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
ADCSRB = (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);// отказываемся от источника запуска преобразования

ISR(ADC_vect)
{        
    static u08 i = 0;        
    
    adcData[i] = ADCW;// Read the AD conversion result
    switch(i)
    {
        case 0:
        {
            ADMUX = ADMUX_7;    //res
            i = 1;            
        }break;
        
        case 1:
        {
            ADMUX = ADMUX_0;    //m_s
            i = 0;            
        }break;        
        
    }    
    _delay_us(10);// Delay needed for the stabilization of the ADC input voltage        
    ADCSRA|=(1<<ADSC);
}

проблема в том, что adcData[0] оцифровывает значение с канала ADC7, а adcData[1] с канала ADC0, т.е наоборот...В чем косяк понять не могу, ведь я могу сменить вход adc только при окончании текущего преобразования и до запуска слудующего. Попав в обработчик я полагаю, что текущее преобразование уже закончено и новое не запустится, пока не взведу флаг ADSC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В чем косяк понять не могу, ведь я могу сменить вход adc только при окончании текущего преобразования и до запуска слудующего
Не совсем так, читайте описание внимательнее. Вы можете писать биты выбора канала когда угодно, но если преобразование уже началось, то сработают они только после его окончания. У вас же происходит следующее: вы запускаете АЦП в свободнобегущем режиме, т.е. взведение бита ADSC запускает первое преобразование, а дальше АЦП само автоматически начинает следующее преобразование сразу после окончания предыдущего. У вас заканчивается преобразование, скажем, канала 0, генерится прерывание и тут же запускается следующее. Вы попадаете в прерывание, переключаете канал, но это переключение будет принято во внимание только перед следующим преобразованием, поскольку очередное преобразование уже началось. У вас есть два выхода: либо сразу после первой установки ADSC записать в ADMUX номер канала для следующего преобразования и дальше уже ADSC не трогать, либо записать в ADATE ноль и тогда АЦП будет ожидать от вас ADSC перед началом каждого преобразования.

 

 

        ....
    _delay_us(10);// Delay needed for the stabilization of the ADC input voltage        
        .....
}

Ужас. Уберите __delay_us() и больше так никогда не делайте. Во-первых АЦП само добавляет необходимое количество тактов к времени выборки при смене канала, а во-вторых задержки в прерывании - это просто глупо. Пока вы сидите в этой задержке все остальные прерывания заблокированы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...вы запускаете АЦП в свободнобегущем режиме, т.е. взведение бита ADSC запускает первое преобразование, а дальше АЦП само автоматически начинает следующее преобразование сразу после окончания предыдущего. У вас заканчивается преобразование, скажем, канала 0, генерится прерывание и тут же запускается следующее. Вы попадаете в прерывание, переключаете канал, но это переключение будет принято во внимание только перед следующим преобразованием, поскольку очередное преобразование уже началось. У вас есть два выхода: либо сразу после первой установки ADSC записать в ADMUX номер канала для следующего преобразования и дальше уже ADSC не трогать, либо записать в ADATE ноль и тогда АЦП будет ожидать от вас ADSC перед началом каждого преобразования.

Вы молодец Сергей, я тоже пришел к такому выводу после долгих мучений, что вся проблема во free run mode и в прерывании нахожусь когда наверняка следуещее уже шпарит. Просто в даташите это не было описано. В последствии я убрал DATE бит, и запускаю каждое следующее уже в конце обработчика.

Ужас. Уберите __delay_us() и больше так никогда не делайте. Во-первых АЦП само добавляет необходимое количество тактов к времени выборки при смене канала, а во-вторых задержки в прерывании - это просто глупо. Пока вы сидите в этой задержке все остальные прерывания заблокированы.

Логично рассуждаете, готов сделать так, но почему тогда в датише описана эта задержка....Ах да, там скорее всего наверное дан пример однократных запусков, т.к к ней комментарий объяснял ее внедрение для устаканивания напряжения на выходе мультиплексора при смене входного канала.

Большое спасибо Сергей...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто в даташите это не было описано
Было, и даже с картинкой:

post-17095-1505974592_thumb.png

 

Логично рассуждаете, готов сделать так, но почему тогда в датише описана эта задержка... Ах да, там скорее всего наверное дан пример однократных запусков, т.к к ней комментарий объяснял ее внедрение для устаканивания напряжения на выходе мультиплексора при смене входного канала.
Что-то я не нашел такого объяснения. Я тоже глупость спорол (перечитал еще раз, освежил в памяти): дополнительная задержка делается автоматически только при первом преобразовании после взведения ADEN:
The first conversion after the ADC is switched on (ADEN in ADCSRA is set) takes 25 ADC clock cycles in order to initialize the analog circuitry
После смены канала дополнительная задержка не нужна просто потому, что конденсатор устройства выборки-хранения (УВХ, sampling capacitor) подключается к входной цепи только на время выборки. Это время в описании не указано, но оно прибито гвоздями, на него мы повлиять не можем никак. Единственное, что мы можем сделать - это обеспечить настолько низкое выходное сопротивление измеряемой цепи, чтобы за время выборки запоминающий конденсатор УВХ успел зарядиться до входного напряжения с погрешностью не более половины веса младшего значащего разряда или же уменьшить тактовую частоту АЦП настолько, чтобы времени выборки стало достаточно для имеющегося выходного сопротивления источника сигнала. Для 12-битного преобразования на максимальной частоте выходное сопротивление источника сигнала должно быть меньше 10 кОм (это указано в документации), для меньшей разрядности или частоты его можно посчитать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...