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».
Как это?
@Niko O, 👍1
1 ответ
millis
и micros
, по-видимому, используют внутренний таймер 0. Использование этого таймера для генерации ШИМ-сигнала нарушает их способность работать должным образом.
Решение состоит в том, чтобы либо использовать другой таймер для генерации сигнала ШИМ, либо использовать собственный эквивалент этих функций.
Почему в официальной документации Arduino не указано, что millis
и micros
занимают таймер 0?
Почему нет результатов Google, в которых упоминается таймер 0 при поиске «arduino Millis возвращает 0», «Arduino Millis Constant», «Arduino Millis не считает» и т.п.? (Есть результаты с одинаковыми симптомами, но по разным причинам.)
Кто знает.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
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