Когда таймер переполняется, процессор не сразу уходит в обработку прерывания. Сначала он должен завершить текущую команду. В AVR на это уходит до трех тактов в зависимости от текущей команды и момента возникновения прерывания. Мне видится три пути обхода этой проблемы:
Тривиальный способ, который подходит только для очень простых задач - расчитать всю программу по тактам. Тогда прерывание вообще не нужно.
Более "правильный" - загнать процессор в SLEEP. Если после этого возникнет прерывание от таймера, процессор сразу же начнет его выполнять. Проблема в том, чтобы гарантированно уходить в SLEEP _перед_ приходом прерывания. Этот способ удобно использовать, когда "фоновую" задачу можно порезать на заведомо быстрые кусочки, или "фоновая" задача сама привязана к таймеру.
Ну и наконец есть способ прочитать значение таймера внутри процедуры обработки, определить сколько времени прошло с момента переполнения и скомпенсировать ошибку. Это наиболее удобный способ, так как он позволяет не курочить ВСЮ программу, чтобы привязать ее к таймеру.
В результате экспериментов родилась последовательность команд, приведенная чуть ниже.
Обратите внимание на использование команд "SBRC" и "SBRS". Какую из них когда использовать зависит от места расположения этих команд в обработчике прерывания. Так что в вашем проекте возможно понадобится другая комбинация команд "SBRC" и "SBRS".
Еще одно замечание. Этот кусок изменяет регистры "R16" и "R0" (командой "LPM"). Так что, если они используются в программе, их придется сохранить.
Целиком пример можно скачать в виде архива: timer_int.zip Он написан для AT90S2313 и компилировался в AVR-Studio. Эта тестовая программка выдает на ноге D.0 импульс длиной в 10 тактов с периодом 100 тактов. Ради интереса можно посмотреть на лог порта, который выдал симулятор AVR-Studio:
И еще одно замечание: Фоновая задача может быть какой угодно сложной и написанной на чем угодно. Однако любое другое прерывание (или команда "STI") могут заблокировать ваш обработчик.

01.02.2015 ©
9zip.ru
Авторские права охраняет Роскомнадзор