Buderus-trade.ru

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

Счетчик с прерыванием по переполнению

Счётчики/Таймеры

Счётчики (англ. counter), в некотором смысле таймеры (англ. timer), являются одними из важнейших дополнительных функций микроконтроллеров. С их помощью можно регулировать процессы точно по времени, генерировать сигналы и считывать события. Рабочий принцип счётчика состоит в том, что он преобразовывает число входных тактов в бинарное значение при помощи цепочки триггеров. От длины цепочки зависит максимальное считываемое количество тактов, которое обозначается длинной двоичного кода. Счётчики микроконтроллера AVR 8- и 16-битные. Если счётчик достигает максимального значения (у 8-битных 255, 16-битных 65535), то при следующем такте происходит переполнение (англ. overflow) и счётчик обнуляется. Тактовый сигнал может приходить из рабочего такта микроконтроллера и в этом случае можно уменьшить его частоту при помощи делителя частоты (англ. prescaler). У некоторых AVR имеется отдельный внутренний генератор тактовых сигналов, частоту которого можно увеличить с помощью умножителя частоты. Счётчики различаются так же по возможностям применения и рабочим режимам.

Стандартный режим счётчика

В стандартном режиме счётчик не выполняет других функций кроме постоянного считывания последовательных номеров. Значение счётчика в программе можно в любой момент считать и изменить. Единственная дополнительная возможность в стандартном режиме счётчика – это вызвать прерывание при переполнении счётчика. Стандартный режим обычно используется для заполнения какого-либо отрезка программы в определённые интервалы времени.

Счётчик в данном примере не будет совершать прерывания ровно через 10мс, так как для этого счётчику нужно присвоить десятичное значение, а это невозможно. Для того чтобы получить точный интервал прерывания, следует коэффициент делителя частоты и значение, получаемое счётчиком при заполнении выбирать так, чтобы их деление было точным. К сожалению, это не всегда возможно, особенно в случае с 8-битным счётчиком, так как его шкала значений достаточна мала. Для получения более точного и широкого интервала можно использовать 16-битный счётчик.

Счётчик с внешним тактом

В качестве тактового сигнала счётчика можно использовать внешний сигнал микроконтроллера (англ. external clock source). Для этого на AVR имеется вывод Tn, где n обозначает номер счётчика. Внешний сигнал такта и полярность можно выбрать с помощью регистра делителя частоты.

Измерение событий

Так как счётчики позволяют измерять время, на более сложных микроконтроллерах AVR есть возможность с помощью аппаратного обеспечения измерить время, в которое произошло какое-либо событие. Эта часть счётчика называется фиксатором событий (англ. input capture unit). В AVR есть возможность выбора между двумя событиями: изменение логического значения результатов сравнения специального входного вывода или аналогового компаратора. Если происходит выбранное событие, значение счётчика записывается в специальный регистр, где его можно вычитать в желаемое время. Если время происхождения события длиннее, чем время переполнения счётчика, следует программно считать и переполнения счётчика (например, прерыванием переполнений) и учесть их в конечном результате.

Фиксацию событий и регистрацию их времени можно так же совершать программно. Можно использовать внешние и другие прерывания и во время их возникновения считывать значение счётчика. Аппаратная фиксация событий всё же, прежде всего, предназначена для работы вне зависимости от программы и для измерения достаточно кратковременных или частых событий.

Генерирование сигнала

С помощью более сложных счётчиков можно помимо измерения длинны сигнала так же создавать сигналы. Для этого у счётчика есть компаратор (блок сравнения) значений (англ. output compare unit) и блок вывода результатов сравнения (англ. compare match output unit). Регистры компаратора имеют ту же битовую ширину, что и сам счётчик и значения их регистров сравниваются со значениями счётчика во время его работы. В тот момент, когда значение регистра компаратора сравняется со значением счётчика, можно совершить прерывание и изменение состояния специальных выходных выводов. В момент сравнения вывод может быть установлен в высокое, низкое или обратное положение. Изменения состояния выходного вывода генерируют сигнал.

