Технический форум по робототехнике.
kyc0k » 03 июл 2013, 19:38
Всем доброго времени суток. Начал впитывать про внешние прерывания МК и после написание короткой программы и запуска её протеусе сразу возникли недопонимания.
Ниже представлен код:
- Код: Выделить всё • Развернуть
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
ISR(INT0_vect){
PORTB = 0b00000010;
_delay_ms(200);
PORTB = 0b00000000;
_delay_ms(200);
}
void init_ports(void)
{
DDRB = 0b00000011;
PORTB = 0b00000000;
DDRA = 0b00000001;
PORTA = 0b00000001;
DDRD=0b00000000;
PORTD=0b00000000;
}
void init_interrupt(void)
{
GICR = 0b01000000;
MCUCR = 0b00000011;
}
void led_manager(void)
{
while (1)
{
PORTB = 0b00000001;
_delay_ms(700);
PORTB = 0b00000000;
_delay_ms(700);
}
}
int main(void)
{
init_ports();
init_interrupt();
sei();
while(1)
{
led_manager();
//TODO:: Please write your application code
}
}
В протеусе это выглядет следующим образом:
К ножкам PB0 и PB1 анодами напрямую подключены светодиоды. Через кнопку падаётся напряжение на ножку PD2(INT0). Так вот. Когда запускаю симуляцию с начало кратковременно загорается светодиод на PB1, а потом по циклу функции начинает led_manager(); мигать светодиод на PB0. При нажатии на кнопку светодиод на PD2 так же кратковременно загорается и в этот момент СД на PB0 гаснет как и должно быть. Но остаётся два вопроса. Почему в самом начале после запуска симуляции выполняется процедура прерывания и почему после первого раза как нажал на кнопку она больше не выполняется?
RoboHobbyRu » 03 июл 2013, 23:17
У тебя подтяжка на ноге INT0 есть?
Dmitry__ » 03 июл 2013, 23:36
А это нормально и в прерывании и в основной программе использовать _delay_ms ???
kyc0k » 04 июл 2013, 01:51
Внешний подтягивающий резистор я не ставил на ногу - от кнопки сразу на вывод идёт линия. Событие естественно на возрастание стоит. А что такого если в прерывании использовать delay? Вроде как не запрещено или я чего-то может не знаю?
Duhas » 04 июл 2013, 10:25
сам смысл прерываний состоит в быстрой обработке внешних событий. пока у вас программа простая все ок. далее задержки в прерываниях начнут вам мешать.
в принципе можно просто разрешить прерывания внутри прерывания, если основной цикл пустой.
Dmitry__ » 04 июл 2013, 17:47
kyc0k писал(а): А что такого если в прерывании использовать delay? Вроде как не запрещено или я чего-то может не знаю?
Ну, надо посмотреть на листинг после компилятора. _delay_ms - одна функция и для прерывания и для основной программы. Например выполняется _delay_ms в основной программе, происходит прерывание и затираются все переменные этой функции, после выход из прерывания - хз какие данные в переменных _delay_ms для основной программы. А может компилятор умный и сохранит все переменные. Ну и конечно в прерываниях нет места задержкам. Быстро обработал событие кнопки, выставил нужные флаги для основной программы и убежал из прерывания.
kyc0k » 05 июл 2013, 03:26
Duhas писал(а): Ну и конечно в прерываниях нет места задержкам. Быстро обработал событие кнопки, выставил нужные флаги для основной программы и убежал из прерывания.
Кстати верное подмечено. Уберу задержку в прерывании. Создам некую переменную и по событию прерывания буду менять её значение, а в основном цикле уже с помощью if разбирать, что делать, а что нет. А после окончания процедуры прерывания МК начнёт работу с места в цикле функции main на котором остановился или цикл по-новой побежит?
RoboHobbyRu » 05 июл 2013, 05:19
kyc0k писал(а):А после окончания процедуры прерывания МК начнёт работу с места в цикле функции main на котором остановился ...?
по сути да (применительно к языку более высокого уровня чем ассемблер).
Формально это звучит так:
прерывание происходит только по завершению текущей машинной команды в основном коде, а возврат из прерывания выполняется к следующей машинной команде.
kyc0k » 10 июл 2013, 13:36
С работой прерывания разобрался. Что бы прерывание срабатывало каждый раз по нажатию кнопки, надо было параллельно кнопки подключить кондер от дребезга и подтянуть на 10кОм резистор к земле, что бы тот в свою очередь разряжал кондер. И всё в протеусе всё работает.