roboforum.ru

Технический форум по робототехнике.
Текущее время: 27 ноя 2024, 07:54

Часовой пояс: UTC + 4 часа




Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 12:49 
Не в сети

Зарегистрирован: 20 июн 2009, 23:06
Сообщения: 2
Откуда: Omsk
Пишу довольно большой проект. И столкнулся с проблемой. В программе используются два прерывания: при переполнении таймера0, и при завершении АЦП. Обработчик прерывания от tmr0 довольно длинный. В самом его начале запускается начало АЦП (ADSRA.6 = 1). Но атмега8 просто игнорирует прерывание от АЦП, в него она просто не залетает. В-общем, проблема свелась в следующему простому коду:
Код:
#include <mega8.h>
#include <delay.h>
#include <MyLCD.inc>

interrupt [TIM0_OVF] void timer0_ovf_isr(void);
interrupt [ADC_INT] void adc_isr(void);
void lcd_putnum(unsigned char num);
void main(void);

//======== TIMER0 INTERRUPT HANDLER ========//
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
  ADCSRA.6 = 1;
//  delay_ms(500);
}
//==== END OF TIMER0 INTERRUPT HANDLER =====//


//======== ADC INTERRUPT HANDLER ========//
interrupt [ADC_INT] void adc_isr(void)
{
  unsigned char adc_data;
  adc_data = ADCH;
  lcd_clear();
  lcd_putsf("ADC = ");
  lcd_putnum(adc_data);
  delay_ms(200);
}
//==== END OF ADC INTERRUPT HANDLER =====//


void lcd_putnum(unsigned char num)
{
unsigned char tmp1, tmp2;
tmp1 = num / 100;
tmp2 = ( num / 10 ) % 10;
if (tmp1)
  lcd_putchar(tmp1 + 48);
if ( ((!tmp2) && (tmp1)) ||(tmp2))
  lcd_putchar(tmp2 + 48);
lcd_putchar((num%100)%10 + 48);
}


void main(void)
{
DDRC  = 0b00110110;
PORTC = 0b00111110;

ADMUX  = 0b01100000;
ADCSRA = 0x8B;

TCCR0=0x03;
TIMSK=0x01;
ACSR=0x80;

lcd_init();
lcd_putsf("TEST");
delay_ms(200);
ADCSRA.6 = 1;

#asm("sei");

while (1)
  {
  }
}

При комментировании delay(500) в прерывании от таймера, прерывание от АЦП СРАБАТЫВАЕТ. При внесении же delay_ms (500), т.е. "удлинения по времени" прерывания от таймера, прерывание от АЦП игнорируется. В чем может быть дело?
P.S. Контроль данных АЦП выводится на ЛСД дисплей (100% рабочий).
P.S.S. В протеусе все эмулится нормально.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:09 
Не в сети
Аватара пользователя

Зарегистрирован: 23 окт 2007, 22:03
Сообщения: 3037
Откуда: Москва
прог. языки: С
ФИО: Евгений Яковец
Использовать delay в теле прерывания не есть гуд.
Да потом delay_ms(500) - это же 0,5 секунды :shock:

_________________
- Этот человек - не человек! это робот!
- Как? уже делают?!
- Делают!!!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:12 
Не в сети
Аватара пользователя

Зарегистрирован: 20 мар 2009, 12:45
Сообщения: 682
Откуда: Украина, Одесса
ФИО: Сергей
зачем в main запуск АЦП (ADCSRA.6 = 1;), ведь он запускается таймером
а таймер тактируется от внешнего источника?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:17 
Не в сети
Аватара пользователя

Зарегистрирован: 23 окт 2007, 22:03
Сообщения: 3037
Откуда: Москва
прог. языки: С
ФИО: Евгений Яковец
TCCR0=0x03; - clk /64 (From prescaler)

_________________
- Этот человек - не человек! это робот!
- Как? уже делают?!
- Делают!!!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:32 
Не в сети
Аватара пользователя

