delayMicroseconds и время выполнения микросекунд необъяснимо
Я только что поэкспериментировал с точностью синхронизации моего Arduino Uno R3, используя этот код:
unsigned long beginTime;
unsigned long endTime;
void setup() {
Serial.begin(9600); // открываем последовательный порт
}
void loop() {
beginTime = micros();
delayMicroseconds(200);
endTime = micros();
delay(500);
Serial.println(endTime-beginTime);
delay(500);
}
Результаты, которые я получил (просто выдержка):
200
204
200
200
204
204
204
200
212
208
212
204
204
Я пытался понять это поведение, прочитайте эту ссылку Могу ли я сделать delayMicroseconds более точным?.
Из-за времени микросекунд
(4 мкс) я понимаю значения между 200 и 208. Но почему я иногда получаю значения 212 микросекунд? Я любопытно, так как я купил Arduino из-за программирования на «голом железе» и ограниченного времени выполнения.
@Michael S, 👍-1
Обсуждение1 ответ
Лучший ответ:
Ядро Arduino использует аппаратный Timer0 с его ISR (процедурой обслуживания прерываний) для хронометража. В то время как delayMicroseconds()
напрямую использует значение аппаратного таймера, delay()
и millis()
обрабатываются ISR. Он будет вызываться регулярно.
Если ISR выполняется во время вашего измерения, то время выполнения ISR будет добавляться ко времени выполнения вашего измеренного кода. Таким образом, вы иногда получаете более высокий счет.
Чтобы предотвратить это, вы можете либо деактивировать все прерывания (через noInterrupts()
), либо деактивировать конкретное прерывание, либо остановив Timer0:
TCCR0B &= ~( (1 << CS02) | (1 << CS01) | (1 << CS00) );
или запустив таймер, но отключив его прерывания:
TIMSK0 = 0;
Подробности см. в техническом описании Atmega328p. , который является микроконтроллером Arduino Uno.
- Использовать timer0, не влияя на millis() и micros().
- Arduino Мигает двумя светодиодами без задержки (количество повторений)
- Аппаратное прерывание срабатывает случайным образом
- _delay_ms() работает намного медленнее, чем ожидалось (в 6 раз) на tinyAVR 0/1 (ATTiny1604)
- Как рандомизировать задержку в коде шагового двигателя Arduino?
- Запуск двигателя постоянного тока в течение заданного промежутка времени
- Как заставить ЖК-экран прокручивать текст , позволяя вводить кнопки?
- Как запустить 4 светодиода последовательно на основе кнопочного входа?
Возможно, во время измерения иногда возникают прерывания. Это увеличило бы фактическое время выполнения., @chrisl
попробуйте добавить Serial.flush(), чтобы дождаться завершения Serial, @Juraj
@Juraj: Спасибо за предложение. Я попробовал (т.е. добавил
Serial.flush();
послеprintln
, но это не сработало., @Michael S@chrisl: Спасибо, я добавил
noInterrupts();
перед первымmicros();
иinterrupts();
послеendTime = micros();
. Я получил стабильные значения, 200 или 204 микросекунды, что и ожидалось :). Знаете ли вы, какие прерывания могут быть вызваны при выполнении такой простой программы? Я думал, чтоSerial.flush();
может остановить любое возможное прерывание, но это не так.., @Michael SЯдро Arduino использует прерывание таймера для отсчета времени., @Edgar Bonet