millis и micros всегда возвращают 0 (или другую константу)

На Arduino Uno у меня есть примерно такой скетч:

void setup()
{
    // Генерируем некоторый ШИМ-сигнал на выводе 5, используя таймер 0.
    pinMode(5, OUTPUT);
    TCCR0A = 0b00110011;
    TCCR0B = 0b00001000;
    OCR0A = 0x80;
    OCR0B = 0x20;
    TIMSK0 = 0b00000100;

    Serial.begin(115200);
}
void loop()
{
    // Просто записываем результат миллис в терминал.
    unsigned long ms = millis();
    char s[100];
    sprintf(s, "%lu\r\n", ms);
    Serial.print(s);
}

Настройте таймер 0 для генерации ШИМ-сигнала, настройте последовательный порт, постоянно выводите результат millis() на терминал.

Числа, выведенные на консоль, не увеличиваются, как ожидалось, а остаются равными "0". Точно так же, если я использую micros, постоянно печатается «4».

Как это?

, 👍1


1 ответ


2

millis и micros, по-видимому, используют внутренний таймер 0. Использование этого таймера для генерации ШИМ-сигнала нарушает их способность работать должным образом. Решение состоит в том, чтобы либо использовать другой таймер для генерации сигнала ШИМ, либо использовать собственный эквивалент этих функций.

Почему в официальной документации Arduino не указано, что millis и micros занимают таймер 0?
Почему нет результатов Google, в которых упоминается таймер 0 при поиске «arduino Millis возвращает 0», «Arduino Millis Constant», «Arduino Millis не считает» и т.п.? (Есть результаты с одинаковыми симптомами, но по разным причинам.)
Кто знает.

,

PWM с AnalogWrite() и millis() работают вместе на Uno, если вы не меняете Timer0. каждый таймер ATmega обрабатывает пару контактов. Timer0 имеет 5 и 6 на Uno/Nano/Mini https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/#_notes_and_warnings, @Juraj

Вы должны использовать analogWrite() для генерации ШИМ и получать доступ к низкоуровневым периферийным устройствам только в том случае, если вы знаете, что делаете. Я согласен, что упоминание Таймера 0 в документе millis() было бы хорошо. Обратите внимание, что поиск в Google «millis timer 0» дает много релевантных результатов., @Edgar Bonet

Аналог @JurajWrite не позволяет изменять период (потому что это испортило бы скорость подсчета миллисекунд). Но спасибо за упоминание об этом; другие могут найти это полезным для этой цели., @Niko O

В 2014 году я написал библиотеку для использования Timer 2 в качестве замены millis()/micros(). Вы можете прочитать об этом на моем личном сайте здесь: https://www.electricrcaircraftguy.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html. Если вы используете это, вы можете использовать Таймер 0 для чего угодно. Конечно, Таймер 2 и Таймер 0 являются 8-битными таймерами с одинаковым уровнем функциональности, поэтому нет никакого реального преимущества в использовании одного над другим для синхронизации, но моя реализация имеет разрешение 0,5 мкс вместо разрешения 4 мкс (в 8 раз лучше) при стоимость более частого джиттера ~4~5us (в 8 раз чаще)., @Gabriel Staples

Что касается того, какой таймер что делает, вы должны иметь привычку просматривать исходный код, чтобы видеть, когда, как и почему аппаратные ресурсы, такие как таймеры и счетчики, захват ввода, сравнение вывода, UART, сторожевые таймеры, внешние прерывания, изменение контактов. используются прерывания и т.д. Только что пришло в голову:millis()/micros() — это таймер 0, библиотека сервоприводов — это таймер 1, библиотека тонов — это таймер 2, я думаю, и т. д., @Gabriel Staples

*Почему в официальной документации Arduino не указано, что миллисекунды и микросекунды занимают таймер 0?* - вероятно, одной из причин может быть то, что это будет варьироваться от процессора к процессору. Если вы начнете возиться с аппаратными регистрами, вы можете ожидать, что все будет вести себя не так, как описано в документации. Например, если вы измените регистры, относящиеся к последовательному выходу, то запись в Serial может не работать., @Nick Gammon

@NickGammon Это не помешало бы мне записать эту информацию для каждого контроллера. Arduino (компания) знает, какие у них процессоры на платах., @Niko O