Зарегистрирован: 20 мар 2009, 12:45
Сообщения: 682
Откуда: Украина, Одесса
ФИО: Сергей
а блин... точно...
пардон, надо кофе выпить :)

Добавлено спустя 6 минут 16 секунд:
Какая тактовая у МК?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:43 
Не в сети
отсылающий читать курс
Аватара пользователя

Зарегистрирован: 06 ноя 2005, 04:18
Сообщения: 14195
Откуда: Москва
C-r-o-w писал(а):
атмега8 просто игнорирует прерывание от АЦП, в него она просто не залетает.


Механизм прерываний AVR ATmega описан на страничке 3 учебного курса по AVR - http://avr123.nm.ru/03.htm

Там сказано что AVR не помнит порядок появления накопленых прерываний (порядок установки их флагов) и поэтому обрабатывает их по порядку расположения в таблице прерываний в даташите.

Т.е. у вас перед флагом АЦП всегда есть флаг таймера (если он устанавливается за время большой паузы) - его и обрабатывает мега8.

Там же КРУПНО написано:

Делайте функции обработчики прерывания как можно короче !
Не засиживайтесь в них ...


Нужно тщательно продумывать алгоритм программы чтоб успевать обрабатывать все прерывания - т.е. не пропускать нужные события
и обрабатывать их вовремя.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 13:52 
Не в сети
Аватара пользователя

Зарегистрирован: 23 окт 2007, 22:03
Сообщения: 3037
Откуда: Москва
прог. языки: С
ФИО: Евгений Яковец
avr123.nm.ru писал(а):
Т.е. у вас перед флагом АЦП всегда есть флаг таймера - его и обрабатывает мега8.

Позвольте несогласиться.
Топикстартер пишет:
C-r-o-w писал(а):
При комментировании delay(500) в прерывании от таймера, прерывание от АЦП СРАБАТЫВАЕТ.

Значит дело не во флагах, а в delay-е. :)

_________________
- Этот человек - не человек! это робот!
- Как? уже делают?!
- Делают!!!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 14:12 
Не в сети
Аватара пользователя

Зарегистрирован: 20 мар 2009, 12:45
Сообщения: 682
Откуда: Украина, Одесса
ФИО: Сергей
что такое delay(500), это сколько???
написали же, русским языком
Цитата:
Там сказано что AVR не помнит порядок появления накопленых прерываний (порядок установки их флагов) и поэтому обрабатывает их по порядку расположения в таблице прерываний в даташите.

Т.е. у вас перед флагом АЦП всегда есть флаг таймера (если он устанавливается за время большой паузы) - его и обрабатывает мега8.

т.е. таймер всегда находится в своем прерывании, т.к. за 0,5сек оно точно наступит


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 14:28 
Не в сети
отсылающий читать курс
Аватара пользователя

Зарегистрирован: 06 ноя 2005, 04:18
Сообщения: 14195
Откуда: Москва
yak-40 писал(а):
avr123.nm.ru Позвольте несогласиться.
Топикстартер пишет:
C-r-o-w писал(а):
При комментировании delay(500) в прерывании от таймера, прерывание от АЦП СРАБАТЫВАЕТ.

Значит дело не во флагах, а в delay-е. :)


Я об этом и написал. Внимательно перечитайте если интересно.

Добавлено спустя 2 минуты 31 секунду:
SERGEY_M писал(а):
т.е. таймер всегда находится в своем прерывании, т.к. за 0,5сек оно точно наступит

Нет. Прога почти всегда находится в прерывании от таймера. Таймер там не находится :)

Когда прога выходит из этого прерывания то обнаруживает два флага - от таймера (который внось возник за время длинной паузы) и от АЦП и обрабоатывает ПЕРВЫЙ их них по списку в даташите.

Если в конце прерывания сделать очистку флага от таймера то вероятно прога сможет попасть в прерывание от АЦП.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 14:42 
Не в сети
Аватара пользователя

