Как отключить цифровой выход через 2 секунды с помощью таймера - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть 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 должен был делать это автоматически.

1 Ответ

0 голосов
/ 06 декабря 2018

вы должны примерно следовать этим шагам:

  • в вашей процедуре обработки кнопок установите таймер со следующими свойствами:
    • лучше всего использовать 16-битный таймер в режиме CTC (если выесть свободные таймеры)
    • установите прескалер так, чтобы таймер работал немного медленнее, чем значение сравнения:
      для частоты процессора 2 с и 10 МГц, я бы запустил его на прескалере 1/1024, так что переполнениепроизойдет (10.000.000 / 1024/65536) -> 1 переполнение за ~ 6,7 с (при 265 оно будет переполняться чаще, чем раз в 2 с)
    • установить верхнее значение ctc (см. описание выбранного вамирежим - конкретный регистр изменяется) до значения, которое достигается через 2 с: 10.000.000 / 1024 * 2 с -> 19531
  • реализуют ISR (см., какой из них будет правильнымв выбранном режиме CTC) и активируйте Interupt в регистре маски
    • в ISR установите свой выход и остановите таймер
  • Бонус: установите таймер, которыйон использует вывод сСравнивайте контакты для деактивации выхода.
    Тогда ISR вообще не требуется, просто установите для режима сравнения выходных данных значение 'clear on Match'

Если у вас нет свободного 16-битного таймера, я быпредлагаем использовать 1 таймер в режиме CTC для генерации (10) миллисекундной временной шкалы и реализовать логику подсчета времени в этой обработке ms-событий.

...