Точность таймера

Тема в разделе "Микроконтроллеры AVR", создана пользователем ostrov, 14 июн 2017.

  1. Vladimir71

    Vladimir71 Нерд

    На сколько я понял, то вы задаете таймеру отсчитать 1 сек, но не учитываете то, что контроллеру еще нужно выполнить команды перехода, обработси, записи и т.д. Может я и ошибаюсь, но на ассемблеры так и получится.
     
    Igor68 нравится это.
  2. Igor68

    Igor68 Гуру

    Простите за вмешательство, но Вы тысячу раз правы. В любом случае (для всех процессоров) само прерывание требует таки сохранение стека, счётчика команд, переход... а ещё завершения выполняемой инструкции... ту что на ассемблере - точнее уже в самом бинарном коде, которая исполняется в момент возникновения прерывания. И кроме того если вектора прерывания отсутствуют (поверьте есть и с одним вектором - например ADuC7024 "ARM7TDMI") и в самом начале собственно вектора приходится анализировать чьё это прерывание... а только потом делать переход на обработку. Для таймера это конечно снижение точности. Благо что выполнение в ARM(Cortex) занимают мало циклов - для простых инструкций. А если сложные инструкции выполняются? Такие как загрузка и выгрузка нескольких регистров в память или из памяти... то "линейность" по времени очень сильно нарушается. Один выход - это таймер без автоочистки при прерывании, а при обработке прерывания смотреть на сколько он больше "протикал" с момента прерывания и производить перезапуск таймера в самом прерывании. В любом случае не удобно.
     
  3. ostrov

    ostrov Гуру

    Насколько я понимаю, таймер тикает вне зависимости от того что происходит в самом мозгу МК. Совпало заданное число с текущим - прыгнули на обработку, при этом таймер продолжает тикать как и тикал, то есть с начала до совпадения. Единственное, что может быть следует обнулять таймер в самом начале обработки прерывания, но это вроде бы реализуется автоматически.
     
  4. Unixon

    Unixon Оракул Модератор

    Так в обработчике тогда обнулять ничего нельзя, иначе вы будете к каждому интервалу прибавлять еще и задержку обработки.
     
  5. Igor68

    Igor68 Гуру

    ...про реализуется автоматически я и говорю. Именно в ADuC7024 и ещё PIC16F877 так и приходилось делать. У первого из них "автосброс" реализуется в установке флага при его настройке. Но в любом случае можно прконтролировать сколько он "натикал" с момента прерывания... хоть после автосброса, хоть смотреть сколько он пересчитал. Если по прерыванию только значение как параметр это одно... а вот если по событию какое-то действие это совсем другое.
     
  6. Vladimir71

    Vladimir71 Нерд

    Для более правильной работы обычно таймер тактируют внешним часовым кварцем 32768, что дает правильный отсчет. Что бы выяснить откуда берутся лишние секунды лучше всего проследить в симуляторе по шаговои все станет ясно.
     
  7. mcureenab

    mcureenab Гуру

    Так и есть. Если таймер подключен к генератору тактовых импульсов (это программно управляется через регистры), он тикает счётчик вперед постоянно. Когда счётчик переполняется ( в МК могут быть разные таймеры/счётчики на 8 бит и/или 16 бит), счётчик переходит в 0 и продолжает считать. На событие переполнения можно повесить прерывание. На стабильность частоты таймера это не повлияет.

    Можно настроить сброс счётчика по достижению порога. Тогда сброс будет проходить не после 0xFF или 0xFFFF, а раньше. Цикл будет короче. Прерывание по сбросу будет чаще. Можно подобрать делитель частоты импульсов и порог счётчика так, чтобы прерывание происходило 1/10/100/1000 раз в секунду.

    Рассчитывать на то, что обработчик прерывания будет делать что то со стабильной задержкой не стоит. В момент срабатывания МК может обрабатывать другое прерывание, прерывания могут быть запрещены.
     
  8. mcureenab

    mcureenab Гуру

    Часовой кварц удобен тем, что вызывает переполнение 15 битного счётчика 1 раз в сек. Возможности МК считать такты гораздо богаче. Если частота кварца кратна 1 Гц, то секунды можно будет считать без ошибок округления с любым кварцем. Точность будет зависеть лишь от самого кварца.
    Если частота кварца не кратна 1 Гц, придется периодически вводить поправку - пропускать тик, или на тик добавлять два отсчёта. Так, например, в календаре есть високосные года.
     
  9. Vladimir71

    Vladimir71 Нерд

    можно подробнее, что значит без ошибок округления?

    Автор, а можно написать на какой частоте работает контроллер?
     
  10. ostrov

    ostrov Гуру

    Сдается мне, джентельмены, что ошибка таймера, если она вообще есть, влияет на точность меньше, чем плавающий кварц без термокомпенсации.
     
    DetSimen и Igor68 нравится это.
  11. ostrov

    ostrov Гуру

    Ардуино Про Мини 16МГц китайский.
     
  12. Igor68

    Igor68 Гуру

    Насколько понимаю если событие допустимо через плавающее значение (каждый раз разное) микросекунд (время реакции на прерывание)... то есть устраивает. то забейте. Вам важна точность от самого таймера, то смотрите в сторону точности кварца... ну и термокомпенсации. Можно и ещё ряд методов. Надеюсь это не альтернатива "атомным" часам.
     
  13. Vladimir71

    Vladimir71 Нерд

    Я правильно понял, что в программе счетчик отнимает до нуля, а не прибавляет до переволнения? Правда смущает 1024 в TCCR1B
    Считал, считал, так 1 секунду и не получил. Ни как не получается.
     
    Последнее редактирование: 18 июл 2017
  14. Igor68

    Igor68 Гуру

    Так вам в секундах надо!? Тогда вам придётся сделать выбрать частоту кварца кратную делителя (счётчика), чтобы на выходе был 1 Гц. Тут ребята говорили про 32768 Гц - как у стандартных часов... ну соответственно будете загружать 0x8000. Вешайте кварц на другой таймер (16-ти битный). Проще взять специализированный интегральный таймер.
    По моему воду в ступе толчём.
    Извините!
     
  15. mcureenab

    mcureenab Гуру

    16000000 Гц/1024 = 15625
    Счёт с 0 идет.

    15624 (hex 0x3D08)
     
  16. Vladimir71

    Vladimir71 Нерд

    Я не автор, не путайте, это он писал про часы, а я про кварц.
    похоже я с нулями запутался, надо пересчитать.
     
  17. Vladimir71

    Vladimir71 Нерд

    Да, секунда получается, все правильно. Попробуйте уменьшить число на два (0x3D06), посмотреть что получится, ради эксперимента, если возможность есть.
     
    Последнее редактирование: 19 июл 2017