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

 
 
 
Reply to this topicStart new topic
> Не работает АЦП Attiny461a в реальной схеме, в Протеусе работает.
Dimon84
сообщение Nov 3 2012, 14:29
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



АЦП в реальной выдает постоянно одно и тоже значение (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); //Выкл. АЦП
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 3 2012, 14:44
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Эти строки вызывают сомнения:
Цитата(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.
Go to the top of the page
 
+Quote Post
Dimon84
сообщение Nov 3 2012, 14:58
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



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


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

Рекомендации данные выше не помогли.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 3 2012, 15:14
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата из 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.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 3 2012, 15:16
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(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? Зачем его в ноль сбрасывать?
Go to the top of the page
 
+Quote Post
Dimon84
сообщение Nov 3 2012, 15:19
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



Вот я и жду пока ADIF сбросться:
while (!(ADCSRA &(1<<ADIF)))
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 3 2012, 15:24
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(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;
Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 3 2012, 15:40
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



После первого преобразования ADIF навсегда остаётся в единице - нужно сбрасывать записью в него единицы
Go to the top of the page
 
+Quote Post
Dimon84
сообщение Nov 3 2012, 15:45
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



Цитата(_Артём_ @ 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;


Сейчас попробую


Сообщение отредактировал Dimon84 - Nov 3 2012, 15:47
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 3 2012, 15:54
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



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


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

то не остаётся.
Go to the top of the page
 
+Quote Post
Dimon84
сообщение Nov 3 2012, 16:05
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



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

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



ADCSRA |=(0<< ADATE) - ни на что не влияет.
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Nov 4 2012, 06:38
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Из даташита (по поводу Внешний ИОН (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.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 4 2012, 09:26
Сообщение #13


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Палыч @ 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))) //Дождатся окончания преобразования
это то же самое.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Dimon84
сообщение Nov 6 2012, 18:39
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 4-08-12
Из: г.Чебоксары
Пользователь №: 73 015



Цитата(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 и заработало. Рабочий код напишу чуть позже.
Go to the top of the page
 
+Quote Post

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

 


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


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