реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> ADC на 328 атмеге оцифровка с не тех входов
Fynjisx
сообщение Sep 20 2017, 12:18
Сообщение #1


студент
****

Группа: Свой
Сообщений: 571
Регистрация: 3-07-08
Из: Russia
Пользователь №: 38 712



Привет всем! попытаюсь описать свою проблему. Есть 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.


--------------------
С Уважением...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 20 2017, 13:48
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Fynjisx
сообщение Sep 21 2017, 04:28
Сообщение #3


студент
****

Группа: Свой
Сообщений: 571
Регистрация: 3-07-08
Из: Russia
Пользователь №: 38 712



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

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

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


--------------------
С Уважением...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 21 2017, 06:46
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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 кОм (это указано в документации), для меньшей разрядности или частоты его можно посчитать.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st September 2024 - 18:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01383 секунд с 7
ELECTRONIX ©2004-2016