Объясните новичку по прерыванию INT0 в Atmega8, пожалуйста
Объясните новичку по прерыванию INT0 в Atmega8, пожалуйста
Добрый день!
Разрешил одно прерывание INT0 по фронту импульса. В прерывании взвожу флаг int0=1 и выхожу.
В цикле main сравниваю int0 с 1, если int0 == 1 то {int0=0; делаю вызов подпрограммы}
Беда в том, что пока после фронта импульса на ноге int0 держится 1, у меня эта подпрограмма всё время выполняется несколько раз. А ведь, по идее, прерывание уже не должно срабатывать, т.к. фронт уже прошёл, до следующего фронта. Или я неверно понимаю?
Разрешил одно прерывание INT0 по фронту импульса. В прерывании взвожу флаг int0=1 и выхожу.
В цикле main сравниваю int0 с 1, если int0 == 1 то {int0=0; делаю вызов подпрограммы}
Беда в том, что пока после фронта импульса на ноге int0 держится 1, у меня эта подпрограмма всё время выполняется несколько раз. А ведь, по идее, прерывание уже не должно срабатывать, т.к. фронт уже прошёл, до следующего фронта. Или я неверно понимаю?
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
Если я правильно понял Вашу мысль. То получается следующее.AonMaster писал(а):В прерывании взвожу флаг int0=1
-произошло событие внешнего прерывания, у вас установился флаг.
-т.к. у Вас прерывания разрешены, оно у Вас возникает (при этом контроллер автоматически сбрасывает флаг и запрещает все прерывания)
-Вы флаг принудительно зачем то устанавливаете
-контроллер выходит из прерывания и разрешает их. Глядь, а флаг опять установлен (Вы ж его установили сами), ну и обратно в обработчик и т.д.
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
Проблема в том что у атмеги невозможно вручную выставить флаг в регистре и тем самым сгенерировать IRQ. Так что ждём подробностей.
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
Точно ж, там же сброс единицей. Ждемс...
-
Novice user
- Мудрый кот
- Сообщения: 1704
- Зарегистрирован: Вт янв 05, 2016 10:14:25
- Откуда: поселок Мелеуз
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
а если стандартно?(сам новичок)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
подпрограмма
}
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
подпрограмма
}
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
Z_h_e писал(а):-произошло событие внешнего прерывания, у вас установился флаг..
Int0 - это не флаг внутренних регистров МК, это так я назвал переменную, которая вначале равна 0.
Вошло в прерывание - установилась переменная в 1, вышло из прерывания.
В цикле анализирую эту переменную, как только она стала равна 1 - выполняю подпрограмму.
Сбрасыванием в 0 пытался добиться того, чтоб больше до следующего начала импульса подпрограмма не выполнялась. А она всё равно выполняется.
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
У Вас реальное устройство или в симуляции?
Если реальное, то может оказаться что дребезг какой на входе.
Код то покажите?
Если реальное, то может оказаться что дребезг какой на входе.
Код то покажите?
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
Реальное.
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();
}
}
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, пожалуйс
Возможно, виноват дребезг, а возможно что-то ещё.
Я бы сделал так:
Я бы сделал так:
Код: Выделить всё
// объявил бы 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, пожалуйс
Дребезг, думаю, тут ни при чём, т.к. у меня импульсы на PORTC.5 возникают только при "1" на входе int0. Из чего я делаю вывод, что вопреки ожидаемому, МК после первого фронта и пока там держится 1, всё-таки отрабатывает это прерывание снова и снова. Вот и спрашивал, должно ли так быть 
- __Alexander
- Потрогал лапой паяльник
- Сообщения: 335
- Зарегистрирован: Вт сен 11, 2007 10:27:08
- Откуда: Киев
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
та кончено дребезг. сначала вызови функцию, а потом обнули флаг.
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
в чём разница? пробовал и так, кажись.
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
А что у Вас за источник импульсов для INT0? Попробуйте его отключить (источник), а вместо него подавать сигнал с другого порта. Даже скорее всего и подавать не надо, просто порт INT0 переключить на выход и его дергать, тоже наверное должны возникать прерывания.
- __Alexander
- Потрогал лапой паяльник
- Сообщения: 335
- Зарегистрирован: Вт сен 11, 2007 10:27:08
- Откуда: Киев
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
AonMaster писал(а):в чём разница? пробовал и так, кажись.
разница в том, что пока будет выполнятся функция, где 400мс задержа, то дребезг уже пройдет в любом случае, вот тогда и обнуляйте.
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
И где Ваш исходник?
Вот и я об этом же писал...__Alexander писал(а):пока будет выполнятся функция, где 400мс задержа, то дребезг уже пройдет в любом случае
-
Novice user
- Мудрый кот
- Сообщения: 1704
- Зарегистрирован: Вт янв 05, 2016 10:14:25
- Откуда: поселок Мелеуз
Re: Объясните новичку по прерыванию INT0 в Atmega8, пожалуйс
int0 = 0;
front();-поменяйте местами,что будет?
front();-поменяйте местами,что будет?
