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

 
 
> Опрос АЦП внутри прерывания
AndreyVN
сообщение Dec 7 2013, 06:41
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 754
Регистрация: 29-06-06
Из: Volgograd
Пользователь №: 18 458



Всем привет!
Перенес код опроса АЦП (ATmega16) внутрь обработчика прерываний от таймера, АЦП напрочь перестал работать, оба байта стабильно 00, 00.
Есть какие-то подводные камни при запуске однократного преобразования АЦП в теле обработчика прерывания? (Сам факт вызова процедуры обработчика прерывания вижу на осциллографе.)

Этим кодом пользовался много раз:
Код

//АЦП доступен, прерывания разрешены
//ADCSRA: 7-ADEEN 6-ADSC 5-ADATE 4-ADIF 3-ADIE 2-ADPS2 1-ADPS2 0-ADPS0
//           1      0       0      0      0      1       1       1
ADCSRA = 0x87;
...
ADCSRA |= 0x40; //Начать одиночное преобразование АЦП
while( (ADCSRA & 0x40)==0x40 ); //ждем завершения преобразования ADSC (13-14 тактов)
c1 = ADCL; //Читаем результат преобразования сначала младший
c2 = ADCH; //затем старший (иначе не работает!)
VADC = c1 + c2*256;
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение Dec 8 2013, 00:31
Сообщение #2


Гуру
******

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



Цитата(AndreyVN @ Dec 7 2013, 08:41) *
оба байта стабильно 00, 00.
А где вы их проверяете? В этом же прерывании или в основном цикле? Если в основном цикле, то как объявлена переменная VADC?

Цитата(AndreyVN @ Dec 7 2013, 08:41) *
Код
while( (ADCSRA & 0x40)==0x40 ); //ждем завершения преобразования ADSC (13-14 тактов)
Вы только не забывайте, что это 13-14 тактов частоты АЦП, в вашем случае это 13...14 * 128 = 1664 или 1792 тактов ядра. Вы хорошо подумали, прежде чем засунуть такое ожидание в обработчик прерывания?

Цитата(AndreyVN @ Dec 7 2013, 08:41) *
Код
c1 = ADCL; //Читаем результат преобразования сначала младший
c2 = ADCH; //затем старший (иначе не работает!)
VADC = c1 + c2*256;
Ой. Делайте VADC = ADC; и не морочьте себе голову. Любой компилятор для AVR знает, в каком порядке надо читать двухбайтные регистры.

Цитата(AndreyVN @ Dec 7 2013, 21:36) *
А Иде смотреть-то?
В своем листинге. Внимательно смотреть, что сгенерил компилятор и думать - где вы могли неправильно объяснить ему свою задумку.

Чудес не бывает.


--------------------
На любой вопрос даю любой ответ
"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
AndreyVN
сообщение Dec 8 2013, 06:22
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 754
Регистрация: 29-06-06
Из: Volgograd
Пользователь №: 18 458



Цитата
А где вы их проверяете? В этом же прерывании или в основном цикле? Если в основном цикле, то как объявлена переменная VADC?


Я контролирую не VADC, а непосредственно с1, с2, чтобы свести к минимуму возможные причины ошибок в т.ч. присвоения, преобразования типов и т.п..
VADC тоже выводится на экран после мат. обработки, но это сейчас не интересно.
Вывод на LCD и в основном цикле пробовал и прямо в обработчике пробовал. Переменные тоже пробовал объявлять глобальными и локальными, ситуация не меняется.

Цитата
Вы только не забывайте, что это 13-14 тактов частоты АЦП, в вашем случае это 13...14 * 128 = 1664 или 1792 тактов ядра. Вы хорошо подумали, прежде чем засунуть такое ожидание в обработчик прерывания?

Общего быстродействия хватает, тем более, что сейчас ловлю готовность АЦП в прерывании (см. выше).

Цитата
Ой. Делайте VADC = ADC; и не морочьте себе голову. Любой компилятор для AVR знает, в каком порядке надо читать двухбайтные регистры.

Когда код заработает так и сделаю, а сейчас, предпочитаю видеть каждый байт как он есть.

Цитата
В своем листинге. Внимательно смотреть, что сгенерил компилятор и думать - где вы могли неправильно объяснить ему свою задумку.
Чудес не бывает.

Ой, Спасибо! Однако, Вы не сказали, удавалось лично Вам опрашивать АЦП в обработчике прерываний таймера?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 8 2013, 08:57
Сообщение #4


Гуру
******

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



Цитата(AndreyVN @ Dec 8 2013, 08:22) *
Вывод на LCD и в основном цикле пробовал и прямо в обработчике пробовал. Переменные тоже пробовал объявлять глобальными и локальными, ситуация не меняется.
Покажите объявление этих переменных. Хорошо, без намеков: используете ли вы в объявлении ключевое слово volatile?
Цитата(AndreyVN @ Dec 8 2013, 08:22) *
Ой, Спасибо! Однако, Вы не сказали, удавалось лично Вам опрашивать АЦП в обработчике прерываний таймера?
Мне удается опрашивать его где угодно. Еще раз повторю: чудес не бывает. В документации опрашивать АЦП в прерывании таймера не запрещено.


