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

 
 
> Опрос АЦП внутри прерывания
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 9 2013, 04:25
Сообщение #8


Знающий
****

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



Цитата(WHALE @ Dec 8 2013, 23:26) *
ТС так и не указал используемый компилятор.Но судя по приведенным кускам кода-это CV.
А он не такой резкий в оптимизации как тот-же ЯР и не выкидывает без предупреждения
не- volatile переменные в прерываниях.Кажется,квалификатра volatile там и вовсе нет...
Но я бы не заметал непонятки под ковер, а постарался-бы все-таки разобраться до конца,
бо неизветно,не всплывут-ли они потом при модификации кода.


Да, действительно, Code Vision (версию сейчас не назову), на модификатор volatile CV ошибки не выдает, но, возможно, никаких действий не предпринимает.
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
|- - 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 Текстовая версия Сейчас: 30th July 2025 - 23:47
Рейтинг@Mail.ru


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