Я пытаюсь заставить работать простую процедуру прерывания на ATMega328P. К PD6 подключен светодиод, а к PB7 - встроенная кнопка. Светодиод должен нормально мигать до тех пор, пока кнопка не будет нажата, а затем загорится ровным светом в течение 1,5 с, прежде чем снова начнет мигать. Вот код:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
// Enable pull-ups and set pin directions
MCUCR |= (1<<PUD);
PORTD &= ~(1<<PORTD6);
DDRD |= (1<<DDD6);
PORTB |= (1<<PORTB7);
DDRB &= ~(1<<DDB7);
// Enable pin change interrupt
PCICR = 0x01;
PCMSK0 = 0x80;
sei();
while (1)
{
// Blink LED at standard rate
_delay_ms(500);
PORTD ^= (1<<PORTD6);
_delay_ms(500);
PORTD ^= (1<<PORTD6);
}
}
ISR(PCINT0_vect,ISR_BLOCK)
{
PORTD &= ~(1<<PORTD6);
_delay_ms(500);
PORTD |= (1<<PORTD6);
_delay_ms(1500);
PORTD &= ~(1<<PORTD6);
}
Прерывание срабатывает правильно, однако процедура ISR повторяется дважды. Я предполагаю, что это какая-то проблема с отскоком кнопки, но я не знаю, как с этим бороться. Я попытался ввести задержку 500 мс в начале, а также попытался очистить флаг прерывания смены вывода в ISR, чтобы он не запускался снова, но все еще работает. Заранее благодарю за любую помощь!
button_pressed
и завершил работу. Затем поставьтеif (button_pressed) {delay(1000); button_pressed=false;}
после того, как включите свет в основном цикле. Однако в целом встроенный код должен полностью избегать циклов задержки и заменять их проверками часов и / или прерываниями по таймеру. - person AShelly   schedule 02.11.2018