Зарегистрирован: 20 мар 2009, 12:45
Сообщения: 682
Откуда: Украина, Одесса
ФИО: Сергей
пардон, ну не так выразился :oops:
именно это я и хотел про таймер сказать


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 23 июн 2009, 20:37 
Не в сети

Зарегистрирован: 20 июн 2009, 23:06
Сообщения: 2
Откуда: Omsk
avr123.nm.ru писал(а):
Если в конце прерывания сделать очистку флага от таймера то вероятно прога сможет попасть в прерывание от АЦП.

Да, идеи теперь две: либо переносить весь обработчик таймера в мэйн и сделать там свой "переполнитель" таймера, либо в прерывании от таймера тормозить сам таймер и обнулять его... Наверно лучше первое. Спасибо всем за внимание!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 24 июн 2009, 00:51 
Не в сети

Зарегистрирован: 27 авг 2008, 10:45
Сообщения: 1981
Откуда: Харьков
прог. языки: С/С++
Однозначно лучше. Много видел всякого, но delay(500) в обработчике - это жесть :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 24 июн 2009, 22:26 
Не в сети

Зарегистрирован: 03 июн 2009, 21:16
Сообщения: 50
Откуда: пос. Актюбинский
Skype: ffaanniiss777
Может из-за

Обратите внимание, что при выполнении команды "чтение-модификация-запись" с регистром ADCSRA ожидаемое прерывание может быть отключено.
http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/12.htm

И таймер 0 здесь вроде только 1-раз срабатывает.
А если так попробовать
Код:
#include <mega8.h>
#include <delay.h>
#include <MyLCD.inc>

interrupt [TIM0_OVF] void timer0_ovf_isr(void);
interrupt [ADC_INT] void adc_isr(void);
void lcd_putnum(unsigned char num);
void main(void);

//======== TIMER0 INTERRUPT HANDLER ========//
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0 = 0x??;
ADCSRA = 0xCB;

//  delay_ms(500);
}
//==== END OF TIMER0 INTERRUPT HANDLER =====//


//======== ADC INTERRUPT HANDLER ========//
interrupt [ADC_INT] void adc_isr(void)
{
  unsigned char adc_data;
ADCSRA=0x00;
  adc_data = ADCH;
  lcd_clear();
  lcd_putsf("ADC = ");
  lcd_putnum(adc_data);
  delay_ms(200);
}
//==== END OF ADC INTERRUPT HANDLER =====//


void lcd_putnum(unsigned char num)
{
unsigned char tmp1, tmp2;
tmp1 = num / 100;
tmp2 = ( num / 10 ) % 10;
if (tmp1)
  lcd_putchar(tmp1 + 48);
if ( ((!tmp2) && (tmp1)) ||(tmp2))
  lcd_putchar(tmp2 + 48);
lcd_putchar((num%100)%10 + 48);
}


void main(void)
{
DDRC  = 0b00110110;
PORTC = 0b00111110;

ADCSRA=0x00;
ADMUX  = 0b01100000;
ACSR=0x80;


TCCR0=0x00;
TCNT0 = 0x??;
TCCR0=0x03;
TIMSK=0x01;


lcd_init();
lcd_putsf("TEST");
delay_ms(200);


#asm("sei");

while (1)
  {
  }
}
?


Последний раз редактировалось USER777 24 июн 2009, 22:30, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 24 июн 2009, 22:28 
Не в сети
отсылающий читать курс
Аватара пользователя

Зарегистрирован: 06 ноя 2005, 04:18
Сообщения: 14195
Откуда: Москва
А у вас есть "чтение-модификация-запись" с регистром ADCSRA ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Прерывание от АЦП в ATMEGA8 не срабатывает
СообщениеДобавлено: 25 июн 2009, 18:01 
Не в сети
Аватара пользователя

Зарегистрирован: 15 сен 2007, 13:03
Сообщения: 6338
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович
ADCSRA = 0xCB;

а это кто?

_________________
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 4 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 20


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
phpBB SEO