Sanitaryhygiene.ru

Санитары Гигиены
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Таймер розетка интервал секунд

Введение

По сути, таймер микроконтроллера — это цифровой счетчик, только «навороченый». На вход счетчика подается тактовый сигнал, по перепадам которого счетчик увеличивает свое значение. При возникновении событий — переполнение счетчика или совпадение его значения с заданным — генерируется запрос на прерывание.

Давайте разберем, как пользоваться таймером Т0 в режиме Normal. В этом режиме таймер считает от какого-то начального значения счетного регистра до максимально возможного (до 255 или 0xFF). Когда таймер Т0 досчитывает до максимума, то в следующий такт таймера возникает переполнение счетного регистра TCNT0 — он обнуляется и устанавливается флаг TOV0. Если в программе разрешены прерывания глобально (флаг I регистра SREG) и прерывание таймера Т0 по переполнению (флаг TOIE0 регистра TIMSK), то микроконтроллер вызовет соответствующий обработчик. Если значение счетного регистра совпадет с регистром сравнения OCR0, то установится флаг OCF0 и при разрешенном прерывании по событию совпадение, запустится его обработчик.

Таймер Т0 в режиме Normal

Рассмотрим практическую задачу — нам нужно каждые 20 мс опрашивать кнопку. Частота микроконтроллера 8 МГц, микроконтроллер ATmega16.

Первое, что нужно сделать — это определиться с выбором коэффициента предделителя таймера и рассчитать начальное значение для счетного регистра TCNT0.

Таймер Т0 может тактироваться от внутреннего тактового сигнала микроконтроллера или от внешнего, который подается на вывод Т0. При работе от внутреннего тактового сигнала пользователь может выбирать коэффициенты деления частоты этого сигнала. У таймера Т0 есть пять возможных вариантов коэффициента предделителя — 1, 8, 64, 256, 1024.

Для решения поставленной задачи, я рассуждаю следующим образом. Если бы один такт таймера Т0 имел период 1 мс, то мне бы это подошло. 20 тактов дают 20 мс. Какой коэффициент предделителя таймера позволит получить близкий к 1 мс период тактовой частоты? Можно посчитать.

Тактовая частота микроконтроллера Fcpu = 8000000 Гц
Период тактового сигнала микроконтроллера Tcpu = 1/Fcpu
Период тактового сигнала таймера Т0 равен Tt0 = (1/Fcpu)/k = k/Fcpu

При k = 1024 период тактовой частоты таймера Т0 будет равен Tt0 = 1024/8000000 = 0.128 мс

Это максимальный период тактового сигнала таймера, который мы можем получить при наших условиях (Fcpu = 8 МГц). При меньших коэффициентах — период получится еще меньше.

Ну хорошо, пусть один такт таймера это 0.128 мс, хватит ли разрядности счетного регистра, чтобы отсчитать этот временной интервал и сколько для этого понадобится тактов? Делим требуемый интервал времени (20 мс) на длительность одного такта таймера и получаем ответ.

n = t/Tto = 20 мс/ 0.128 мс = 156.25

Округлив до целого, получаем 156 тактов. Это меньше 255 (максимального значения счетного регистра), значит разрядности счетного регистра TCNT0 хватит.

Начальное значение для счетного регистра TCNT0 вычисляем как разницу между максимальным числом тактов таймера Т0 и требуемым, то есть 256 — 156 = 100. (256 — это максимальное количество временных интервалов, которые может отсчитать любой 8-и разрядный таймер.)

Думаю, теперь понятно, как рассчитывать начальное значение TCNT0 для режима Normal:

— вычисляем период одного такта таймера Tt0 = k/Fcpu,
— вычисляем требуемое количество тактов для заданного интервала n = t/Tto,
— вычисляем начальное значение для счетного регистра TCNT0 = 256 — n.

Можно автоматизировать эту процедуру с помощью макросов. Например, так:

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

Теперь переходим к коду. Чтобы использовать таймер Т0 (да и любой другой тоже), его нужно настроить (инициализировать) и описать обработчик прерывания (если они используются).

Инициализация таймера состоит из следующих шагов:

— остановка таймера,
— задание режима Normal в TCCR0 без старта,
— установка начального значения TCNT0,
— сброс флагов в регистре TIFR,
— разрешение прерывания по переполнению в TIMSK,
— установка предделителя в TCCR0, то есть старт таймера

В данной последовательности возможны вариации.

Для нашей задачи код инициализации будет выглядеть так:

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

