Страница 1 из 1

Объясните новичку по прерыванию INT0 в Atmega8, пожалуйста

Добавлено: Чт май 05, 2016 19:07:47
AonMaster
Добрый день!

Разрешил одно прерывание INT0 по фронту импульса. В прерывании взвожу флаг int0=1 и выхожу.
В цикле main сравниваю int0 с 1, если int0 == 1 то {int0=0; делаю вызов подпрограммы}

Беда в том, что пока после фронта импульса на ноге int0 держится 1, у меня эта подпрограмма всё время выполняется несколько раз. А ведь, по идее, прерывание уже не должно срабатывать, т.к. фронт уже прошёл, до следующего фронта. Или я неверно понимаю?

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 19:22:12
Z_h_e
AonMaster писал(а):В прерывании взвожу флаг int0=1
Если я правильно понял Вашу мысль. То получается следующее.
-произошло событие внешнего прерывания, у вас установился флаг.
-т.к. у Вас прерывания разрешены, оно у Вас возникает (при этом контроллер автоматически сбрасывает флаг и запрещает все прерывания)
-Вы флаг принудительно зачем то устанавливаете
-контроллер выходит из прерывания и разрешает их. Глядь, а флаг опять установлен (Вы ж его установили сами), ну и обратно в обработчик и т.д.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 19:42:51
uk8amk
Проблема в том что у атмеги невозможно вручную выставить флаг в регистре и тем самым сгенерировать IRQ. Так что ждём подробностей.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 19:52:22
Z_h_e
Точно ж, там же сброс единицей. Ждемс...

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 19:56:43
Novice user
а если стандартно?(сам новичок)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
подпрограмма
}

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 20:03:07
AonMaster
Z_h_e писал(а):-произошло событие внешнего прерывания, у вас установился флаг..
Int0 - это не флаг внутренних регистров МК, это так я назвал переменную, которая вначале равна 0.

Вошло в прерывание - установилась переменная в 1, вышло из прерывания.
В цикле анализирую эту переменную, как только она стала равна 1 - выполняю подпрограмму.
Сбрасыванием в 0 пытался добиться того, чтоб больше до следующего начала импульса подпрограмма не выполнялась. А она всё равно выполняется.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 20:05:27
Z_h_e
У Вас реальное устройство или в симуляции?
Если реальное, то может оказаться что дребезг какой на входе.
Код то покажите?

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Чт май 05, 2016 20:12:12
AonMaster
Реальное.

int drob,drob1, int0=0, done = 0;

interrupt [EXT_INT0] void ext_int0_isr(void)
{
int0 = 1;
}

void front() {
PORTC.5=0;
delay_ms(200);
PORTC.5=1;
delay_ms(200);
}

void main(void)
{

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
GICR|=0x40;
MCUCR=0x03;
//MCUCR=0x00;
GIFR=0x40;
ACSR=0x80;

#asm("sei")

while(1) {

if ((int0 == 1) && (done < 1000) ) {
int0 = 0;
front();
}

}

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 09:53:19
Барсик
Возможно, виноват дребезг, а возможно что-то ещё.
Я бы сделал так:

Код: Выделить всё

// объявил бы int0 как volatile
volatile unsigned char int0 = 0;

// внутри обработчика прерывания, запретил бы то самое прерывание

// в main объявил бы локальную переменную
unsigned char tmp_int0 = 0;

// поскольку боюсь неатомарных операций до дрожи в коленках, считывал флаг так:
#asm("cli")
tmp_int0 = int0;
#asm("sei")
// потом бы уже неспеша работал с переменной tmp_int0

// после того, как импульс сгенерирован, очистил бы флаг прерывания. И не int0, а именно бит в регистре,
// который за это прерывание отвечает
// после чего разрешил бы прерывание опять
// и установил переменную - флаг

#asm("cli")
int0 = 0;
#asm("sei")

// таким образом, прерывания не произойдёт, пока формируется импульс.
// при формировании импульса такие задержки, что дребезг влиять не будет

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 13:31:55
AonMaster
Дребезг, думаю, тут ни при чём, т.к. у меня импульсы на PORTC.5 возникают только при "1" на входе int0. Из чего я делаю вывод, что вопреки ожидаемому, МК после первого фронта и пока там держится 1, всё-таки отрабатывает это прерывание снова и снова. Вот и спрашивал, должно ли так быть :-(

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 13:37:02
__Alexander
та кончено дребезг. сначала вызови функцию, а потом обнули флаг.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 14:07:23
AonMaster
в чём разница? пробовал и так, кажись.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 14:22:35
Z_h_e
А что у Вас за источник импульсов для INT0? Попробуйте его отключить (источник), а вместо него подавать сигнал с другого порта. Даже скорее всего и подавать не надо, просто порт INT0 переключить на выход и его дергать, тоже наверное должны возникать прерывания.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 14:37:32
__Alexander
AonMaster писал(а):в чём разница? пробовал и так, кажись.
разница в том, что пока будет выполнятся функция, где 400мс задержа, то дребезг уже пройдет в любом случае, вот тогда и обнуляйте.

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 14:43:45
Барсик
И где Ваш исходник?
__Alexander писал(а):пока будет выполнятся функция, где 400мс задержа, то дребезг уже пройдет в любом случае
Вот и я об этом же писал...

Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс

Добавлено: Пт май 06, 2016 18:21:21
Novice user
int0 = 0;
front();-поменяйте местами,что будет?