sadr0b0t / arduino-timer-api

Cross-platform Arduino timer API
GNU Lesser General Public License v3.0
35 stars 18 forks source link

timer_stop_ISR не работает на AVR/Arduino #6

Closed sadr0b0t closed 6 years ago

sadr0b0t commented 6 years ago

timer_stop_ISR не работает на AVR/Arduino, таймер не останавливается. Что логично, т.к. метод по факту не реализован:

void timer_stop_ISR(int timer) {
    //disable use of the given timer
#if defined WIRING   // Wiring
    if(timer == _timer1) {
        #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
        TIMSK1 &= ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
        #else
        TIMSK &= ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
        #endif
        timerDetach(TIMER1OUTCOMPAREA_INT);
    } else if(timer == _timer3) {
        #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
        TIMSK3 &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
        #else
        ETIMSK &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
        #endif
        timerDetach(TIMER3OUTCOMPAREA_INT);
    }
#else
    //For arduino - in future: call here to a currently undefined function to reset the timer
#endif
}

Код взят из Servo.cpp, нужно реализовать самим https://github.com/arduino/Arduino/blob/ide-1.5.x/libraries/Servo/src/avr/Servo.cpp#L184

sadr0b0t commented 6 years ago

Готово дело. Работает на Arduino Leonardo (на ней есть только Timer1) https://github.com/sadr0b0t/arduino-timer-api/commit/e6dc816583370c544a7d7634706f69b46fd89882

Смысл - установить/снять бит в регистре TIMSKx

включить прерывание

        TIFR5 = _BV(OCF5A);     // clear any pending interrupts
        TIMSK5 = _BV(OCIE5A);   // enable the output compare interrupt

выключить прерывание

        TIMSK5 = ~_BV(OCIE5A); // disable output compare interrupt

Стоит ли еще сбрасывать TIFR5 не только перед включением, но и перед выключением - вопрос. В куске кода, который все-таки был в Sevro.cpp для Wiring TIFR5 не сбрасывался и мы не будем. Скорее всего выключить прерывание достаточно, чтобы старые вызовы не пришли из очереди, а при запуске таймера старую очередь имеет смысл чистить, например, в том случае, когда идет перенастройка еще при работающем таймере. В любом случае текущий вариант рабочий, ок.