Сброс флагов прерываний в регистре TIFR выполняется записью 1 в соответствующий разряд. Эту операцию нужно выполнять именно перезаписью регистра, а не с помощью побитового ИЛИ. И вот почему.

Допустим, в регистре TIFR устанавлены два флага прерывания — TOV1 и TOV0. TOV0 нам нужно сбросить. При установке требуемого разряда с помощью ИЛИ происходит примерно следующая вещь.

Читайте так же:
Розетка компьютерная это для интернета

В результате сброшены оба флага, а мы хотели сбросить один.

Синтаксис описания обработчиков прерывания у разных компиляторов немного отличается. Для IAR`a обработчик прерывания таймера Т0 по событию переполнение будет выглядеть так:

TIMER0_OVF_vect — это адрес вектора прерывания по событию переполнение. Он берется из заголовочных файлов на микроконтроллер. В данном случае я взял его из файла iom16.h.

Первая строка обработчика (TCNT0 = T_POLL;) выполняет перезапись счетного регистра, то устанавливает его начальное значение. Если этого не сделать, таймер продолжит счет с 0. Перезапись счетного регистра нужно выполнять в начале обработчика прерывания.

Весь код для нашей задачи будет выглядеть примерно так. (Код приведен для IAR`a. Для других компиляторов нужно изменить заголовочные файлы и обработчик прерывания.)

Управление выводом OC0

В режиме Normal таймер Т0 может изменять состояние вывода OC0 при совпадении счетного регистра и регистра сравнения. Причем даже без прерываний. Варианты управления определяются разрядами COM01 и COM00 регистра TCCR0.

Вот пример программы, генерирующей прямоугольный сигнала на выводе ОС0.

Вывод ОС0 будет менять свое состояние на противоположное при нулевом значении счетного регистра.

Несколько моментов относительно использования таймера

Обработчик прерывания таймера (да и любой другой периферии) нужно делать как можно короче.

Если расчетное значение для счетного регистра (или регистра сравнения) округляется, то временной интервал будет отсчитываться таймером с погрешностью.

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

И последнее. Может случится ситуация, что обработка прерывания таймера задержится (например, по вине другого обработчика) и регистр TCNT0 уже посчитает несколько тактов. Если просто перезаписать значение TCNT0, то следующее прерывание вызовется позже, чем нужно. Получится, что предыдущее (задержанное) и новое прерывания не выдержат требуемый интервал.

Эту ситуацию можно сгладить, если выполнять перезапись счетного регистра вот так:

TCNT0 = TCNT0 + startValue;

Сложение текущего значения счетного регистра с инициализируемым, учтет эти лишние такты. Правда есть одно НО! При больших значения startValue операция сложения может вызвать переполнение счетного регистра.

Например, startValue = 250, а таймер успел досчитать до 10. Тогда операция сложения приведет к такому результату:

барахлит розетка с таймером

Розетка с таймером работает день -два, потом обнуляет(скидывает) и часы, и установленные программы ( на включение и выключение ).
Подскажите , пожалуйста, возможен ли ремонт; или не стоит того, и проще купить новый? Уж больно надоело переустанавливать все
программы заново. Таймер точно такой http://feron.ru/inde.

Свой на Aqa.ru, Советник

Был один такой — совершенно бессистемно, периодически 1 раз в 30-50 дней обнулялся — выкинул и поставил механический. Хотя другой, такой же, работает до сих пор, без проблем.

18 3

9 года

этот то-же не первый. первый работал лет пять. механический не «помнит» программу при выключении света, а во вторых использую по 3 минуты включения
несколько раз в день, что механический не в состоянии.
только по 15 минут интервал.

Свой на Aqa.ru, Советник

18 3

9 года

вот-вот отстанет от времени(имелось в ввиду). и ещё у механического 15 минутный интервал включения.
я же по 3 минуты несколько раз в день включаю так наз.орошение с помощью эрлифта полюдариума.получается
типа точечный микрополив . а по 15 мин много , позалевает всё слишком.

Свой на Aqa.ru, Советник

141 34

8 года

А как насчёт вот этого