В некоторых режимах генерирования сигнала максимальное значение счётчика может быть изменено. Физическая величина счётчика остаётся такой же, но он обнуляется при превышении значения регистра сравнения. Используя эту возможность, можно решить вышеприведённые задания, но это скорее предусмотрено для изменения периода сигнала. Так же счётчик можно настроить в режим прямого (увеличение) и обратного (уменьшение) счёта.

Счётчики, и генерируемые с их помощью режимы сигналов, являются одними из самых сложных периферических модулей в AVR. Их описание выходит за рамки данного текста, и в большинстве случаев нет необходимости знать все аспекты их использования. В связи с этим, далее приведён только один из них, наиболее распространённый в роботике, сигнал ШИМ (широтно-импульсная модуляция). Информацию об остальных можно получить в документации к AVR.

Широтно-импульсная модуляция

ШИМ (англ. pulse width modulation) – это тип сигнала, частота и период (обычно), которого константен, но длинна полупериодов меняется. Сигналы ШИМ используются для управления электромеханическими, оптическими и другими приборами. Например, сервомотор, известный в моделировании, использует сигнал ШИМ с частотой в 50 Hz и высокий полупериод длинной от 1 ms до 2 ms.

Русские Блоги

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

Таймер, по сути, представляет собой 16-разрядный счетчик с самостоятельным приращением. Когда происходит переполнение, если прерывание по переполнению разрешено, микроконтроллер автоматически сообщит прерывание по переполнению ЦПУ и обработает соответствующую задачу прерывания.

Читайте так же:
Куда вводить код счетчика

регистр

TCON регистр управления таймером

Нижние 4 бита TCON используются в качестве внешних прерываний, а верхние 4 бита используются для контроля времени. Адрес 88H.

Значение каждого бита регистра управления таймером TCON следующее:

  • IT0: режим запуска внешнего прерывания 0. 1 — триггер низкого уровня, 0 — триггер спадающего фронта
  • IE0: флаг запроса внешнего прерывания 0 IE0 = 1 означает, что есть запрос прерывания, 0 означает нет.
  • IT1: режим запуска внешнего прерывания 1. 1 — низкий уровень, 0 — сигнал с падающим фронтом.
  • IE1: флаг запроса внешнего прерывания 1 IE0 = 1 означает, что есть запрос прерывания, 0 означает нет.
  • TR0: Таймер / счетчик 0, бит управления остановом запуска. 1 — начало, 0 — остановка.
  • TF0: Флаг переполнения таймера / счетчика 0. 1 означает переполнение, если прерывание включено, оно вызовет прерывание.
  • TR1: Бит управления остановом запуска таймера / счетчика 1. 1 — начало, 0 — остановка.
  • TF1: флаг переполнения таймера / счетчика 1. 1 означает переполнение, если прерывание включено, оно вызовет прерывание.

Регистр управления разрешением прерываний IE

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

Значение каждого бита регистра IE

Значение каждого бита регистра управления разрешением прерываний IE следующее:

  • EX0: бит разрешения внешнего прерывания 0
  • ET0: Бит разрешения прерывания от таймера / счетчика 0
  • EX1: бит разрешения внешнего прерывания 1
  • ET1: Бит разрешения прерывания от таймера / счетчика 1
  • ES: бит разрешения прерывания последовательного порта
  • ET2: Бит разрешения прерывания от Таймера / Счетчика 2 (для серии 52)
  • EA: главный прерыватель прерывания

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

Пример языка Си

Всякий раз, когда вы хотите использовать прерывание, вы должны включить полное прерывание эксперта. Например, если вы хотите использовать таймер / счетчик 0, вам нужно добавить следующий код Keil C51, чтобы включить EA и ET0:

Или используйте байтовые операции:

Примеры ассемблера

Если вы используете язык ассемблера, включите внешний ассемблерный код прерывания 0, операция байта:

Или используйте битовые операции на ассемблере:

Регистр рабочего режима таймера TMOD

