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

 
 
> 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
 
Start new topic
Ответов
Сергей Борщ
сообщение 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



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

 


RSS Текстовая версия Сейчас: 26th July 2025 - 00:45
Рейтинг@Mail.ru


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