Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает АЦП Attiny461a в реальной схеме
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Dimon84
АЦП в реальной выдает постоянно одно и тоже значение (0xFF) при любом напряжении на выводе ADC1.
В Протеусе все работает, а в реальной схеме нет.

Конфигурация вывода ADC1:
DDRA=0x00
PORTA=0x00

Инициализация АЦП:
Код:
ADCSRA |=(0<< ADATE); // Режим одиночного преобразования АЦП
ADCSRA |=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Коэфф. деления предделителя АЦП =64
// частота преобраз.=62,5 кГц.
ADMUX |=(0<<REFS1) | (1<<REFS0)|(1<<ADLAR); // Внешний ИОН (1,23 В), подкл. к выводу
//AREF
DIDR0 |=(1<<ADC1D) |(1<<ADC2D)|(1<<AREFD); // Отключаем цифровые буферы на выводах
//считывания аналоговых сигналов (для уменьш. токопотребления)


Функция считывания данных с АЦП:
Код:
// Настройка входа для измерения напряжения
ADMUX &=~((1<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0)); // Обнуляем предыдущие настройки
ADMUX |=((0<<MUX5) | (0<<MUX4) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (1<<MUX0)); // подкл. вход ADC1
ADCSRA|=(1<<ADEN); //Вкл. АЦП
ADCSRA|=(1<<ADSC); //Начать преобразование
while (!(ADCSRA &(1<<ADIF))) //Дождатся окончания преобразования
{
}
_delay_ms(100);
v=ADCL;
v=ADCH;
ADCSRA &=~(1<<ADEN); //Выкл. АЦП
_Артём_
Эти строки вызывают сомнения:
Цитата(Dimon84 @ Nov 3 2012, 16:29) *
_delay_ms(100);
v=ADCL;
v=ADCH;
ADCSRA &=~(1<<ADEN); //Выкл. АЦП


потому что
Цитата
When initiating a single ended conversion by setting the ADSC bit in ADCSRA, the conversion
starts at the following rising edge of the ADC clock cycle.
A normal conversion takes 13 ADC clock cycles. 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,
as shown in Figure 15-4 below.

Попробуйте не выключать АЦП после завершения преобразования.

И ещё вот это:
Цитата(Dimon84 @ Nov 3 2012, 16:29) *
v=ADCL;
v=ADCH;
ADCSRA &=~(1<<ADEN); //Выкл. АЦП

Получается что вы читаете в одну и ту же переменную - теряется ADCL.
Dimon84
Цитата(_Артём_ @ Nov 3 2012, 17:44) *
Получается что вы читаете в одну и ту же переменную - теряется ADCL.


А полезные данные находятся в ADCH.

Рекомендации данные выше не помогли.
Палыч
Цитата из DS:
Цитата
ADIF is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, ADIF is cleared by writing a logical one to the flag.
_Артём_
Цитата(Dimon84 @ Nov 3 2012, 16:58) *
А полезные данные находятся в ADCH.

Тогда ладно.

Цитата(Dimon84 @ Nov 3 2012, 16:58) *
Рекомендации данные выше не помогли.

Бывает.

Что ещё посоветовать?
У вас много операций с ADCSRA и MUX через |= и &=, возможно где-то ошиблись. Попробуйте записать нужное сразу.
Код
ADCSRA=ADC_CTRL_VALUE;
ADMUX=MUX_VALUE;


PS. MUX5 - это кто? ADLAR? Зачем его в ноль сбрасывать?
Dimon84
Вот я и жду пока ADIF сбросться:
while (!(ADCSRA &(1<<ADIF)))
_Артём_
Цитата(Dimon84 @ Nov 3 2012, 17:19) *
Вот я и жду пока ADIF сбросться:
while (!(ADCSRA &(1<<ADIF)))

С какой стати ADIF должен сбросится?
Сбрасывается ADSC, ADIF - устанавливается по завершении преобразования.
Код
while ((ADCSRA &(1<<ADIF))==0); // ожидание завершения