TMOD используется для управления режимом работы таймера, младшие 4 бита используются для T0, а старшие 4 бита используются для T1. Значение каждого бита следующее:

  • M0 и M1: всего 4 комбинации, соответствующие 4 режимам работы таймера
    • M1 = 0, M0 = 0: режим 0, 13 бит, максимальный диапазон счета составляет 8192. Нижние 5 битов TL и верхние 8 битов TH образуют 13-битный счетчик, который обычно не используется для совместимости с серией 48.
    • M1 = 0,M0 = 1:Режим 1, 16 бит, максимальный диапазон счета 65536
    • M1 = 1, M0 = 0: режим 2, 8 бит, максимальный диапазон счета составляет 256. Старшие 8 бит устанавливают номер предустановки, и только младшие 8 бит участвуют в подсчете.Номер предустановки может быть автоматически пополнен после переполнения счетаВысокая точность синхронизации. Он может быть использован для точных временных интервалов, таких как генератор скорости передачи.
    • M1 = 1, M0 = 1: режим 3, 8 бит, максимальный диапазон счета составляет 256. В это время T0 разделен на 2 независимых таймера / счетчика. Среди них TL0 может использоваться как 8-битный таймер / счетчик, а TH0 может использоваться только как таймер. Управление TH0 и флаг переполнения заимствованы из T1. Как правило, T0 работает в режиме 3, только когда T1 работает в режиме 2.
    • Когда GATE = 0, переключателем управляет только TR0, когда TR0 = 1, импульс счета может пройти, в противном случае он не может пройти
    • Когда GATE = 1, переключатель управляется TR0 и INT0 одновременно.Только если TR0 = 1 и INT0 высокий, импульс счета может пройти

    Регистр управления приоритетом IP-прерывания

    Немного7654321
    названиеPT2PSPT1PX1PT0PX0

    Регистр управления последовательным портом SCON

    • SM0 и SM1: выбор режима последовательного порта
    • SM2: бит разрешения связи с несколькими машинами. В режиме 2 или режиме 3, если SM2 = 1, только когда принятые девятые данные (RB8) равны 1, полученные данные могут быть отправлены в SBUF, и флаг прерывания приема RI установлен в ЦПУ Подать заявку на прерывание, в противном случае данные будут потеряны: если SM2 = 0, первые 8 бит данных будут загружены в SBUF независимо от того, являются ли принятые 9-е данные 1 или 0, а флаг RI получения прерывания будет установлен на ЦП Приложение прервано. В режиме 1, если SM2 = 1, RI будет установлен только при получении действительного стоп-бита. В режиме 0 SM2 должен быть 0.
    • REN: бит разрешения приема последовательных данных, 1 разрешен, 0 запрещен
    • TB8: в режиме 2 и режиме 3 этот отправил девятое место. В связи с несколькими машинами состояние этого бита часто используется для указания того, посылает ли хост адрес или данные. Обычно оговорено, что TB8 равен «0», чтобы указать, что хост отправляет данные, а «1» должен указать, что адрес отправляется.
    • RB8: в режиме 2 и режиме 3 этот отправил девятое место. Используется для управления связью вместе с SM2 и TB8.
    • TI: флаг прерывания передачи, сбрасываемый программным обеспечением после завершения
    • RI: Принять флаг прерывания, сбросить его программным обеспечением, когда он израсходован

    Прерывание

    Источник прерывания

    Микроконтроллер 51 имеет 5 источников прерываний. 5 источников прерываний:

    • Внешнее прерывание 0, мультиплексированное от порта P3.2
    • Внешнее прерывание 1, мультиплексированное от порта P3.3
    • Таймер / Счетчик 0 прерывание переполнения
    • Прерывание переполнения таймера / счетчика 1
    • Последовательный порт, отправляющий или получающий прерывание

    Прерывания могут быть вложены в соответствии с приоритетом, серия 51 может достигать 2 уровней вложенности (соответствует IP-адресу регистра приоритета), серия 52 может реализовывать 4 уровня вложенности (соответствует IP-адресу регистра приоритета и IPH).

    Прервать соответствующую информацию

    Имя прерыванияФлаг прерыванияНомер прерыванияПриоритет по умолчаниюАдрес прерывания
    Внешнее прерывание 0IE0высокая0003H
    Таймер / Счетчик 0 прерывание переполненияTF02000BH
    Внешнее прерывание 1IE110013H
    Прерывание переполнения таймера / счетчика 1TF13001BH
    Последовательный порт, отправляющий или получающий прерываниеRI/TI4низкий0023H

    Поток обработки прерываний

    1. Остановить основную программу
    2. Защитите точки останова и поместите значение ПК счетчика программ в стек
    3. В поисках прерывания, каждое прерывание имеет свою запись в программе
    4. Выполнить обработчик прерываний
    5. Возврат прерывания, продолжить выполнение основной программы

    Прерванное использование

    Любое использование прерывания должно удовлетворять 3 условиям:

    • Включить главный выключатель: EA EX = 1
    • Включите переключатель для указанного прерывания. Например, если вы хотите использовать внешнее прерывание 0, вы должны установить: EX0=1
    • Прерывание произошло

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

    Каждое прерывание имеет отдельный переключатель, эти отдельные переключатели находятся в регистре IE, как и главный переключатель EA.

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

    Расчет первоначальной стоимости

    Предположим, я хочу запускать прерывание переполнения каждые 24 отсчета, таймер работает в режиме 1, затем начальное значение отсчета составляет 65536-24 = 65512.

    Keil C51 код

    Пример кода для внешнего прерывания

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

    Принципиальная электрическая схема:

    Arduino.ru

    Я связался с Дэвидом Меллисом (David Mellis) из команды разработчиков Arduino и узнал, что Arduino пользуется всеми тремя таймерами ATMega168.

    • Tаймер 0 (Системное время, ШИМ 5 and 6)
      Используется для хранения счетчика времени работы программы. Функция millis() возвращает число миллисекунд с момента запуска программы, используя ISR глобального приращения таймера 0. Таймер 0 также используется для реализации ШИМ на выводах 5 и 6.
    • Tаймер 1 (ШИМ 9 и 10)
      Используется для реализации ШИМ для цифровых выводах 9 и 10.
    • Tаймер 2 (ШИМ 3 и 11)
      Используется для управления выходами ШИМ для цифровых выводов 3 и 11.

    Хотя все таймеры используются, только Tаймер 0 имеет назначенную таймеру ISR. Это означает, что мы можем захватить Таймер 1 и/или Таймер2 под свои нужды. Однако в результате вы не сможете использовать ШИМ на некоторых портах ввода-вывода. Если вы планируете использовать ШИМ, имейте это ввиду. Я выбрал использование Таймера 2, что окажет влияние на выводы 3 и 11.

    Моя тестовая программа полностью отключила вывод ШИМ на цифровые выводы, управляемые с таймера 2. Я подозреваю, что библиотека функций ШИМ рассчитана на работу счетчика в заданном диапазоне, который я превысил. Функция захвата сравнивает загруженные значения, и значения моего таймера просто не будут понятны для ШИМ.

    Дэвид Меллис дал мне эту ссылку для изучения того, как библиотечные программы используют таймеры. Она хорошо документирована и я уверен, что она сослужит мне хорошую службу в будущем. В будущих экспериментах я планирую управлять ШИМ-модуляцией напрямую, чтобы достичь намного большей частоты, чем нормальная. Высокочастотный ШИМ может здорово пригодиться для функции аудио-ЦАП.
    Ссылки, относящиеся к прерываниям в Arduino.

    Здесь приведены несколько ссылок (англ.), относящихся к прерываниям на Arduino. Я просмотрел некоторые из них, пока забавлялся с прерываниями. Я должен признать, что мои познания – заслуга этих авторов.

    • Обработка внешних прерываний на Arduino (
    • Буду думать прежде чем писать программу
    • Прерывания против последовательного опроса
    • Больше внешних прерываний?
    • AVR Libc : Прерывания
    Тексты программ

    Программы, приведенные в этой статье, доступны в zip-архиве.

    Установка Таймера 2

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

    Сначала определяется тактовая частота таймера. Показано, что тактовая частота установлена 2 МГц, так как мы используем деление на 8 (делитель частоты) опорной частоты 16 МГц. Это жестко запрограммировано в функции. Это определение улучшает внешний вид программы и может быть полезно в некоторых приложениях. Наконец, оно напоминает мне, как я настроил таймер.

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

    Далее подсчитывается значение, перезагружаемое в таймер. Это очень простой подсчет, но требует операций с плавающей точкой. К счастью, нам нужно сделать это только один раз, поскольку операции с плавающей точкой очень дорого обходятся в пересчете на машинное время. Примем, что таймер будет установлен на 2 МГц при каждом счете. Загружаемое значение – это число отсчетов, которое мы хотим произвести при 2 МГц между прерываниями. Вы можете заметить, что я использовал 257 вместо 256 для числа отсчетов в этом выражении. Я знаю, что верное значение – 256, но я получил лучшие результаты с 257. Далее в этой в этой статье я разъясню, почему.

    Следующий участок секретного кода устанавливает таймер в режим 0 и выбирает делитель частоты /8. Режим 0 – это базовый режим таймера, а делитель /8 показывает, как мы получаем счетчик, считающий с частотой 2 МГц или 0,5 мкс на отсчет.

    Далее подключается прерывание по переполнению. После выполнения этого кода микроконтроллер будет вызывать ISR каждый раз, когда счетчик прокрутится от 0xFF до 0×00. Это случится, когда счетчик просчитает от нашего загруженного значения через FF и назад до 00.

    Наконец, мы загружаем значение счетчика в таймер и возвращаем это загруженное значение, чтобы ISR могла использовать его позже.

    Я запускал таймер максимум при 50 кГц. Это очень быстро и любые действия, выполняемые в ISR, значительно тормозят выполнение основной программы. Я не рекомендую использовать частоты свыше 50 кГц, разве что вы почти ничего не делаете в ISR.

    Загрузка микроконтроллера прерываниями

    Чтобы дать вам представление об эффекте, предположим, что таймер ISR запускался бы каждые 20 мкс. Процессор, работающий на 16 МГц, может выполнить около 1 машинной команды каждые 63 нс или около 320 машинных команд для каждого цикла прерывания (20 мкс). Предположим также, что исполнение каждой строки программы на С может занять много машинных команд. Каждая инструкция, используемая в ISR, отнимает время, доступное для исполнения любой другой программы. Если бы наша ISR использовала около 150 машинных циклов, мы сожрали бы половину доступного процессорного времени. При активных прерываниях главная программа откладывалась бы около ½ времени, занимаемого ей в других случаях. 150 машинных команд – не очень большая программа на С, поэтому вы должны быть внимательны.

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

    Измерение загрузки прерываниями

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

    Трюк заключается в том, что таймер хранит время, даже если он переполнен и прерван. В конце нашей ISR мы можем захватить текущее значение счетчика таймера. Это значение представляет то время, которое он отнял у нас до следующей точки программы. Это суммарное время, затраченное на переход в процедуру прерывания и выполнение программы в ISR. Небольшая ошибка будет оттого, что не подсчитывается время, затраченное на команду перезагрузки таймера, но мы можем исправить её эмпирически. Фактически именно поэтому я использовал в формуле подсчета загружаемого значения 257 вместо 256. Я обнаружил опытным путем, что это дает лучший результат. Лишний такт компенсирует команду перезагрузки таймера.

    ATMega8. Таймер счетчик. Прерывание по переполнению

    Прерывание по переполнению не работает
    Я начинающий. Сделал первый девайс на Tiny13. Первую прошивку написал на CAVR. Для отладки.

    Режим CTC, прерывание по переполнению «теряем» обязательно?
    Правильно ли я понимаю, что при работе таймера в режиме CTC, обязательно "теряется" прерывание по.

    Почему не срабатывает прерывание по переполнению таймера Timer/Counter0
    Добрый день! В чем грабли, почему не запускается подпрограмма обработки прерывания по переполнению.

    Как реализовать прерывание по переполнению таймера atmega32a в Atmel Studio 4
    Здравствуйте! Пытаюсь постигнуть таймеры. Но что-то не получается даже простенькое и понять не.

    И тебе привет, господин хороший, например ;о)

    Прежде чем ответить на твой элементарный вопрос, киборг должен таки скромно отметить тот факт, что ты слегка не там пишешь: это форум по ассемблеру MASM, который, к сожалению, не генерит код для Atmel’а — для него есть свой совершенно чудовищный асм, продолжающий убивать маленькава беззащитнава робатега дичайше некошернейшим си-подобным синтаксисом и отсутствием поддержки структур, например ;о)

    Однако само появление твоего поста именно здесь какбе намекаэ нам на его причину: твою невнимательность, по причине которой и не работает твой код, что и явилось причиной опубликования твоего поста не на том форуме (надеюсь всё же, что это была не хитрость, например ;о)

    Теперь к сути вопроса: если бы ты не был столь самоуверен, господин сапровец, то прежде чем писать прогу ты должен был бы обязательно заглянуть в файл m8def.inc, который у тебя включён в самом начале исходника совсем не просто так, в конце которого бы нашёл определение таблицы векторов прерываний:

    И будучи внимательным, увидел бы в ней, что вектор прерывания по переполнению счётчика 2 находится слегка выше (если считать вершиной нулевой адрес ;о) вектора преравания АЦП. А т.к. перед RJMP TIMER_OVF ты не поставил .ORG OVF2addr, то он находится именно _под_ вектором АЦП. На месте же вектора прерывания счётчика 2 находится код FFFF (т.к. после стирания туда ничего не записано), что является кодом команды SBRS.

    Так что контроллер, прыгая на вектор прерывания по переполнению счётчика 2, не находит там адреса твоего обработчика, добирается таки до команды перехода на обработчик АЦП, который успешно и выполняет (хотя, возможно, мог бы его и пропустить — это зависит от содержимого регистра, проверяемого командой SBRS — так что тебе ещё повезло, что это выплыло сразу) — как-то так, например ;о)

    Чтобы такого не случалось, очень желательно было бы не экономить крохами байты исходника и не дёргать из таблицы векторов прерываний куски, а не полениться и включить её целиком в прогу, поставив на вектора неиспольумых прерываний, которые могут быть включены только по ошибке, хотя бы заглушки RETI — это на худой конец (а на толстый — обработчик нештатных ситуаций, например ;о)

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

    Такие дела, господин сапровец, такие дела (короче — не будь коекакером, например ;о)

    Прерывания по переполнению таймера-счётчика

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

    Если запрос на прерывание вырабатывается внутри контроллера – его функциональными блоками или процессором, то такое прерывание называют внутренним. Одним из источников внутренних прерываний являются таймеры-счётчики.

    Контроллер ATmega8 имеет следующие таймеры:

    v T/C0 (Timer/Counter0) – 8-разрядный таймер-счётчик, имеющий предделитель частоты и режим сравнения;

    v T/C1 (Timer/Counter0) – 16-разрядный таймер-счётчик, имеющий все основные режимы работы таймеров-счётчиков, в том числе режим захвата событий;

    v T/C2 (Timer/Counter0) – 8-разрядный таймер-счётчик, имеющий предделитель частоты, режим сравнения и режим широтно-импульсной модуляции (ШИМ).

    v WDT (Watch Dog Timer) – сторожевой таймер, имеющий предделитель частоты и собственный генератор с частотой 1 МГц.

    На этом практическом занятии рассмотрим задание прерывания по переполнению T/C0 и его обработку. Счётный 8-битный регистр TCNT0 (Timer/Counter0) этого таймера хранит текущую сумму импульсов от предделителя частоты. При переходе содержимого этого регистра с 255 к 0 наступает переполнение T/C0, что и вызывает так называемое прерывание по переполнению T/C0. Этот регистр доступен по чтению и по записи в любой момент времени.

    Для инициализации прерывания по переполнению необходимо установить бит разрешения прерывания TOIE0 (Timer/Counter0 Overflow Interrupt Enable) в регистре масок прерываний TIMSK (Timer/Counter Interrupt Mask Register) и задать коэффициент предварительного деления частоты PRESCALER в регистре управления таймером-счётчиком TCCR0 (Timer/Counter Control Register0). На рисунках 2.3.1 и 2.3.2 описаны биты регистров TIMSK и TCCR0 соответственно. Биты выбора CS (Clock Select) источника тактирования описаны в Таблице 2.3.1.

    Таблица 2.3.1. Описание битов выбора источника тактирования

    CS02CS01CS00Описание
    Нет источника (T/C0 – остановлен)
    Источник – тактовый генератор с fтакт
    Источник – тактовый генератор с fтакт/8
    Источник – тактовый генератор с fтакт/64
    Источник – тактовый генератор с fтакт/256
    Источник – тактовый генератор с fтакт/1024
    Источник – спадающий фронт импульсов на линии T0
    Источник – возрастающий фронт импульсов на линии T0

    Как видно из таблицы мы можем выбирать всего пять коэффициентов предварительного делителя частоты. Время до срабатывания прерывания можно оценить по суммарной длительности импульсов тактового генератора, которые заполнят регистр TCNT0 от 0 до 255, т.е. всего 256 (таймер у нас 8-битный). Для этого надо выбранный из Таблицы 1 коэффициент предделителя частоты умножить на число 256 и разделить на тактовую частоту генератора fтакт.

    Например, пусть fтакт = 8МГц, коэффициент предделителя PRESCALER = 010, т.е. тактовая частота делится на восемь (к регистру TCNT0 будет проходить только каждый восьмой импульс от генератора). Значит время до срабатывания прерывания T

    T = 8*256 / 8*10 6 = 0,000256 сек.

    Таким образом, время срабатывания прерывания равно 256 микросекундам. Для увеличения этого времени надо увеличить коэффициент предделителя. К примеру, при PRESCALER = 101, T = 0,032768 сек.

    Пример 2.3.1. Рассмотрим задачу управления группой реле с помощью прерывания по переполнению T/C0. На рис. 2.3.3 изображена схема подключения шести реле Р1-Р6 к линиям порта B через схему ULN2003A, содержащую семь транзисторных ключей на составных транзисторах (схема Дарлингтона), шесть из которых нами используются, а один – нет. Они позволяют управлять нагрузкой до 500 mA при напряжении Uпит до 50 В. Внутри этой микросхемы уже имеется встроенный защитный диод, который можно подключать или отключать, осуществляя внешние соединения. На листинге 2.3.1 представлена программа подачи напряжения на управляющие обмотки реле Р1-Р6 на строго заданное время T = 0,016 сек., по истечению которого напряжение снимается. Включение реле производится подачей на соответствующую линию порта B логической единицы. Отключается реле логическим нулём.

    В начале программы расписана таблица векторов прерываний, в которой инициализируются только два прерывания: INIT – для инициализации контроллера при подаче питания и TIM0_OVF – для обработки прерывания по переполнению разрядной сетки таймера-счётчика T/C0. Процедура ERROR обслуживает остальные прерывания, если они случайно возникнут.

    Далее в программе задаётся коэффициент предделителя частоты в шестнадцатеричном представлении PRESCALER = 0x04, то есть fтакт/256. На тактовой частоте 4 Мгц такой предделитель обеспечит время срабатывания T = 0,016384 сек.

    .INCLUDE "m8def.inc" ; AtMega8 definitions

    .ORG 0x00 rjmp INIT ; начальные установки

    .ORG INT0addr rjmp ERROR ; ловушка для всех

    .ORG INT1addr rjmp ERROR ; неинициализированных прерываний

    .ORG OC2addr rjmp ERROR

    .ORG OVF2addr rjmp ERROR

    .ORG ICP1addr rjmp ERROR

    .ORG OC1Aaddr rjmp ERROR

    .ORG OC1Baddr rjmp ERROR

    .ORG OVF1addr rjmp ERROR

    .ORG OVF0addr rjmp TIM0_OVF ; прерывание Timer/Counter0

    .ORG SPIaddr rjmp ERROR

    .ORG URXCaddr rjmp ERROR

    .ORG UDREaddr rjmp ERROR

    .ORG UTXCaddr rjmp ERROR

    .ORG ADCCaddr rjmp ERROR

    .ORG ERDYaddr rjmp ERROR

    .ORG ACIaddr rjmp ERROR

    .ORG TWIaddr rjmp ERROR

    .ORG SPMRaddr rjmp ERROR

    ERROR: rjmp ERROR ; бесконечный цикл ловушки

    .EQU PRESCALER = 0x04 ; настройка делителя таймера

    Cli ; запрет прерываний

    ldi r16,high(RAMEND) ; указ-ль стека на последний байт ОЗУ

    out DDRB,r16 ; инициализируем порт B на вывод

    out PORTB,r16 ; снимаем напряжение с реле

    ldi r16,0x01 ; TOIE0=1

    out TIMSK,r16 ; прерывание по переполнению регистра TCNT0

    out TCCR0,r16 ; включаем прерывание от Timer/Counter0

    out PORTB,r16 ; подаём напряжение на реле

    sei ; разрешаем прерывания

    out PORTB,r16 ; снимаем напряжение с реле

    out TCCR0,r16 ; отключаем прерывание от Timer/Counter0

    Скопируйте указанную программу в окно редактора исходного текста, ассемблируйте и запустите отладчик (рис. 2.3.4). Так как в нашей программе используется порт B для взаимодействия с группой реле Р1-Р6 и таймер-счётчик T/C0, то для удобства просмотра регистров порта B и регистров таймера T/C0 отобразим их на панели регистров. Для этого щёлкнем по порту B на панели модулей и, удерживая клавишу CTRL, щёлкнем по таймеру-счётчику T/C0, добавив тем самым регистры таймера к регистрам порта на панели регистров (рис. 2.3.4).

    Делать пошаговое выполнение мы не будем, так как для этого потребуется нащёлкать мышкой несколько тысяч тактов генератора. Поэтому вначале поставим курсор перед основным циклом программы – командой sei и выполним нашу программу до указанного положения курсора с помощью пункта меню Debug ® Run to Cursor или кнопкой на панели инструментов, указанной на рис. 2.3.4. На рисунке 2.3.5 представлен внешний вид программы и содержимое регистров контроллера по достижении курсора.

    Для того чтобы убедиться, что контроллер накапливает сумму тактов в регистре TCNT0, выполним несколько тактов вручную с помощью клавиши F11 или соответствующей кнопки на панели инструментов. Удерживайте клавишу F11 и наблюдайте за увеличением счётчика тактов. На 257 такте в счётчик TCNT0 запишется первая единица.

    На рисунке 2.3.6 показано содержимое регистров после выполнения 259 тактов. Команда sei устанавливает флаг разрешения прерываний и далее программа входит в основной цикл, где и будет выполняться до тех пор, пока счётчик таймера T/C0 досчитав от 0 до 255 и вернувшись на 0, вызовет прерывание TIM0_OVF. Однако на данный момент времени счётчик таймера равен единице. Этот счётчик будет инкрементироваться каждые 256 тактов тактовой частоты, так как константой PRESCALER мы задали деление тактовой частоты на 256.

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

    Как можно увидеть (рис. 2.3.7) счётчик тактов стал равен 65544. Таким образом, программа ожидала прерывания, включив реле, 65544‑16=65528 тактов. Тактовая частота процессора равна 4 МГц. Следовательно, прошло ровно 65528/4000000 = 0,016382 сек. или »16 мс.

    Выполнив вручную по шагам процедуру TIM0_OVF вплоть до возвращения в основной цикл программы (рис. 2.3.8) можно увидеть, как сначала отключаются все реле, потом запрещается прерывания таймера T/C0, потом по команде возврата из прерывания устанавливается флаг разрешения прерываний.

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

    Задание 2.3.1. Разработать электрическую схему и программу подачи питания на управляющие обмотки 12 маломощных реле на 0,065536 сек. (65мс.) по включении контроллера.

    Задание 2.3.2. Разработать электрическую схему и программу для управления реле, которое должно попеременно включаться и отключаться с периодом 130 мс. (65 мс. + 65мс.) и скважностью 1/2.

    Задание 2.3.3. Разработать электрическую схему и программу для управления тремя светодиодами, которые должны включаться и отключаться с периодом 4 сек. и скважностью 1/2. Подсказка: организуйте дополнительный цикл, который будет считать нужное количество срабатываний прерываний по переполнению таймера.

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