У меня есть Atmega328p, и я хочу включить цифровой выход нажатием кнопки, а затем автоматически выключить его через 2 секунды.
Я знаю, как использовать аппаратное прерывание для кнопки, но какнастроить прерывание по таймеру для автоматического выключения цифрового выхода?
ОБНОВЛЕНИЕ:
Мне удалось выяснить это.Вот мое решение (показаны только соответствующие функции):
static inline void initTimer1(void) {
TCCR1B |= (1 << WGM12); // CTC Mode, immediate
TCCR1B |= (1 << CS10) | (1 << CS12); // Clock speed: 16 MHz / 1024, ~= 15.6 ticks per ms
}
void set_valve_on_time(uint16_t on_time) {
OCR1A = on_time; // set output compare register for valve on time
}
void open_valve(uint8_t state) {
if (state > 0) {
PORTD |= (1 << PIND6); //turn on PD6, open valve
PORTD &= ~(1 << PIND7); //turn off PD7, turn off close valve in case it was on
if (state == 2) {
TCNT1 = 0;
TIFR1 |= (1 << OCF1A); // clear output compare match flag
TIMSK1 |= (1 << OCIE1A); // enable output compare interrupt
}
}
else {
PORTD &= ~(1 << PIND6); //turn off PD6, stop opening valve
}
}
ISR(TIMER1_COMPA_vect) {
TIMSK1 &= ~(1 << OCIE1A); // disable output compare interrupt
open_valve(0); //turn off close valve output
}
Функция open_valve вызывается нажатием кнопки (не показано).Самым сложным моментом было выяснить, что мне нужно TIFR1 |= (1 << OCF1A)
, чтобы он работал правильно.Я до сих пор не совсем понимаю, почему, потому что я думал, что ISR должен был делать это автоматически.