unsigned short adc_result=ADC; // чтение результата
// или если нужен 1 байт
//unsigned char adc_resulr_byte=ADCH;
Палыч
После первого преобразования ADIF навсегда остаётся в единице - нужно сбрасывать записью в него единицы
Dimon84
Цитата(_Артём_ @ Nov 3 2012, 18:24) *
С какой стати ADIF должен сбросится?
Сбрасывается ADSC, ADIF - устанавливается по завершении преобразования.
Код
while ((ADCSRA &(1<<ADIF))==0); // ожидание завершения

unsigned short adc_result=ADC; // чтение результата
// или если нужен 1 байт
//unsigned char adc_resulr_byte=ADCH;


Сейчас попробую
_Артём_
Цитата(Палыч @ Nov 3 2012, 17:40) *
После первого преобразования ADIF навсегда остаётся в единице - нужно сбрасывать записью в него единицы


Смотря как делается.
Если так
Код
ADCSRA |=(0<< ADATE);

то не остаётся.
Dimon84
Цитата(_Артём_ @ Nov 3 2012, 18:54) *
Смотря как делается.
Если так
Код
ADCSRA |=(0<< ADATE);

то не остаётся.



ADCSRA |=(0<< ADATE) - ни на что не влияет.
RabidRabbit
Из даташита (по поводу Внешний ИОН (1,23 В), подкл. к выводу //AREF):
AREF External Voltage Reference
Single Ended Conversions Min 2.0V
Differential Conversions Min 2.0V

Ну и без прерываний, по-моему, для определения завершения в режиме одиночного преобразования лучше пользоваться битом ADCSRA.ADSC

И ещё:
ADCSRA |=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Коэфф. деления предделителя АЦП =64
в этом случае предделитель 128, а не 64.
ReAl
Цитата(Палыч @ Nov 3 2012, 17:40) *
После первого преобразования ADIF навсегда остаётся в единице - нужно сбрасывать записью в него единицы

Вот именно, причём _явной_ записью.
У старых AVR-ок с SBI/CBI в виде Read (весь байт SFR) - Modify - Write (опять весь байт SFR) достаточно было
Код
    // Компилируется в SBI ADCSRA, ADSC -- хоть это, по моему мнению, некоторое отклонение от стандарта С,
    // но полезное с точки зрения эффективности.
    // Если бы оно компилировалось в более корректное IN/ORI/OUT, обсуждаемой проблемы не было бы,
    // но была бы со всеобщей точки зрения «недостаточная оптимизация».
    ADCSRA |= (1<<ADSC);

и ADIF сбрасывался сам собой, так как сам в себя писал единичку в RMW-цикле.
В новых шара не канает. То, что работало в Tiny26, в Tiny261/461/861 работать не будет.
Ну что оно в протеусе работает, так это он, значит, не знает, что работа команд SBI/CBI давно поменялась (тогда же, когда запись в PINx стала инвертировать PORTx).

Ещё по теме http://electronix.ru/forum/index.php?showtopic=95401

Цитата(_Артём_ @ Nov 3 2012, 17:24) *
С какой стати ADIF должен сбросится?
Сбрасывается ADSC, ADIF - устанавливается по завершении преобразования.
Код
while ((ADCSRA &(1<<ADIF))==0); // ожидание завершения
Там надо читать «вот я и жду, пока ADIF сброшен» независимо от того, что написано «сбросится» :-)
Ведь
Цитата(Dimon84 @ Nov 3 2012, 16:29) *
while (!(ADCSRA &(1<<ADIF))) //Дождатся окончания преобразования
это то же самое.
Dimon84
Цитата(RabidRabbit @ Nov 4 2012, 10:38) *
Из даташита (по поводу Внешний ИОН (1,23 В), подкл. к выводу //AREF):
AREF External Voltage Reference
Single Ended Conversions Min 2.0V
Differential Conversions Min 2.0V

Ну и без прерываний, по-моему, для определения завершения в режиме одиночного преобразования лучше пользоваться битом ADCSRA.ADSC

И ещё:
ADCSRA |=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Коэфф. деления предделителя АЦП =64
в этом случае предделитель 128, а не 64.


Проблема решилась. Скорее всего дело было в ИОН. Поставил на 2,56 и заработало. Рабочий код напишу чуть позже.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.