Технический форум по робототехнике.
vastok » 20 мар 2011, 14:17
Компилирую для attiny45. В результате прерывание INT0 срабатывает сразу на старте, а мне этого не нужно. Помогите, пожалуйста разобраться.
- Код: Выделить всё • Развернуть
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/signal.h>
char pressed;
SIGNAL (__vector_defoult)
{
//Заглушка
}
//Простой код. При нажатии кнопки переключаем сигнал между двумя выходами.
//До нажатия кнопки все выходы должны молчать.
//Но не молчат, т.к. почему-то срабатывет прерывание сразу при старте.
SIGNAL (SIG_INTERRUPT0)
{
switch(pressed)
{
case 0:
{
PORTB = 0x01;
break;
};
case 1:
{
PORTB = 0x02;
break;
};
};
pressed= 1-pressed;
}
int main(void)
{
pressed = 0;//Нажата ли кнопка
DDRB = 0xFF;//Порт говорит на выход
PORTB = 0x00;//Гасим все лапки
GIMSK=0x40;//Разрешаем перерывание INT0 на проподание сигнала на входе INT0
sei();
while(1)//Зацикливаем
{
}
}
Идея такая: При старте все выходы молчат. При нажатии кнопки сигнал переключается между первым или вторым выходом. Стартую эмулятор и вижу, что первый выход уже горит. Как будто уже была нажата кнопка... Не пойму почему срабатывает прерывание при старте и как этого избежать.
dccharacter » 20 мар 2011, 16:51
не знаю, есть ли это на АВРах, но на ПИКах есть флаг прерывания. При входе в обработчик прерывания мы проверяем, кто был источником прерывания. Вы этого не делаете.
Дальше, в ПИКах при включении прерывания оно может сработать, поэтому флаг прерывания обнуляется, вы этого тоже не делаете.
Чтобы инвертировать флаг, можно использовать такую команду: pressed = ~pressed;
Опять же если есть на АВРАХ, то условие можно вообще не делать.
RB0 = pressed;
RB1 = !pressed;
А еще, наверное, можно поксорить: PORTB ^= 0x03;
KOS » 20 мар 2011, 17:01
У тебя изначально pressed =0;
я думаю он у тебя и зажигает диод.
vastok » 20 мар 2011, 17:25
KOS писал(а):У тебя изначально pressed =0;
я думаю он у тебя и зажигает диод.
Ну да. pressed = 0. Но почему вызывается прерывание? Оно должно быть вызвано только по кнопке, а оно у меня вызывается при старте.
Добавлено спустя 9 минут 40 секунд:dccharacter писал(а):не знаю, есть ли это на АВРах, но на ПИКах есть флаг прерывания. При входе в обработчик прерывания мы проверяем, кто был источником прерывания.
В АВРах этого можно не делать. От источника прерывания зависит вектор прерывания, а в ПИКах (на сколько я знаю) вектор всегда один.
dccharacter писал(а):Дальше, в ПИКах при включении прерывания оно может сработать, поэтому флаг прерывания обнуляется, вы этого тоже не делаете.
хм... Делается ли это в АВР? Если да то как?
dccharacter » 20 мар 2011, 17:35
All interrupts have a separate Interrupt Vector in the Interrupt Vector table. Жируете, ребята...
Добавлено спустя 6 минут 35 секунд:
Re: Помогите разобраться. Само срабатывает прерывание INT0 AVR.
When using the SEI instruction to enable interrupts, the instruction following SEI will be executed before any pending interrupts, as shown in this example.
Короче обнулите флаг прерывания сразу после sei.
vastok » 20 мар 2011, 18:37
dccharacter писал(а):When using the SEI instruction to enable interrupts, the instruction following SEI will be executed before any pending interrupts, as shown in this example.
Короче обнулите флаг прерывания сразу после sei.
Какие флаги? Здесь сказано: "Если Вы включаете флаг использование прерываний (SEI), то инструкция, которая следует за SEI будет выполнена до любого прерывания, как показано в примере..."
Я не понял какие флаги Вы имели введу?
Duhas » 20 мар 2011, 20:11
меня лично сразу свалило наповал это --> _defoult
boez » 21 мар 2011, 11:21
Чего-то я вообще не пойму, в чем вопрос. Прерывание INT0 срабатывает от низкого уровня. Ты ж своими же командами
- Код: Выделить всё • Развернуть
DDRB = 0xFF;//Порт говорит на выход
PORTB = 0x00;//Гасим все лапки
этот низкий уровень туда и выдал!!!
А вообще, если хочешь вешать на ногу кнопку и не спалить контроллер - эту ногу надо делать входом...
avr123.nm.ru » 21 мар 2011, 11:57
Еще лучше не жалеть резисторов на 300-600 Ом от ноги МК к чему либо.