--------------------
На любой вопрос даю любой ответ
"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
AndreyVN
сообщение Dec 8 2013, 09:17
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 754
Регистрация: 29-06-06
Из: Volgograd
Пользователь №: 18 458



Цитата(Сергей Борщ @ Dec 8 2013, 11:57) *
Покажите объявление этих переменных. Хорошо, без намеков: используете ли вы в объявлении ключевое слово volatile?
Мне удается опрашивать его где угодно. Еще раз повторю: чудес не бывает. В документации опрашивать АЦП в прерывании таймера не запрещено.

Нет, volatile не использую. Раньше пользовался, когда менял C'шные переменные из кода ассемблерных вставок, но так и не знаю, зачем это надо компилятору. Собственно, проблема решилась, заработала конструкция:

Код
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
ADCSRA |= 0x40; //Начать одиночное преобразование АЦП  
PORTA.4 = ~PINA.4; //Для осциллографа
}

interrupt[ADC_INT] void ADC(void)
{
unsigned char c1,c2;
#asm("sei"); //Разрешить вложенные прерывания (управляющие H-мостом)
PORTA.4 = ~PINA.4; //Для осциллографа
c1 = ADCL; //Читаем результат преобразования сначала младший
c2 = ADCH; //затем старший (иначе не работает!)
V2 = (c1 + c2*256)*4.97*Ku/1024;
PORTA.4 = ~PINA.4; //Для осциллографа
}


Отключил 90% кода не связанного с обслуживанием АЦП, измерение ожило, затем стал возвращать процедуру за процедурой, специально проверил, работоспособность прерываний которые случаются во время interrupt[ADC_INT] (это разрешено командой SEI) - все работает, переменные c1, c2 хранятся в регистрах, но успешно сохраняются и восстанавливаются через стек. К сожалению, так и не понял, что было. Сейчас вернул почти весь код на место, все работает, возвращаться к обработке АЦП "внутри таймера" уже нет смысла.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 8 2013, 11:52
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AndreyVN @ Dec 8 2013, 12:17) *
Нет, volatile не использую.


Ну вот и ответ на вопрос.
Go to the top of the page
 
+Quote Post
WHALE
сообщение Dec 8 2013, 19:26
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Цитата(_Pasha @ Dec 8 2013, 15:52) *
Ну вот и ответ на вопрос.

ТС так и не указал используемый компилятор.Но судя по приведенным кускам кода-это CV.
А он не такой резкий в оптимизации как тот-же ЯР и не выкидывает без предупреждения
не- volatile переменные в прерываниях.Кажется,квалификатра volatile там и вовсе нет...
Но я бы не заметал непонятки под ковер, а постарался-бы все-таки разобраться до конца,
бо неизветно,не всплывут-ли они потом при модификации кода.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- AndreyVN   Опрос АЦП внутри прерывания   Dec 7 2013, 06:41
- - Abell   А Вы не обрабатывайте АЦП в прерывании, Вы обрабат...   Dec 7 2013, 08:03
|- - AndreyVN   Цитата(Abell @ Dec 7 2013, 11:03) А Вы не...   Dec 7 2013, 09:12
|- - Abell   Цитата(AndreyVN @ Dec 7 2013, 13:12) Ну т...   Dec 7 2013, 09:41
||- - AndreyVN   Цитата(Abell @ Dec 7 2013, 12:41) Ну пуст...   Dec 7 2013, 10:02
||- - stells   Цитата(AndreyVN @ Dec 7 2013, 14:02) А у ...   Dec 7 2013, 10:19
|- - Xenia   Цитата(AndreyVN @ Dec 7 2013, 13:12) Мне ...   Dec 7 2013, 17:15
|- - AndreyVN   Цитата(Xenia @ Dec 7 2013, 20:15) А вы ст...   Dec 7 2013, 18:59
- - stells   я сталкивался с неправильной обработкой АЦП в подп...   Dec 7 2013, 09:30
- - _Pasha   Мега8 недалеко ушла от 16-й, все работало и работа...   Dec 7 2013, 19:17
|- - AndreyVN   Цитата(_Pasha @ Dec 7 2013, 22:17) Мега8 ...   Dec 7 2013, 19:36
||- - AndreyVN   Цитата(WHALE @ Dec 8 2013, 23:26) ТС так ...   Dec 9 2013, 04:25
|- - demiurg_spb   Цитата(_Pasha @ Dec 8 2013, 15:52) Ну вот...   Dec 9 2013, 05:51
- - Сергей Борщ   Цитата(WHALE @ Dec 8 2013, 21:26) А он не...   Dec 9 2013, 14:38


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

 


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


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