Этот пост является ответом на тема автор avn о программном таймере/счетчике в микроконтроллерах.
В своем посте автор говорит о программных счетчиках с приемлемой точностью и временем переполнения, но не указывает на ограничения, которые вводят реализованные таким образом программные счетчики.
Не привязываясь к архитектуре микроконтроллера, попытаюсь в доступной форме изложить еще один алгоритм отсчета времени.
Постановка задачи
Реализация подсчета времени, предложенная avn, имеет право на жизнь в небольших программах, когда основной задачей является подсчет времени.В реальной жизни маломощным микроконтроллерам «иногда» приходится выполнять дифференциальные вычисления.
Время математического расчета может занимать от двух до нескольких десятков приращений программного счетчика.
Кроме того, объемная фоновая задача по математическим расчетам прерывается запросами от периферии (АЦП, ЦАП, ШИМ, асинхронные и синхронные каналы связи).
Если принять во внимание, что может потребоваться ведение счетчика программ с еще большим переполнением и учесть, что при каждом входе в таймер выполняется несколько десятков ассемблерных инструкций (сохранение стека, операции по приращению большого таймера, восстановление стека), то мы видим, что на основную задачу времени не осталось.
Что делать?
В такой ситуации я поступаю следующим образом.Частоту переполнения аппаратного таймера я выбираю исходя из требований программного обеспечения (точность синхронизации событий, достаточная точность математических расчетов и запас по переполнению программного таймера).
Приоритет прерывания ставлю максимальным (если нет возможности использовать таймер с «автозагрузкой»), а само прерывание — минимально возможным.
То есть в прерывании я увеличиваю переменную дельта ширина равна ширине микроконтроллера (для восьмибитных контроллеров это 1 байт).
Таким образом, нет необходимости дополнительно хранить регистры в стеке.
В основной программе я объявляю глобальную переменную, являющуюся копией счетчика программы — дельта_ .
В основном цикле программы отключаю все прерывания, переписываю значение из дельта В дельта_ , я перезагружаю дельта , включаю прерывания.
Таким образом, в глобальной переменной дельта_ оказывается временем выполнения предыдущего основного цикла программы.
С этой переменной можно производить дальнейшие операции: складывать с текущим временем, считать большие задержки и учитывать их при подсчете диффузий.
Какие здесь преимущества?
Несомненным преимуществом является скорость выполнения прерывания по аппаратному таймеру, а значит, и возможность установить несколько большую частоту прерываний.Отсутствие ошибок накопления при подсчете времени.
Независимость от времени выполнения основной программы и периферийных прерываний.
А что насчет минусов?
Минусом является ситуация, когда требования к точности привязки событий высоки, а время выполнения основного программного цикла велико.В этом случае дельты программного счетчика может оказаться недостаточно и придется увеличить его разрядность и, следовательно, увеличить время выполнения прерывания аппаратного таймера.
Несколько больший программный код.
Заключительные слова
Предложенный алгоритм расчета времени мне пришлось использовать при разработке программного обеспечения, где точность привязки времени устанавливалась до 1 мс, необходимость расчета временных задержек от 25 мс до нескольких минут, интегральные звенья со временем интегрирования от 1 секунды до 1 часа., постоянная времени дифференциальных звеньев от 1 секунды до 1 часа, а время выполнения основного цикла программы составляло от 30 до 40 мс.
Спасибо за внимание.
Теги: #mcu #avr #pic #Chulan #timers #i51
-
Гигабайт Ep45-Ud3R
19 Oct, 24 -
Принципы Дизайна Веб-Сайта
19 Oct, 24 -
Эффект Спирито В Полевых Транзисторах
19 Oct, 24 -
Умные Цели
19 Oct, 24