Базовый модуль (исполнение 24V DC) имеет 6 входов + 2 аналоговых 0-10V и 4 релейных выхода или исполнение 230V AC — 8 входов 230V AC, к ним можно пристыковать ещё 4 блока расширения, как обычных 4 входа +4 выхода (мах. количество 20 входов и 16 выходов) так и спец. блоки (к примеру аналоговые выходы или входы 4-20mA /0/2-10V).
Программируется при помощи логических функций (AND, OR и т.д.) (никаких программных языков — простой и интуитивный графический интерфейс) и каких только возможных функций времени (задержки включения и выключения , таймеры и счётчики и т.д.) (от нескольких миллисекунд до . ), плюс функции обработки аналогового сигнала.
Модуль имеет дисплей, можно выводить до 10 сообщений (какие угодно). при помощи кнопок на передней панели можно включать и выключать определённые выходы или запускать определённые функции программы.

Изменено 8.3.08 автор Bek

Читайте так же:
Розетка однополюсная открытой установки ip20

18 3

9 года

прибор новый, включен в разетку постоянно и аккумы не должны влиять никак, вроде. а вот микроконтроллер — точно причина. сейчас один таймер работает, который уже и глючил и гарелым попахивал итд, но пролежав лет 5 на полке — заработал снова. и без проблем и сбоев уже год или больше работает . а вообще таймеры нужно подороже покупать. это 100% гарантия . почемуто же «фирменные» нААмного дороже?! а с агрегатом по ссылке как то знакомилсяна рынке, давно.. неподходит то ли неразумной ценой , то ли ещё чем то непомню уже сейчас. промышленные они..

11 1

11 года

