Контейнерная программа Arduino Timer0

Как описано здесь https://learn.adafruit.com/multi-tasking-the-arduino-part- 2/таймеры

Я использую таймер 0, чтобы получить собственный таймер с разрешением в миллисекундах.

Он настроен следующим образом:

void setup (void)
{
    ...
    cli();
    OCR0A  = 0xAB;
    TIMSK0 |= (1 << OCIE0A);
    sei();
    ...
}

Значение 0xAB выбирается случайно и не должно влиять на поведение.

Обработчик прерывания выглядит следующим образом:

ISR(TIMER0_COMPA_vect)
{
    if (myTimer != 0)
        myTimer--;
    return;
}

Это работает просто нормально, но при более внимательном рассмотрении фактических значений времени с помощью millis() я обнаружил, что значения таймера, заданные этим ISR, примерно на 2-3% больше, чем нужно.

Согласно сайту adafruit.com, этот метод должен точно следовать встроенному в Arduino таймеру millis(). В моей программе нет других активных прерываний. Есть некоторые выходные данные Serial.print(), может быть, они влияют на время? Решение, которое я нашел, выглядит так:

ISR(TIMER0_COMPA_vect)
{
    static unsigned long timeLast;

    unsigned long timeNow = millis();
    uint8_t timeDiff = (uint8_t)(timeNow - timeLast);
    timeLast = timeNow;

    if (myTimer != 0)
        myTimer -= timeDiff;

    return;
}

Вместо простого уменьшения значения таймера значение таймера уменьшается на фактическое время, прошедшее с момента последнего вызова ISR.

При этом мой таймер точно следует за миллисом(). Но почему первый подход не дает точного времени? По-видимому, бывают случаи, когда время между вызовами ISR составляет не 1 мс, а 2 мс.

, 👍1

Обсуждение

Означает ли это, что millis() уже возвращает исправленное значение, т.е. millis() дает фактическое количество миллисекунд, а не 1,024 мс?, @Sören


1 ответ


3

Ядро Arduino настраивает таймер 0 на период 1024 мкс. Твой Затем ISR будет вызываться через очень регулярные промежутки времени, и это хорошее место. иметь код, связанный с синхронизацией. Просто нужно помнить, что устройство времени составляет не одну миллисекунду, а 1,024 мс.

Если вас беспокоит этот «странный» модуль, вы можете сделать следующее: Ардуино ISR по времени: отслеживает задержку относительно 1 мс период, вы получаете. Когда вы заметите, что опаздываете на 1 мс, посчитайте одна дополнительная миллисекунда.

,