Pull to refresh

Счетчик на микроконтроллере с точностью 2/3 микросекунды и переполнением в несколько суток. Ответ

Reading time3 min
Views1.6K
Этот пост является ответом на топик автора avn о программном таймере/счетчике в микроконтроллерах.
В своем посте автор рассказывает о программных счетчиках с приемлемыми точностью и временем переполнения, но не указывает на ограничения, которые вводят программные счетчики реализованные таким образом. Не привязываясь к архитектуре микроконтроллеров я постараюсь изложить другой алгоритм счета времени в доступной форме.


Постановка задачи

Преложенный avn вариант реализации счета времени имеет право на жизнь в небольших программах, когда основной задачей является счет времени. В реальной жизни на маломощных микроконтроллерах «иногда» приходится выполнять дифференциальные вычисления. Время счета математики может занимать от двух до нескольких десятков инкрементов программного счетчика. Кроме того, объемная фоновая задача счета математики прерывается запросами от периферии (АЦП, ЦАП, ШИМ, асинхронные и синхронные каналы связи).
Если учесть, что может понадобится вести программный счетчик с еще большим переполнением и принять во внимание, что при каждом заходе в таймер выполняется несколько десятков ассемблерных команд (сохранение стека, операции по икнрементированию большого таймера, восстановление стека), то можно увидеть — на основную задачу времени совсем не остается.

Что же делать?

В такой ситуации я поступаю следующим образом. Частоту переполнения аппаратного таймера выбираю из требований к ПО (точность привязки событий к времени, достаточная точность при вычислениях математики и запас по переполнению программного таймера). Приоритет прерывания делаю максимальным (если нет возможности использовать таймер с «авторелоадом»), а само прерывание минимально возможным. Т.е в прерывании произвожу инкремент переменной delta по разрядности равной разрядности микроконтроллера (для восьмибитных контроллеров это 1 байт). Таким образом нет необходимости дополнительно сохранять в стек регистры.
В основной программе объявляю глобальную переменную-копию программного счетчика — delta_. В главном цикле программы запрещаю все прерывания, делаю перепись значения из delta в delta_, обнуляю delta, разрешаю прерывания. Таким образом в глобальной переменной delta_ оказывается время выполнения предыдущего главного цикла программы. С это переменной можно производить дальнейшие операции: складывать с текущим временем, отсчитывать большие выдержки времени, учитывать при счете диффуров.

Какие же здесь плюсы?

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

А минусы?

В минусах остается ситуация, когда требования по точности привязки событий высоки, а время выполнения главного программного цикла велико. В этом случае программного счетчика delta может не хватить и придется увеличивать его разрядность и, следовательно, увеличивать время выполнения прерывания аппаратного таймера.
Несколько бОльший код программы.

Завершающие слова

Предложенный алгоритм счета времени мне пришлось использовать при разработке ПО, где точность привязки времени задали 1мс, необходимость счета выдержек времени от 25мс до нескольких минут, интегральные звенья с временем интегрирования от 1 секунды до 1 часа, постоянной времени дифференциальных звеньев от 1 секунды до 1 часа, а время выполнения главного цикла программы колебалось от 30 до 40 мс.

Благодарю за внимание.
Tags:
Hubs:
+5
Comments3

Articles