Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADC на 328 атмеге оцифровка с не тех входов
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Fynjisx
Привет всем! попытаюсь описать свою проблему. Есть 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.
Сергей Борщ
QUOTE (Fynjisx @ Sep 20 2017, 15:18) *
В чем косяк понять не могу, ведь я могу сменить вход adc только при окончании текущего преобразования и до запуска слудующего
Не совсем так, читайте описание внимательнее. Вы можете писать биты выбора канала когда угодно, но если преобразование уже началось, то сработают они только после его окончания. У вас же происходит следующее: вы запускаете АЦП в свободнобегущем режиме, т.е. взведение бита ADSC запускает первое преобразование, а дальше АЦП само автоматически начинает следующее преобразование сразу после окончания предыдущего. У вас заканчивается преобразование, скажем, канала 0, генерится прерывание и тут же запускается следующее. Вы попадаете в прерывание, переключаете канал, но это переключение будет принято во внимание только перед следующим преобразованием, поскольку очередное преобразование уже началось. У вас есть два выхода: либо сразу после первой установки ADSC записать в ADMUX номер канала для следующего преобразования и дальше уже ADSC не трогать, либо записать в ADATE ноль и тогда АЦП будет ожидать от вас ADSC перед началом каждого преобразования.


QUOTE (Fynjisx @ Sep 20 2017, 15:18) *
CODE
        ....
    _delay_us(10);// Delay needed for the stabilization of the ADC input voltage        
        .....
}
Ужас. Уберите __delay_us() и больше так никогда не делайте. Во-первых АЦП само добавляет необходимое количество тактов к времени выборки при смене канала, а во-вторых задержки в прерывании - это просто глупо. Пока вы сидите в этой задержке все остальные прерывания заблокированы.
Fynjisx
Цитата(Сергей Борщ @ Sep 20 2017, 17:48) *
...вы запускаете АЦП в свободнобегущем режиме, т.е. взведение бита ADSC запускает первое преобразование, а дальше АЦП само автоматически начинает следующее преобразование сразу после окончания предыдущего. У вас заканчивается преобразование, скажем, канала 0, генерится прерывание и тут же запускается следующее. Вы попадаете в прерывание, переключаете канал, но это переключение будет принято во внимание только перед следующим преобразованием, поскольку очередное преобразование уже началось. У вас есть два выхода: либо сразу после первой установки ADSC записать в ADMUX номер канала для следующего преобразования и дальше уже ADSC не трогать, либо записать в ADATE ноль и тогда АЦП будет ожидать от вас ADSC перед началом каждого преобразования.

Вы молодец Сергей, я тоже пришел к такому выводу после долгих мучений, что вся проблема во free run mode и в прерывании нахожусь когда наверняка следуещее уже шпарит. Просто в даташите это не было описано. В последствии я убрал DATE бит, и запускаю каждое следующее уже в конце обработчика.
Цитата(Сергей Борщ @ Sep 20 2017, 17:48) *
Ужас. Уберите __delay_us() и больше так никогда не делайте. Во-первых АЦП само добавляет необходимое количество тактов к времени выборки при смене канала, а во-вторых задержки в прерывании - это просто глупо. Пока вы сидите в этой задержке все остальные прерывания заблокированы.

Логично рассуждаете, готов сделать так, но почему тогда в датише описана эта задержка....Ах да, там скорее всего наверное дан пример однократных запусков, т.к к ней комментарий объяснял ее внедрение для устаканивания напряжения на выходе мультиплексора при смене входного канала.
Большое спасибо Сергей...
Сергей Борщ
QUOTE (Fynjisx @ Sep 21 2017, 07:28) *
Просто в даташите это не было описано
Было, и даже с картинкой:
Нажмите для просмотра прикрепленного файла

QUOTE (Fynjisx @ Sep 21 2017, 07:28) *
Логично рассуждаете, готов сделать так, но почему тогда в датише описана эта задержка... Ах да, там скорее всего наверное дан пример однократных запусков, т.к к ней комментарий объяснял ее внедрение для устаканивания напряжения на выходе мультиплексора при смене входного канала.
Что-то я не нашел такого объяснения. Я тоже глупость спорол (перечитал еще раз, освежил в памяти): дополнительная задержка делается автоматически только при первом преобразовании после взведения ADEN:
QUOTE
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 кОм (это указано в документации), для меньшей разрядности или частоты его можно посчитать.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.