Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADC+MUX
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
bodja74
Проблема такая ,пытаюсь мерять 2 напряжения с помощью ADC ,попеременно переключая входы в прерывании от АЦП ,в результате у меня получаемые значения как будто я меряю только на одном входе и как правило того входа АЦП ,которое я инициализирую первым ,хотя бывают "глюки-исключения" smile.gif

MUX меняю точно ,пробовал отключать и заново запускать АЦП ,что битами ,что полностью регистрами-результат одинаков,похоже есть какой то ньюанс при переключении АЦП,но какой не знаю sad.gif

Вот такие лыжи на асфальте ,и не могу понять в чем дело.
Kovrov
после смены мукса попробуйте дернуть ADEN.
Dopler
Не надо после Mux ничего дергать, все должно работать и так. На какой частоте работаете?
SasaVitebsk
Привет Богдан! smile.gif
Было бы приятно тебе помочь. smile.gif

Привожу пример на любимом твоём АСМе. smile.gif

Код
; Сменить канал АЦП
izm1:
    mov        wpl,chan
    andi    wpl,7    ; выделить номер канала
    subi    wpl,-2    ; начать с канала 2
    ori        wpl,kadmux
.if chip == 88
    sts        admux,wpl; включить новый канал
.else
    out        admux,wpl; включить новый канал
.endif
.......
; Инициализация

.if chip == 88
    .equ    kadcsra    = exp2(aden)+exp2(adsc)+exp2(adate)+exp2(adps1)+exp2(adps0)
.else
    .equ    kadcsra    = exp2(aden)+exp2(adsc)+exp2(adfr)+exp2(adps1)+exp2(adps0)
.endif
; Для внутреннего АЦП
;.equ    kadmux    = exp2(refs1)+exp2(refs0)+exp2(adlar)
; Для внешнего АЦП
.equ    kadmux    = exp2(adlar)

    ldi        chan,0
    ldi        wl,kadcsra+exp2(adif)
.if chip == 88
    sts        adcsra,wl; сбросить флаг завершения преобразования
.else
    out        adcsr,wl; сбросить флаг завершения преобразования
.endif
    mov        wl,chan
    subi    wl,-2    ; начать с канала 2
    ori        wl,kadmux
.if chip == 88
    sts        admux,wpl; включить новый канал
.else
    out        admux,wpl; включить новый канал
.endif


Я, в данном случае использовал автоматический режим.



Вожможная причина твоей проблемы.

Я измеряю в прерывании от таймера. Интервал выбран по времени измерения. Я сначала измеряю, а потом переключаю канал. То есть должно пройти время от переключения до измерения.

С уважением.
Kovrov
Цитата(Dopler @ Jan 24 2007, 22:47) *
Не надо после Mux ничего дергать, все должно работать и так. На какой частоте работаете?

Только после передергивания ADEN ADC сделает холостую конверсию на интервал измерения.
bodja74
Цитата(Dopler @ Jan 24 2007, 22:47) *
Не надо после Mux ничего дергать, все должно работать и так. На какой частоте работаете?


МК 1МГц
Камень "нулевый"
Клок 125кГц ,тоесть все как книжка пишет.
В симуляторе тоже песня.
Но по факту бздык.

ADEN и дергал и не дергал ,и режимы другие пробовал,и регистры по разному читал ,короче как угодно smile.gif

По идее по прерыванию от АЦП ,в регистрах уже должны быть необходимые данные от нужного входа.

Ок! Всем спасибо за советы ,завтра на работе попробую Ваши предложения.

1 Сделаю по прерыванию от таймера.
2 Сделаю по прерыванию от АЦП ,но результат буду снимать после 2-3 выборки после переключения.
3 Если не поможет поставлю камень в уже готовый проект на проверку,там точно все переключается,но только "вручную".

Похоже действительно ,что то со временем на переключение,попробую разобраться и доложить результат smile.gif
singlskv
А битик ADFR в регистре ADCSRA в нуле ?
То есть точно Single Conversation Mode выбрано ?
sseett
1. Опора включена заранее? Может долго устанавливаться.
2. Входные (измеряемые) сигналы с выходным сопротивлением не более 10 кОм?
rat
Сталкивался с подобным траблом, после переключения канала нужно выждать интервал, равный, или больший времени одного преобразования и только после этого считывать результат(АЦП на автомате).
bodja74
Kovrov ,респект,дали правильное направление в поиске трабла. smile.gif

Сделал по прерыванию от АЦП ,так как уже были наброски.
Вот что выяснилось ,при переключении (вне зависимости дергаем ADEN или нет) ,АЦП делает 1 холостой ход ,при этом генерируя прерывание.
А при включеном бите ADATE нужно пропустить 2 цикла конверсии,и после этого уже считывать результат.
Я знал что на переинациализацию нужно дополнительное время ,но не думал что будут генерироваться прерывания.

