На сколько я понял, то вы задаете таймеру отсчитать 1 сек, но не учитываете то, что контроллеру еще нужно выполнить команды перехода, обработси, записи и т.д. Может я и ошибаюсь, но на ассемблеры так и получится.
Простите за вмешательство, но Вы тысячу раз правы. В любом случае (для всех процессоров) само прерывание требует таки сохранение стека, счётчика команд, переход... а ещё завершения выполняемой инструкции... ту что на ассемблере - точнее уже в самом бинарном коде, которая исполняется в момент возникновения прерывания. И кроме того если вектора прерывания отсутствуют (поверьте есть и с одним вектором - например ADuC7024 "ARM7TDMI") и в самом начале собственно вектора приходится анализировать чьё это прерывание... а только потом делать переход на обработку. Для таймера это конечно снижение точности. Благо что выполнение в ARM(Cortex) занимают мало циклов - для простых инструкций. А если сложные инструкции выполняются? Такие как загрузка и выгрузка нескольких регистров в память или из памяти... то "линейность" по времени очень сильно нарушается. Один выход - это таймер без автоочистки при прерывании, а при обработке прерывания смотреть на сколько он больше "протикал" с момента прерывания и производить перезапуск таймера в самом прерывании. В любом случае не удобно.
Насколько я понимаю, таймер тикает вне зависимости от того что происходит в самом мозгу МК. Совпало заданное число с текущим - прыгнули на обработку, при этом таймер продолжает тикать как и тикал, то есть с начала до совпадения. Единственное, что может быть следует обнулять таймер в самом начале обработки прерывания, но это вроде бы реализуется автоматически.
Так в обработчике тогда обнулять ничего нельзя, иначе вы будете к каждому интервалу прибавлять еще и задержку обработки.
...про реализуется автоматически я и говорю. Именно в ADuC7024 и ещё PIC16F877 так и приходилось делать. У первого из них "автосброс" реализуется в установке флага при его настройке. Но в любом случае можно прконтролировать сколько он "натикал" с момента прерывания... хоть после автосброса, хоть смотреть сколько он пересчитал. Если по прерыванию только значение как параметр это одно... а вот если по событию какое-то действие это совсем другое.
Для более правильной работы обычно таймер тактируют внешним часовым кварцем 32768, что дает правильный отсчет. Что бы выяснить откуда берутся лишние секунды лучше всего проследить в симуляторе по шаговои все станет ясно.
Так и есть. Если таймер подключен к генератору тактовых импульсов (это программно управляется через регистры), он тикает счётчик вперед постоянно. Когда счётчик переполняется ( в МК могут быть разные таймеры/счётчики на 8 бит и/или 16 бит), счётчик переходит в 0 и продолжает считать. На событие переполнения можно повесить прерывание. На стабильность частоты таймера это не повлияет. Можно настроить сброс счётчика по достижению порога. Тогда сброс будет проходить не после 0xFF или 0xFFFF, а раньше. Цикл будет короче. Прерывание по сбросу будет чаще. Можно подобрать делитель частоты импульсов и порог счётчика так, чтобы прерывание происходило 1/10/100/1000 раз в секунду. Рассчитывать на то, что обработчик прерывания будет делать что то со стабильной задержкой не стоит. В момент срабатывания МК может обрабатывать другое прерывание, прерывания могут быть запрещены.
Часовой кварц удобен тем, что вызывает переполнение 15 битного счётчика 1 раз в сек. Возможности МК считать такты гораздо богаче. Если частота кварца кратна 1 Гц, то секунды можно будет считать без ошибок округления с любым кварцем. Точность будет зависеть лишь от самого кварца. Если частота кварца не кратна 1 Гц, придется периодически вводить поправку - пропускать тик, или на тик добавлять два отсчёта. Так, например, в календаре есть високосные года.
можно подробнее, что значит без ошибок округления? Автор, а можно написать на какой частоте работает контроллер?
Сдается мне, джентельмены, что ошибка таймера, если она вообще есть, влияет на точность меньше, чем плавающий кварц без термокомпенсации.
Насколько понимаю если событие допустимо через плавающее значение (каждый раз разное) микросекунд (время реакции на прерывание)... то есть устраивает. то забейте. Вам важна точность от самого таймера, то смотрите в сторону точности кварца... ну и термокомпенсации. Можно и ещё ряд методов. Надеюсь это не альтернатива "атомным" часам.
Я правильно понял, что в программе счетчик отнимает до нуля, а не прибавляет до переволнения? Правда смущает 1024 в TCCR1B Считал, считал, так 1 секунду и не получил. Ни как не получается.
Так вам в секундах надо!? Тогда вам придётся сделать выбрать частоту кварца кратную делителя (счётчика), чтобы на выходе был 1 Гц. Тут ребята говорили про 32768 Гц - как у стандартных часов... ну соответственно будете загружать 0x8000. Вешайте кварц на другой таймер (16-ти битный). Проще взять специализированный интегральный таймер. По моему воду в ступе толчём. Извините!
Я не автор, не путайте, это он писал про часы, а я про кварц. похоже я с нулями запутался, надо пересчитать.
Да, секунда получается, все правильно. Попробуйте уменьшить число на два (0x3D06), посмотреть что получится, ради эксперимента, если возможность есть.