Сегодня умер (я так думаю) таймер, такой же как у postman`а в первом посте, maid in Taiwan. Когда он вставлен в розетку в режиме auto, во время включения начинает щелкать реле внутри (т. е. свет включается и выключается) с частотой примерно 4 раза в секунду. А когда по таймеру время выключения — реле щелкать перестаёт. Придётся ехать за новым. Может кто знает, что там могло сгореть? Или только в помойку?

1

13 года
2

9 года

Таймер-розетка предназначена для автоматического отключения или включения бытовых электроприборов к сети.

Простой таймер с выдержкой от 1 сек. до 24 часов

Таймер

Таймер предназначен для включения нагрузки на заданный интервал времени. Диапазон возможного интервала таймера от 1 секунды до 24 часов.

Таймер очень прост, не содержит дефицитных деталей и может быть повторен радиолюбителем средней квалификации. В чем-то этот таймер является улучшенным вариантом ранее опубликованного. Практическое применение устройство может найти, например, при изготовлении печатных плат с помощью фоторезиста для ограничения времени включения ультрафиолетовой лампы при засвечивании фоторезистивной поверхности.

Конструкция имеет гальваническую связь с бытовой сетью 220 вольт, поэтому следует соблюдать особую осторожность в процессе изготовления и испытаний. Будучи помещенным в корпус, таймер уже не представляет опасности.

Таймер может быть собран по одной из двух вариантов схем:

Для первой схемы рекомендуемая мощность коммутируемой нагрузки не более 100 ватт, так как симистор КУ208Г размещён в корпусе без радиатора и при большей нагрузке будет сильно нагреваться.

Если требуется коммутировать нагрузку с большой мощностью, рекомендуется установить симистор на радиатор, или попробовать применить другой, более мощный.

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

В законченном собранном варианте устройства кнопка управления и остальные части схемы должны быть хорошо изолированы от контакта с рукой пользователя.

Напряжение питания микроконтроллера 5 вольт, стабилизировано микросхемой 78L05 .

Конструктивно всё устройство уместилось в корпус от адаптера, в котором сгорел трансформатор, а корпус сохранился.

Общий вид готового таймераВнутренности таймера
Схема собрана на небольшой монтажной плате, печатная плата не разрабатывалась. Детали применены не дефицитные и широко распространённые, как отечественные, так и импортного производства. В первой схеме с симистором можно применить герконовое реле РГК15 с напряжением включения 5 вольт, симистор VS1КУ208Г , можно использовать КУ208В или зарубежные аналоги с похожими характеристиками.

Во второй схеме в качестве реле К1 применялось импортное реле с одной группой нормально разомкнутых контактов, рассчитанных на ток 10 А, название реле SDT-SS-112DM. Полагаю, что можно заменить на реле другого типа с сопротивлением обмотки приблизительно 300 ом, на напряжение 12 в, при этом контакты реле должны быть рассчитаны на максимальный ток предполагаемой нагрузки. Транзистор VT1, коммутирующий реле, подойдёт любой средней мощности npn-проводимости, например из отечественных можно рекомендовать КТ315 или КТ503 . Микроконтроллер – семейства AVR ATtiny13 .

Диоды VD1,VD2 могут быть заменены отечественными, например Д226Б или КД105 с обратным напряжением не менее 350-400в, стабилитрон ZD1 — любой маломощный с напряжением стабилизации 12-20 вольт. В качестве буззера подойдёт любой электродинамический излучатель без встроенного генератора с сопротивлением обмотки 30-50 Ом.

В проекте тактовая частота внутреннего генератора микроконтроллера выбрана равной 1,2 МHz (9,6/8). Как выставить фьюзы для двух популярных программаторов (Chip Blaster и PonyProg) при программировании чипа показано на картинках ниже.

Фьюзы для ChipBlaster
Фьюзы для PonyProg

Как запрограммировать время таймера

Посредством длительного удержания в нажатом состоянии кнопки SB1 перейти в режим установки времени таймера (подробности ниже) и ввести нужное количество интервалов времени. Делается это один раз, все последующие циклы работы будут придерживаться этих установок до тех пор, пока не понадобится сменить их на другие этим же способом.

Читайте так же:
Am3 материнские платы розетка

Последовательность установки времени таймера

Включаем питание, индикатор HL1 НЕ горит. Нажимаем кнопку «SET» и длительно удерживаем в нажатом состоянии до момента, когда светодиод HL1 начнет мигать с частотой 1 раз в секунду (1 мигание = 1 дискретный интервал).

Последовательность установки времени таймера идёт в такой последовательности: сперва идёт набор секунд, после этого следует набор минут, потом набор часов, а затем — выход из режима установки времени таймера.

Наблюдая за миганием светодиода, отсчитываем количество вспышек (каждая сопровождается звуковым пиликанием зуммера). Отсчитав нужное количество секунд отпускаем кнопку. После этого число набранных секунд заносится в память, а индикатор HL1 начинает часто мигать, что означает начало ввода минут.

Нажимаем и удерживаем снова кнопку «SET» — светодиод HL1 мигает с частотой 1 раз в секунду. Снова отсчитываем требуемое число минут по вспышкам или звуковым сигналам, отпускаем кнопку. После этого индикатор HL1 светится постоянно — это означает, что теперь можно вводить часы.

Ввод часов осуществляется полностью аналогично — нажимаем и держим кнопку, отсчитываем нужное количество сигналов, отпускаем кнопку.

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

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

Точно так же поступаем, если нам НЕ надо набирать часовые интервалы: задав секунды и минуты, отпускаем кнопку и ждем сигнала о запоминании времени.

Теперь таймер готов к работе.

Запуск таймера осуществляется кратковременным нажатием кнопки «SET» (она же «Старт»). После нажатия кнопки зуммер пиликанием оповестит о начале цикла, включится нагрузка на время, установленное таймером. Если выдержка времени таймера превышает 1 мин., то индикатор HL1 будет вспыхивать через каждые 10 сек. По завершении цикла нагрузка отключится, и снова прозвучит звуковой сигнал продолжительностью около 5 сек. После этого устройство перейдёт в исходное состояние ожидания.

Если требуется прервать работу таймера не дожидаясь истечения заданного рабочего интервала, можно поступить двумя способами:

  1. если не предполагается изменять время таймера, надо просто выдернуть вилку из розетки — нагрузка отключится;
  2. если текущий интервал времени не устраивает, и предполагается сразу же поменять его, надо нажать и удерживать кнопку «SET» до сигнала зуммера (т.е. до включения режима ввода времени), нагрузка при этом так же отключится.

В приложении к статье находится прошивка таймера, схема в формате Splan7, проект Proteus с прошивкой для ознакомления с принципом работы таймера.

Arduino и прерывания таймера

Плата Arduino позволяет быстро и минимальными средствами решить самые разные задачи. Но там где нужны произвольные интервалы времени (периодический опрос датчиков, высокоточные ШИМ сигналы, импульсы большой длительности) стандартные библиотечные функции задержки не удобны. На время их действия скетч приостанавливается и управлять им становится невозможно.

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

В этой статье обсуждаются таймеры AVR и Arduino и то, как их использовать в Arduino проектах и схемах пользователя.

Что такое таймер?

Как и в повседневной жизни в микроконтроллерах таймер это некоторая вещь, которая может подать сигнал в будущем, в тот момент который вы установите. Когда этот момент наступает, вызывается прерывание микроконтроллера, напоминая ему что-нибудь сделать, например выполнить определенный фрагмент кода.

Таймеры, как и внешние прерывания, работают независимо от основной программы. Вместо выполнения циклов или повторяющегося вызова задержки millis() вы можете назначить таймеру делать свою работу, в то время как ваш код делает другие вещи.

Итак, предположим, что имеется устройство, которое должно что-то делать, например мигать светодиодом каждые 5 секунд. Если не использовать таймеры, а писать обычный код, то надо установить переменную в момент зажигания светодиода и постоянно проверять не наступил ли момент ее переключения. С прерыванием по таймеру вам достаточно настроить прерывание, и затем запустить таймер. Светодиод будет мигать точно вовремя, независимо от действий основной программы.

Читайте так же:
Телефонная розетка как подключить параллельно

Как работает таймер?

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

Вы можете проверять этот флаг вручную или можете сделать таймерный переключатель — вызывать прерывание автоматически в момент установки флага. Подобно всяким другим прерываниям вы можете назначить служебную подпрограмму прерывания (Interrupt Service Routine или ISR), чтобы выполнить заданный код, когда таймер переполнится. ISR сама сбросит флаг переполнения, поэтому использование прерываний обычно лучший выбор из-за простоты и скорости.

Чтобы увеличивать значения счетчика через точные интервалы времени, таймер надо подключить к тактовому источнику. Тактовый источник генерирует постоянно повторяющийся сигнал. Каждый раз, когда таймер обнаруживает этот сигнал, он увеличивает значение счетчика на единицу. Поскольку таймер работает от тактового источника, наименьшей измеряемой единицей времени является период такта. Если вы подключите тактовый сигнал частотой 1 МГц, то разрешение таймера (или период таймера) будет:

T = 1 / f (f это тактовая частота)
T = 1 / 1 МГц = 1 / 10^6 Гц
T = (1 ∗ 10^-6) с

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

Типы таймеров

В стандартных платах Arduino на 8 битном AVR чипе имеется сразу несколько таймеров. У чипов Atmega168 и Atmega328 есть три таймера Timer0, Timer1 и Timer2. Они также имеют сторожевой таймер, который можно использовать для защиты от сбоев или как механизм программного сброса. Вот некоторые особенности каждого таймера.

Timer0:
Timer0 является 8 битным таймером, это означает, что его счетный регистр может хранить числа вплоть до 255 (т. е. байт без знака). Timer0 используется стандартными временными функциями Arduino такими как delay() и millis(), так что лучше не запутывать его если вас заботят последствия.

Timer1:
Timer1 это 16 битный таймер с максимальным значением счета 65535 (целое без знака). Этот таймер использует библиотека Arduino Servo, учитывайте это если применяете его в своих проектах.

Timer2:
Timer2 — 8 битный и очень похож на Timer0. Он используется в Arduino функции tone().

Timer3, Timer4, Timer5:
Чипы ATmega1280 и ATmega2560 (установлены в вариантах Arduino Mega) имеют три добавочных таймера. Все они 16 битные и работают аналогично Timer1.

Конфигурация регистров

Для того чтобы использовать эти таймеры в AVR есть регистры настроек. Таймеры содержат множество таких регистров. Два из них — регистры управления таймера/счетчика содержат установочные переменные и называются TCCRxA и TCCRxB, где x — номер таймера (TCCR1A и TCCR1B, и т. п.). Каждый регистр содержит 8 бит и каждый бит хранит конфигурационную переменную. Вот сведения из даташита Atmega328:

TCCR1A
Бит7654321
0x80COM1A1COM1A0COM1B1COM1B0WGM11WGM10
ReadWriteRWRWRWRWRRRWRW
Начальное значение
TCCR1B
Бит7654321
0x81ICNC1ICES1WGM13WGM12CS12CS11CS10
ReadWriteRWRWRRWRWRWRWRW
Начальное значение

Наиболее важными являются три последние бита в TCCR1B: CS12, CS11 и CS10. Они определяют тактовую частоту таймера. Выбирая их в разных комбинациях вы можете приказать таймеру действовать на различных скоростях. Вот таблица из даташита, описывающая действие битов выбора:

CS12CS11CS10Действие
Нет тактового источника (Timer/Counter остановлен)
1clk_io/1 (нет деления)
1clk_io/8 (делитель частоты)
11clk_io/64 (делитель частоты)
1clk_io/256 (делитель частоты)
11clk_io/1024 (делитель частоты)
11Внешний тактовый источник на выводе T1. Тактирование по спаду
111Внешний тактовый источник на выводе T1. Тактирование по фронту

По умолчанию все эти биты установлены на ноль.

Допустим вы хотите, чтобы Timer1 работал на тактовой частоте с одним отсчетом на период. Когда он переполнится, вы хотите вызвать подпрограмму прерывания, которая переключает светодиод, подсоединенный к ножке 13, в состояние включено или выключено. Для этого примера запишем Arduino код, но будем использовать процедуры и функции библиотеки avr-libc всегда, когда это не делает вещи слишком сложными. Сторонники чистого AVR могут адаптировать код по своему усмотрению.

Сначала инициализируем таймер:

Регистр TIMSK1 это регистр маски прерываний Таймера/Счетчика1. Он контролирует прерывания, которые таймер может вызвать. Установка бита TOIE1 приказывает таймеру вызвать прерывание когда таймер переполняется. Подробнее об этом позже.

Когда вы устанавливаете бит CS10, таймер начинает считать и, как только возникает прерывание по переполнению, вызывается ISR(TIMER1_OVF_vect). Это происходит всегда когда таймер переполняется.

Дальше определим функцию прерывания ISR:

Сейчас мы можем определить цикл loop() и переключать светодиод независимо от того, что происходит в главной программе. Чтобы выключить таймер, установите TCCR1B=0 в любое время.

Как часто будет мигать светодиод?

Timer1 установлен на прерывание по переполнению и давайте предположим, что вы используете Atmega328 с тактовой частотой 16 МГц. Поскольку таймер 16-битный, он может считать до максимального значения (2^16 – 1), или 65535. При 16 МГц цикл выполняется 1/(16 ∗ 10^6) секунды или 6.25e-8 с. Это означает что 65535 отсчетов произойдут за (65535 ∗ 6.25e-8 с) и ISR будет вызываться примерно через 0,0041 с. И так раз за разом, каждую четырехтысячную секунды. Это слишком быстро, чтобы увидеть мерцание.

Если мы подадим на светодиод очень быстрый ШИМ сигнал с 50% заполнением, то свечение будет казаться непрерывным, но менее ярким чем обычно. Подобный эксперимент показывает удивительную мощь микроконтроллеров — даже недорогой 8-битный чип может обрабатывать информацию намного быстрей чем мы способны обнаружить.

Делитель таймера и режим CTC

Чтобы управлять периодом, вы можете использовать делитель, который позволяет поделить тактовый сигнал на различные степени двойки и увеличить период таймера. Например, вы бы хотели мигания светодиода с интервалом одна секунда. В регистре TCCR1B есть три бита CS устанавливающие наиболее подходящее разрешение. Если установить биты CS10 и CS12 используя:

то частота тактового источника поделится на 1024. Это дает разрешение таймера 1/(16 ∗ 10^6 / 1024) или 6.4e-5 с. Теперь таймер будет переполняться каждые (65535 ∗ 6.4e-5с) или за 4,194с. Это слишком долго.

Но есть и другой режим AVR таймера. Он называется сброс таймера по совпадению или CTC. Вместо счета до переполнения, таймер сравнивает свой счетчик с переменой которая ранее сохранена в регистре. Когда счет совпадет с этой переменной, таймер может либо установить флаг, либо вызвать прерывание, точно так же как и в случае переполнения.

Чтобы использовать режим CTC надо понять, сколько циклов вам нужно, чтобы получить интервал в одну секунду. Предположим, что коэффициент деления по-прежнему равен 1024.

Расчет будет следующий:

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

Функция настройки setup() будет такая:

Также нужно заменить прерывание по переполнению на прерывание по совпадению:

Сейчас светодиод будет зажигаться и гаснуть ровно на одну секунду. А вы можете делать все что угодно в цикле loop(). Пока вы не измените настройки таймера, программа никак не связана с прерываниями. У вас нет ограничений на использование таймера с разными режимами и настройками делителя.

Вот полный стартовый пример который вы можете использовать как основу для собственных проектов:

Помните, что вы можете использовать встроенные ISR функции для расширения функций таймера. Например вам требуется опрашивать датчик каждые 10 секунд. Но установок таймера, обеспечивающих такой долгий счет без переполнения нет. Однако можно использовать ISR чтобы инкрементировать счетную переменную раз в секунду и затем опрашивать датчик когда переменная достигнет 10. С использованием СТС режима из предыдущего примера прерывание могло бы выглядеть так:

Поскольку переменная будет модифицироваться внутри ISR она должна быть декларирована как volatile. Поэтому, при описании переменных в начале программы вам надо написать:

Послесловие переводчика

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

голоса
Рейтинг статьи
Ссылка на основную публикацию
Adblock
detector