В принципе проблема решена ,всем спасибо за советы. smile.gif
singlskv
Цитата(bodja74 @ Jan 25 2007, 21:38) *
Kovrov ,респект,дали правильное направление в поиске трабла. smile.gif

Сделал по прерыванию от АЦП ,так как уже были наброски.
Вот что выяснилось ,при переключении (вне зависимости дергаем ADEN или нет) ,АЦП делает 1 холостой ход ,при этом генерируя прерывание.
А при включеном бите ADATE нужно пропустить 2 цикла конверсии,и после этого уже считывать результат.
Я знал что на переинациализацию нужно дополнительное время ,но не думал что будут генерироваться прерывания.

В принципе проблема решена ,всем спасибо за советы. smile.gif

bodja74
А Вы запускаете АЦП в режиме Single Conversion Mode или Free Running ?

Если в Free Running, то Вы просто не вовремя меняеете ADMUX, его нельзя менять
в том же прерывании где считывали последний результат
В режиме Free Running новое преобразование начинается еще до того как Вы попали
в прерывание и если Вы в прерывании меняете ADMUX пока не прошло 1,5 ADC clock cycles
то следующий результат будет просто мусором
Если Вам нужно после каждого результата менять канал ADC и режим Free Running, то
тогда после считывания результата нужно подождать > 1,5 ADC clock cycles и до наступления
нового прерывания успеть сменить ADMUX
Удачи
bodja74
Цитата(singlskv @ Jan 25 2007, 22:56) *
bodja74
А Вы запускаете АЦП в режиме Single Conversion Mode или Free Running ?

Если в Free Running, то Вы просто не вовремя меняеете ADMUX, его нельзя менять
в том же прерывании где считывали последний результат
В режиме Free Running новое преобразование начинается еще до того как Вы попали
в прерывание и если Вы в прерывании меняете ADMUX пока не прошло 1,5 ADC clock cycles
то следующий результат будет просто мусором
Если Вам нужно после каждого результата менять канал ADC и режим Free Running, то
тогда после считывания результата нужно подождать > 1,5 ADC clock cycles и до наступления
нового прерывания успеть сменить ADMUX
Удачи


У меня действительно режим Free Running ,но это не значит ,что это режим непрерывного
преобразования ,без бита ADATE - его не будет .
Я уже писал выше ,что при установке ADATE я получал правильный результат на третьем прерывании.
В моем же случае АЦП уже остановленно при входе в прерывание , читаю результат ,меняю MUX и при выходе запускаю АЦП битом ADSC и получаю правильный результат на втором прерывании.
В данном случае я немогу точно сказать ,сколько времени нужно для полноценного переключения АЦП так как больше интересовало ,на каком прерывании я получу нужный результат.
muravei
Цитата(bodja74 @ Jan 25 2007, 02:15) *
Проблема такая ,пытаюсь мерять 2 напряжения с помощью ADC ,попеременно переключая входы

Теже грабли.
только на mega164P.
Прерывания не использую . Запускаю вручную. Пробовал мерять по три раза, результат тот же. crying.gif
pavel-pervomaysk
На ATmega8 делал вольтметр + амперметр

CODE
//ADC_INIT
ldi tmp,0x87 // Bits 2 1 0 ADC PRESCALLER
out ADCSRA, tmp //

main:
rcall wait
ldi tmp,0xC2 // ADC_2
out ADMUX,tmp //
rcall ADC_1 //
;rcall decod_V //

ldi tmp,0xC1 // ADC_1
out ADMUX,tmp //
rcall ADC_1 //
;rcall decod_A //
sei
rjmp main //


ADC_1: //
sbi ADCSRA,6 //
ADC_NV: //
sbic ADCSRA,6 //
rjmp ADC_NV //
in yl, ADCL //
in yh, ADCH //
ret //


Может не в тему , но работает без нареканий.
troy97
Вот мой кусок кода на С, работает как надо:

Код
        for (i=0; i<6; i++)
        {
                ADMUX&=0b11110000;      
                ADMUX|=i;          
                ADCSRA|=0x40;          
                while(!(ADCSRA & (1<<ADIF)));
                ADCSRA|=(1<<ADIF);        
        
                adc_data=ADCW;              
                .....      
                                              
        };
muravei
Цитата(troy97 @ Sep 25 2009, 10:40) *
Вот мой кусок кода на С, работает как надо:

Код
              
                while(!(ADCSRA & (1<<ADIF)));


Спасибо, помогло это.

А почему так низя?

while (!ADIF);
Rst7
Цитата
А почему так низя?

while (!ADIF);


Т.к. ADIF суть номер бита, то !ADIF будет всегда false (или true, если бит - нулевой).

Можно так:
Код
while(!ADCSRA_ADIF);

, только Enable Bit Definition разрешить.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.