|
Опрос АЦП внутри прерывания |
|
|
|
Dec 7 2013, 06:41
|
Знающий
   
Группа: Свой
Сообщений: 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;
|
|
|
|
|
 |
Ответов
|
Dec 8 2013, 00:31
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 8 2013, 06:22
|
Знающий
   
Группа: Свой
Сообщений: 754
Регистрация: 29-06-06
Из: Volgograd
Пользователь №: 18 458

|
Цитата А где вы их проверяете? В этом же прерывании или в основном цикле? Если в основном цикле, то как объявлена переменная VADC? Я контролирую не VADC, а непосредственно с1, с2, чтобы свести к минимуму возможные причины ошибок в т.ч. присвоения, преобразования типов и т.п.. VADC тоже выводится на экран после мат. обработки, но это сейчас не интересно. Вывод на LCD и в основном цикле пробовал и прямо в обработчике пробовал. Переменные тоже пробовал объявлять глобальными и локальными, ситуация не меняется. Цитата Вы только не забывайте, что это 13-14 тактов частоты АЦП, в вашем случае это 13...14 * 128 = 1664 или 1792 тактов ядра. Вы хорошо подумали, прежде чем засунуть такое ожидание в обработчик прерывания? Общего быстродействия хватает, тем более, что сейчас ловлю готовность АЦП в прерывании (см. выше). Цитата Ой. Делайте VADC = ADC; и не морочьте себе голову. Любой компилятор для AVR знает, в каком порядке надо читать двухбайтные регистры. Когда код заработает так и сделаю, а сейчас, предпочитаю видеть каждый байт как он есть. Цитата В своем листинге. Внимательно смотреть, что сгенерил компилятор и думать - где вы могли неправильно объяснить ему свою задумку. Чудес не бывает. Ой, Спасибо! Однако, Вы не сказали, удавалось лично Вам опрашивать АЦП в обработчике прерываний таймера?
|
|
|
|
|
Dec 8 2013, 08:57
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 8 2013, 09:17
|
Знающий
   
Группа: Свой
Сообщений: 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 хранятся в регистрах, но успешно сохраняются и восстанавливаются через стек. К сожалению, так и не понял, что было. Сейчас вернул почти весь код на место, все работает, возвращаться к обработке АЦП "внутри таймера" уже нет смысла.
|
|
|
|
Сообщений в этой теме
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     WHALE Цитата(_Pasha @ Dec 8 2013, 15:52) Ну вот... Dec 8 2013, 19:26      AndreyVN Цитата(WHALE @ Dec 8 2013, 23:26) ТС так ... Dec 9 2013, 04:25 Сергей Борщ Цитата(WHALE @ Dec 8 2013, 21:26) А он не... Dec 9 2013, 14:38
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|