При программировании на Си Вы должны обязательно реализовать следующие этапы записи исходного текста:
1. При написании программы обработки прерывания на Си, имя подпрограммы обработки прерывания должно быть объявлено с использованием специальной директивы препроцессора. В компиляторе ImageCraft ICC12 для этой цели следует использовать директиву #pragma:
#pragma interrupt_handler
В поле
2. Далее по тексту подпрограмма прерывания оформляется как обычная функция. Компилятор в процессе перевода исходного текста этой функции на Си в инструкции ассемблера автоматически подставит в конце подпрограммы команду возврата из прерывания RTI, потому что эта функция была объявлена подпрограммой прерывания (директива #pragma на этапе 1).
3. Для правильного функционирования МК в процессе прерывания необходимо инициализировать указатель стека. Его значение должно быть равно старшему адресу области оперативной памяти МК, увеличенному на единицу. Поскольку диапазоны памяти пользователя (как постоянной, так и оперативной) являются необходимыми установками в конфигурации компилятора, то функция инициализации указателя стека выполняется компилятором автоматически. Поэтому программист не должен записывать какой либо текст в программе для инициализации указателя стека. Зато следует проверить карту памяти в установках компилятора, которая обязательно должна совпадать с реальной проектируемой системой.
4. Подсистема прерывания будет функционировать корректно, если для нее сформирована таблица векторов прерывания. Мы уже обсуждали, что таблица векторов прерывания в МК B32 находится в области Flash-памяти, которая защищена от перезаписи информации. Для того, чтобы пользователь имел возможность записать собственную таблицу векторов сброса и прерывания, в эту нестираемую область памяти записаны фиксированные вектора, которые передают управление по известным адресам в области перезаписываемой EEPROM памяти (см. рис. 4.19). По этим адресам программист должен вписать команду безусловного перехода JMP с адресом соответствующей подпрограммы обработки прерывания.
5. Каждый маскируемый источник запроса на прерывание должен быть разрешен установкой соответствующего бита в регистре управления периферийного модуля. Мы рассмотрим, как это записать на Си в последующих примерах.
6. После установки всех индивидуальных битов на разрешение прерывания, необходимо сбросить глобальную маску прерывания I. На ассемблере для этого используют команду CLI. При программировании на Си мы также воспользуемся этой командой, посредством следующих макросов:
#define CLI() asm("cli\n"); //разрешить маскируемые прерывания
#define SEI() asm("sei\n"); //запретить маскируемые прерывания
Далее по тексту программы, если необходимо разрешить прерывания, то следует ввести CLI().
Ниже приведен пример инициализации подсистемы прерывания. Полную запись исходного текста программы с прерываниями мы рассмотрим после обсуждения модуля таймера.
//объявление функции в модуле
void toggle_isr(void);
//директива #pragma для указания, что функция является подпрограммой
//обслуживания прерывания
#pragma interrupt_handler toggle_isr
//инициализация соответствующего вектора в таблице векторов прерываний
#pragma abs_address: 0xF7EA
//В32 RAМ based vector address
void (*Timer_Channel_2_interrupt_vector[])()={toggle_isr};
#pragma end_abs_address
4.13. Система тактирования
Микроконтроллеры семейства 68HC12/HCS12 имеют в своем составе модуль генератора CGM (Clock Generation Module), который генерирует импульсные последовательности для тактирования центрального процессора, межмодульных магистралей, периферийных модулей в составе МК, а также внешние периферийные интегральные схемы. Структурная схема модуля CGM представлена на рис. 4.23.
Рис. 4.23. Структура модуля тактирования CGM
Микроконтроллеры семейства 68HC12/HCS12 используют три внутренних сигнала тактирования: TCLK, ECLK и PCLK. Эти сигналы образуются путем деления эталонной импульсной последовательности внутреннего генератора с внешним кварцевым резонатором. Сигнал TCLK предназначен для тактирования центрального процессора, импульсные последовательности ECLK и PCLK используются для тактирования межмодульных магистралей и различных периферийных модулей (рис. 4.23). Модуль тактирования CGM микроконтроллера B32 оснащен также дополнительным делителем, который позволяет существенно снизить частоту одной из импульсных последовательностей тактирования. Низкая частота тактирования таймерных модулей в некоторых применениях позволяет значительно упростить управляющую программу.
4.13.1.Система тактирования отладочной платы MC68HC912B32EVB
Микроконтроллер в составе платы отладки MC68HC912B32EVB тактируется от внешнего кварцевого резонатора с частотой 16 МГц. В модуле генератора CGM эта частота делится на 2, образуя импульсную последовательность для тактирования центрального процессора и межмодульных магистралей микроконтроллера с частотой 8 МГц. Эта же импульсная последовательность используется для тактирования всех периферийных модулей микроконтроллера: таймера, контроллеров последовательного обмена, АЦП. Многие периферийные модули обладают собственным делителем частоты. Этот делитель позволяет создать собственную внутреннюю частоту тактирования модуля, которая может не коррелироваться с частотами других модулей. Это удобно при проектировании.
Кварцевый резонатор может быть отключен от входа МК посредством переключателей на плате MC68HC912B32EVB. Вместо кварцевого резонатора для тактирования МК может быть использован внешний генератор или керамический резонатор. Последний обладает меньшей, чем кварцевый резонатор, стабильностью частоты, однако он является более дешевым компонентом. Мы не будем вносить каких-либо изменений в схемотехнику платы MC68HC912B32EVB. Поэтому далее на протяжении всей книги частота внутренней шины и центрального процессора МК будет составлять 8 МГц. Частота внутренней шины МК может быть понижена дополнительным делителем модуля CGM (рис. 4.23). Его коэффициент деления назначается под управлением программы и может составлять 1, 2, 4, …, 128. Для выбора желаемого коэффициента деления необходимо записать соответствующий таблице рис. 4.24 код в разряды SLDV2…SLDV0 регистра управления дополнительным делителем SLOW. Формат этого регистра приведен на рис. 4.24.
Выбор пониженной частоты межмодульных магистралей МК
SLDV[2:0] | Коэффициент деления 2х | При частоте внешнего кварцевого резонатора | ||
---|---|---|---|---|
16 МГц | 8 МГц | 4 МГц | ||
000 | 1 | 8 МГц | 4 МГц | 2 МГц |
001 | 2 | 4 МГц | 2 МГц | 1 МГц |
010 | 4 | 2 МГц | 1 МГц | 500 кГц |
011 | 8 | 1 МГц | 500 кГц | 250 кГц |
100 | 16 | 500 кГц | 250 кГц | 125 кГц |
101 | 32 | 250 кГц | 125 кГц | 62,5 кГц |
110 | 64 | 125 кГц | 62,5 кГц | 31,2 кГц |
111 | 128 | 62,5 кГц | 31,2 кГц | 15,6 кГц |
Рис. 4.24. Формат регистра SLOW
Вы можете заинтересоваться, а зачем понижать частоту тактирования МК? Ведь тогда снизится его вычислительная производительность. Дело в том, что энергия потребления МК пропорциональна частоте его тактирования. Поэтому для достаточно медленных приложений, которые не требуют большой вычислительной производительности, частоту тактирования можно снизить ради экономии энергопотребления устройства управления. Понижение частоты тактирования возможно также для формирования таймерами необходимых временных интервалов. Например, если снизить частоту тактирования до 62,5 КГц (SLDV2…SLDV0 = 111), то период переполнения счетчика временной базы будет составлять около 1 с.
4.14. Подсистема реального времени — модуль таймера
Подсистема реального времени МК семейства 68HC12/HCS12 включает основной таймерный модуль, который имеет две модификации — TIM и ECT, и отдельный таймер меток реального времени.
Структура модуля таймера TIM (Timer Interface Module) ориентирована на реализацию трех основных функций:
• Входного захвата (IC — Input Capture). Функция входного захвата позволяет производить измерения временных параметров сразу нескольких импульсных сигналов на входах МК. Подсистема входного захвата может быть настроена на измерение длительности единичного или нулевого состояния на входе порта (рис. 4.25, а), а также периода, коэффициента заполнения или частоты периодического импульсного сигнала (рис. 4.25, б).
(а)
(б)
Рис. 4.25. Временные характеристики ШИМ сигнала
• Выходного сравнения (OC — Output Compare). Функция выходного сравнения позволяет МК генерировать на нескольких выходах импульсные последовательности с заданными временными характеристиками, такими, как период и коэффициент заполнения для повторяющихся сигналов, длительность единичного или нулевого состояния для неповторяющихся сигналов.
• Счетчика внешних событий (PA — Pulse Accumulator). Основная функция этого счетчика — подсчет импульсов (внешних событий) на одном из входов МК. Он также может быть использован для измерения временных параметров внешнего импульсного сигнала большой длительности.
Для реализации функций входного захвата/выходного сравнения (IC/OC) модуль таймера TIM использует восемь идентичных аппаратных блоков, которые принято называть каналами. Каждый из каналов посредством программных установок настраивается на реализацию режима входного захвата или выходного сравнения независимо от режима работы других каналов модуля таймера. Каждый из каналов использует общий счетчик временной базы для фиксации моментов наступления событий. Параллельная работа всех восьми каналов с одним счетчиком временной базы не вносит погрешностей в формируемые или измеряемые временные интервалы, поскольку фиксация этих интервалов реализуется на аппаратном уровне с последующим программным обслуживанием каналов по прерываниям. Каждый канал связан с одной из линий порта PORT Т. Счетчик событий PA в составе модуля TIM также связан с линией 7 порта PORT T. Поэтому линии 0…6 порта PORT T в подсистеме таймера могут использоваться или как входы IC, или как выходы OC, в то время как линия 7 порта PORT T кроме этих двух функций IC/OC может также использоваться как вход тактовых импульсов для счетчика внешних событий.
4.14.1. Структура модуля таймера
Структурная схема модуля таймера представлена на рис. 4.26. При ее первичном рассмотрении она кажется запутанной и сложной. Для облегчения понимания мы выделим в составе таймера три блока: блок счетчика временной базы (1), восемь каналов с функциями IC/OC (2), блок счетчика внешних событий (3). Далее мы рассмотрим каждый из этих блоков отдельно, и для каждого из них приведем более понятные структурные схемы.
Рис. 4.26. Структура модуля таймера
4.14.2. Счетчик временной базы
Основным блоком модуля таймера TIM является 16 разрядный счетчик временной базы TCNT, структурная схема которого представлена на рис. 4.27. Текущий код счетчика используется всеми каналами захвата/сравнения в качестве отсчета момента реального времени. Именно поэтому этот счетчик и называют счетчиком временной базы. Этот счетчик также называют свободно считающим счетчиком. Определение «свободно считающий» отражает следующую особенность работы счетчика. Если работа модуля таймера разрешена, то счетчик временной базы производит непрерывный счет, начиная с минимального кода $0000 до максимального кода $FFFF. При поступлении следующего тактового импульса код счетчика изменяется с $FFFF на $0000. Далее счет продолжается в порядке нарастания кода. Невозможно остановить счетчик под управлением программы, так же как и изменить коэффициент счета счетчика, равный 216. Текущее состояние счетчика отображается в двух 8-разрядных регистрах: TCNTH — старший байт счетчика, TCNTL — младший байт счетчика. В карте памяти МК эти регистры располагаются по следующим адресам: $0084 — TCNTH, $0085 — TCNTL. Вместе оба этих регистра составляют 16-разрядный регистр текущего состояния счетчика временной базы TCNT. Имя TCNT обычно объявляется в заголовочном файле.
Рис. 4.27. Структура и регистры управления счетчика временной базы модуля таймера
Счетчик временной базы тактируется импульсной последовательностью с выхода мультиплексора MUX. Ко входам мультиплексора подключены четыре источника тактирования: основная импульсная последовательность с выхода делителя частоты и дополнительные сигналы PACLK, PACLK/256, PACLK/65536. На вход программируемого делителя частоты подключен сигнал PCLK с выхода подсистемы тактирования. Частота следования импульсов на линии PCLK равна частоте тактирования межмодульных магистралей МК. Коэффициент деления программируемого делителя частоты определяется разрядами PR2…PR0 регистра масок таймера 2 (TMSK2). Формат регистра TMSK2 приведен на рис. 4.27. Таблица соответствия численного значения коэффициента деления двоичной комбинации разрядов PR2…PR0 представлена на рис. 4.28.
PR[2:1:0] | Коэффициент деления |
---|---|
000 | 1 |
001 | 2 |
010 | 4 |
011 | 8 |
100 | 16 |
101 | 32 |
110 | зарезервирован |
111 | зарезервирован |
Рис. 4.28. Выбор коэффициента программируемого делителя для счетчика временной базы
Величина коэффициента деления определяет длительность периода переполнения счетчика временной базы. Поскольку разрядность счетчика равна 16, то коэффициент счета этого двоичного счетчика равен 216 или 65356. Минимальный период переполнения счетчика составляет 8169 мс (216 импульсов × 1/8 МГц), поскольку максимальная частота импульсной последовательности PCLK, равная частоте тактирования межмодульных магистралей, составляет 8 МГц. Однако при задании максимального коэффициента деления, равного 32 (см. таблицу рис. 4.28), период переполнения счетчика составит уже 262424 мс (216 импульсов × 32/8 МГц).
В некоторых приложениях необходимо формировать временные интервалы, значительно превышающие приведенные расчетные значения. Этого можно достигнуть путем снижения частоты тактирования счетчика временной базы.
Однако уменьшение частоты импульсной последовательности PCLK связано со снижением производительности процессорного ядра. Поэтому для счетчика временной базы предусмотрены три альтернативных источника тактирования PACLK, PACLK/256, PACLK/65536. Выбор одного из четырех источников тактирования осуществляется двухразрядным кодом CLK1:CLK0 в регистре управления счетчиком внешних событий PACL. Формат регистра PACL представлен на рис. 4.27.
Если длительность измеряемых или формируемых микроконтроллером временных интервалов превышает период переполнения счетчика временной базы, то возникает необходимость в подсчете числа периодов переполнения этого счетчика. При достижении максимального кода $FFFF счетчик не останавливается, он продолжает считать дальше. Поэтому при поступлении следующего тактового импульса в счетчике установится код $0000. Такое изменение кода называется событием переполнения счетчика и фиксируется установкой бита TOF в регистре управления счетчиком TFLG2 (рис. 4.27). Триггер TOF называют триггером переполнения счетчика. Этот триггер может быть считан под управлением программы, или, если прерывания по событию переполнения счетчика разрешены, то установленный в 1 триггер TOF генерирует запрос на прерывание. Прерывание по переполнению счетчика временной базы имеет свой собственный вектор и собственный бит разрешения прерывания TOI в регистре TMSK2 (рис. 4.27).
Если код счетчика временной базы изменился с $FFFF на $0000, то триггер TOF устанавливается в 1. При использовании этого флага для вызова прерываний следует позаботиться о том, чтобы флаг был сброшен под управлением подпрограммы прерывания до наступления следующего переполнения таймера. Для сброса (установки в 0) флага TOF следует записать 1 в бит 7 регистра TMSK2, т.е. выполнить любую команду установки в 1 этого флага. Вышесказанное не ошибка! Большинство флагов регистров специальных функций МК семейства 68HC12/HCS12, генерирующих разнообразные запросы на прерывание, сбрасываются в 0 посредством записи 1 в находящийся в состоянии 1 бит флага. Мы обсудим ниже варианты программного кода, которые могут быть использованы для сброса различных флагов, в том числе и флага переполнения счетчика временной базы.
Если в прикладной задаче необходимо измерить временной интервал, значительно превышающий по длительности период переполнения счетчика временной базы, то следует организовать дополнительный счетчик в одной из ячеек памяти. Содержимое этого счетчика будет инкрементироваться подпрограммой прерывания при каждом переполнении счетчика.
Во многих приложениях возникает необходимость определения длительности временного интервала между двумя изменениями сигнала на одной из линий порта. Эта задача может быть решена двумя способами.
При первом способе счетчик временной базы сбрасывается в момент первого изменения сигнала. Обнуление счетчика можно произвести в подпрограмме прерывания по событию входного захвата, которое соответствует первому изменению исследуемого сигнала. В этой же подпрограмме подсистема входного захвата перепрограммируется на детектирование второго события в исследуемом сигнале. Счетчик временной базы продолжает наращивать код. В момент второго изменения сигнала, которое фиксирует подсистема входного захвата, текущий код счетчика запоминается в специальном двухбайтовом регистре. Если в процессе слежения за сигналом переполнений счетчика временной базы не было, то запомненный код и есть искомая длительность временного интервала, выраженная в числе периодов частоты тактирования счетчика временной базы.
При втором способе счетчик временной базы считает непрерывно, он никогда принудительно не обнуляется. В момент первого изменения сигнала подсистема входного захвата запоминает текущее значение кода счетчика временной базы в регистре и генерирует запрос на прерывание. В подпрограмме прерывания по событию входного захвата этот двухбайтовый код программно считывается и запоминается в оперативной памяти МК под именем Start. В этой же подпрограмме подсистема входного захвата перенастраивается на детектирование второго изменения сигнала. Когда это событие происходит, подсистема входного захвата опять запоминает новое текущее значение кода счетчика временной базы и генерирует запрос на прерывание. В подпрограмме прерывания новый код счетчика запоминается под именем Stop. Если в процессе слежения за сигналом переполнений счетчика временной базы не было, то искомая длительность временного интервала, выраженная в числе периодов частоты тактирования счетчика временной базы, определяется как (Stop – Start).
а) Вариант 1: Код Stop > Код Start, переполнений счетчика временной базы за время измерения не было
б) Вариант 2: Код Start > Код Stop, за время измерения было одно переполнение счетчика временной базы
в) Вариант 3: Код Stop > Код Start, за время измерения было N переполнений счетчика временной базы
г) Вариант 4: Код Start > Код Stop, за время измерения было N переполнений счетчика временной базы
д) Вариант 5: Код Start = Код Stop, за время измерения было N переполнений счетчика временной базы
Рис. 4.29. Диаграммы, поясняющие преобразования кодов для расчета длительности измеряемого временного интервала
Опытный разработчик всегда использует второй способ. По отношению к первому способу он обладает двумя преимуществами:
• Необходимое в первом способе обнуление счетчика может вызвать нарушение правильной работы других каналов таймера, которые также используют для отсчета временных интервалов код счетчика временной базы. Второй способ не нарушает естественный порядок счета счетчика временной базы, и, следовательно, создает «комфортные» условия для работы оставшихся семи каналов модуля таймера.
• Второй способ обладает большей точностью. При первом способе момент первого изменения сигнала отмечается нулевым кодом счетчика, который будет установлен только после перехода к подпрограмме прерывания. Этот процесс может занять от 10 до 20 тактов fBUS. При втором способе аппаратные средства подсистемы входного захвата фиксируют первое изменение сигнала аппаратно, и ошибка не будет составлять более одного такта fBUS.
Рассмотрим более подробно вычисление реальной длительности измеряемого сигнала по второму способу. На рис. 4.29 показаны пять возможных ситуаций, в которых подсистемой входного захвата зафиксированы совершенно одинаковые коды начала и конца измеряемого временного интервала. В первом случае (рис. 4.29,а) код Stop превышает код Start, и переполнений счетчика временной базы не было. Тогда очевидно, что измеряемая длительность временного интервала TIME = Stop – Start. Во втором случае (рис. 4.29,б) код Stop меньше, чем код Start, и между изменениями сигнала было всего одно переполнение счетчика временной базы:
TIME = (216 – Start) + Stop = 216 + (Stop – Start)
Рассмотрев остальные случаи (рис. 4.29, в,г,д), можно убедиться, что в каждом из случаев расчет искомого временного интервала следует вести по формуле:
TIME = 216 × n + (Stop – Start),
где n — число переполнений счетчика временной базы, которое случилось между двумя событиями фиксации изменения сигнала подсистемой входного захвата.
Код TIME отражает длительность временного интервала в периодах частоты тактирования счетчика временной базы. Во многих прикладных задачах вычисление реальной длительности в миллисекундах или секундах не производится. Если же это необходимо, то МК должен выполнить дополнительную операцию умножения:
tIZM= TIME × (TCNTclock),
где TCNTclock — период частоты тактирования счетчика временной базы.
Как было отмечено выше, сброс счетчика временной базы крайне нежелателен, поскольку он нарушает естественный порядок счета и может привести к ошибкам в работе подсистем входного захвата или выходного сравнения IC/OC, которые в момент сброса реализуют предназначенные им функции с использованием изменяющегося кода счетчика временной базы. Однако если сброс все таки необходим, то его можно реализовать следующим образом:
• Установить в 1 бит разрешения сброса счетчика TCRE (бит 3) в регистре управления TMSK2;
• Установить в $0000 регистр данных канала 7 модуля таймера. Комбинация этих двух состояний будет удерживать счетчик временной базы в нулевом состоянии.
1. Какова частота тактирования МК на отладочной плате MC68HC912B32EVB?
Ответ: Микроконтроллер B32, установленный на плате MC68HC912B32EVB тактируется от кварцевого резонатора с частотой 16 МГц. Эта частота делится внутренними средствами МК на 2, поэтому частота межмодульных магистралей составляет 8 МГц.
2. С какой целью Вам может понадобиться тактировать МК на с иной, отличной от fBUS= 8 МГц частотой?
Ответ: Энергия потребления МК в процессе работы пропорциональна частоте тактирования. Поэтому снижение частоты тактирования целесообразно с точки зрения уменьшения энергетических потерь. Ряд применений, связанных с электромеханическими нагрузками, не требует предельного быстродействия МК, поэтому частота тактирования может быть снижена.
3. Подсистема входного захвата зафиксировала два различных события в моменты времени, соответствующие кодам $0105 и $EC20 счетчика временной базы. Чему равен интервал времени между этими событиями? Интервал следует указать в единицах счета счетчика, число должно быть представлено в десятичном коде.
Ответ: $EC20 – $0105 = $EB1B = 60187 тактов счетчика
4. Если в предыдущем примере частота на входе программируемого делителя составляет 2 МГц, и биты PR2…PR0 регистра TMSK2 установлены в 000, то каков интервал времени между событиями в мс?
Ответ: Интервал составляет: 60187 1/(2МГц) = 30093,5 мс.
5. Повторите расчет предыдущего вопроса, но при измененных значениях битов PR2…PR0 = 100.
Ответ: В предыдущем случае коэффициент деления программируемого делителя был равен 1. При указанных в данном примере значениях битов PR2…PR0 коэффициент деления составляет 16. Следовательно, интервал времени между событиями составит 30093,5 мс × 16 = 481496 мс.
6. Назовите три основных режима работы модуля таймера TIM?
Ответ: режим входного захвата IC, режим выходного сравнения OC и режим счетчика внешних событий PA.
7. Почему необходимо следить за флагом переполнения счетчика временной базы?
Ответ: При использовании модуля таймера для измерения временных интервалов необходимо знать, сколько раз в процессе измерения переполнился счетчик. В противном случае подсчитанный код будет неверным.
8. Почему разработчик должен быть крайне осторожен при обнулении счетчика временной базы таймера?
Ответ: Сама по себе операция обнуления не представляет сложности. Однако к работающему счетчику временной базы могут быть «привязаны» другие каналы IC/OC. И изменение естественного порядка счета счетчика может привести к неправильной работе этих каналов. Поскольку каналов в модуле таймера восемь, то достаточно трудно предугадать все возможные комбинации их функционирования в реальной задаче. Поэтому во избежание сбоев в работе целесообразно отказаться от обнуления счетчика временной базы.
4.14.3. Регистры для управления счетчиком временной базы
В данном параграфе мы рассмотрим регистры специальных функций модуля таймера, которые используются для управления и определения текущего состояния счетчика временной базы.
Регистр управления модулем таймера TSCR (Timer System Control Register) располагается в памяти МК по адресу $0086. Формат регистра представлен на рис. 4.30. Старший бит регистра TEN разрешает (при TEN=1) или запрещает (при TEN=0) функционирование модуля таймера. Этот бит используется разработчиками для включения или отключения модуля таймера в процессе работы устройства. Отключение модуля полезно с точки зрения снижения потребления энергии, если функции таймера не используются в алгоритме управления. Обратите внимание, что после сброса МК модуль таймера выключен, т.к. бит TEN автоматически устанавливается в 0 в состоянии сброса МК.
Рис. 4.30. Формат регистра TCSR
Бит TFFCA управляет механизмом сброса флагов событий модуля таймера. К этим флагам относятся флаг переполнения таймера TOF, флаги событий в каналах захвата/сравнения IC/OC и флаг переполнения счетчика внешних событий. Если бит TFFCA установлен в 0, то для сброса перечисленных флагов следует использовать обычную процедуру, когда в бит установленного флага под управлением программы записывается 1 (см. раздел 4.14.2, флаг переполнения счетчика). Попытка записи 0 в бит установленного флага оставит флаг без изменения. Если бит TFFCA установлен в 1, то вводится в действие дополнительный механизм сброса рассматриваемых флагов событий:
• Флаг переполнения счетчика временной базы TOF в регистре TFLG2 будет сброшен автоматически при выполнении операции чтения регистра текущего кода счетчика TCNT;
• Флаг события канала захвата/сравнения CnF (n — номер канала) в регистре TFLG1 будет сброшен автоматически при выполнении операции чтения или записи в регистр данных этого канала;
• Флаги PAONF и PAIF счетчика внешних событий в регистре PAFLG будут сброшены автоматически при чтении или записи в регистр PACNT.
Приведенный ниже программный фрагмент демонстрирует код для разрешения работы модуля таймера.
/*-----------------------------------------------------------------*/
/* MAIN PROGRAMM */
/*-----------------------------------------------------------------*/
#include <912b32.h>
void main(void) {
unsigned char TSCR_MASK = 0x80; /*разрешение работы модуля таймера*/
TSCR = TSCR_MASK;
}
/*------------------------------------------------------------------*/
Если работа модуля таймера разрешена, то счетчик временной базы изменяет свое состояние в порядке естественного счета. Число разрядов счетчика временной базы равно 16, поэтому коэффициент счета счетчика составляет 216. Изменение коэффициента счета не предусмотрено. Счетчик временной базы не возможно остановить, однако его состояние в любой момент времени может быть считано под управлением программы из регистра текущего состояния TCNT (Timer CouNTer register). Регистр TCNT — 16 разрядный, в памяти МК он занимает две ячейки. По адресу $0084 располагается старший байт регистра TCNTH, по адресу $0085 — младший байт регистра TCNTL. Формат регистра представлен на рис. 4.31.
Рис. 4.31. Формат регистра TCNT
Считывание регистра текущего состояния счетчика временной базы следует производить только в 16 разрядном формате, поскольку побайтное чтение может дать неверный результат. Дело в том, что счетчик временной базы может тактироваться максимальной частотой, которая равна fBUS. Каждая операция чтения занимает несколько тактов fBUS, следовательно, две последовательных операции чтения приведут к тому, что старший и младший байты счетчика будут считаны при разных состояниях этого счетчика и вместе составят неверное его состояние (если режим «чтение на лету» не задействован). Приведенный ниже программный фрагмент демонстрирует, как правильно считать состояние счетчика с использованием двухбайтовых переменных.
/*-------------------------------------------------*/
/* MAIN PROGRAMM */
/*-------------------------------------------------*/
#include<912b32.h>
void main(void) {
unsigned int start_time; /*время начала процесса*/
unsigned int stop_time; /*время окончания процесса*/
start_time=TCNT;
stop_time=TCNT;
}
/*-------------------------------------------------*/
Регистр масок таймера TMSK2 (Timer MaSK register 2) располагается в памяти МК по адресу $008D. Формат регистра представлен на рис. 4.32. В данном параграфе мы рассмотрим лишь некоторые биты этого регистра. Бит TCRE разрешает сброс счетчика временной базы таймера (см. раздел 4.14.2, сброс счетчика временной базы). Биты PR2:PR1:PR0 устанавливают коэффициент деления программируемого делителя на входе счетчика временной базы в соответствие с табл. рис. 4.28. Обратите внимание, что минимальный коэффициент деления равен 1, т.е. максимальная частота тактирования счетчика равна fBUS. Максимальный коэффициент деления составляет 32. Биты PUPT и TDRB предназначены для управления схемотехникой входных и выходных буферов линий порта PORT T.
Рис. 4.32. Формат регистра TMSK2
4.14.4. Каналы захвата/сравнения
Модуль таймера TIM содержит в себе восемь идентичных блоков захвата/сравнения, которые в микропроцессорной технике принято именовать каналами захвата/сравнения. Структурная схема аппаратных средств одного канала захвата/сравнения в составе модуля таймера МК семейства 68HC12/HCS12 представлена на рис. 4.33.
Рис. 4.33. Структура одного канала сравнения/захвата таймера и регистр выбора режима работы каналов TIOS
Каждый из восьми каналов захвата/сравнения подключен к выводу IOSn, где n — номер канала, n = 0, 1, 2…7. Если канал с номером n конфигурирован как канал захвата, то вывод IOSn автоматически подключается к одноименной линии PTn порта T. Работа в качестве входов подсистемы входного захвата или выходов подсистемы выходного сравнения является альтернативной функцией порта T. Регистр данных порта T расположен по адресу $00AE.
Реализуемая каналом n модуля таймера функция (входной захват или выходное сравнение) определяется битом IOCn регистра TIOC. Регистр расположен по адресу $0080, формат регистра представлен на рис. 4.33. Если бит IOCn установлен в 1, то канал n работает в режиме выходного сравнения. Если же бит IOCn равен 0, то канал n работает в режиме входного захвата.
Аппаратные средства каждого состоят из 16 разрядного регистра данных канала TCn, 16 разрядных регистра защелки и цифрового компаратора, детектора события, формирователя выходного уровня и триггера события канала (рис. 4.33). Каждый канал использует в качестве эталона реального времени общий для всех каналов счетчик временной базы.
Структура аппаратных средств подсистемы входного захвата IC, которая образуется в результате конфигурирования универсального канала модуля таймера на режим захвата, представлена на рис. 4.34. Подсистема входного захвата запоминает код счетчика временной базы в момент изменения логического сигнала на входе IOSn (n — номер канала). Изменение логического сигнала распознается детектором события, который может быть программно настроен на один из четырех режимов работы:
• Распознавание изменения сигнала с 0 на 1 — положительный фронт;
• Распознавание изменения сигнала с 1 на 0 — отрицательный фронт;
• Распознавание любого изменения уровня сигнала;
• Соответствующий вывод МК не подключен к каналу входного захвата и является выводом порта T.
Рис. 4.34. Структура одного канала таймера в режиме входного захвата и регистры управления каналом TCTL3 и TCTL4
Если детектор определил заданное изменение входного сигнала, то говорят, что наступило событие входного захвата. В момент наступления события код счетчика временной базы запоминается в регистре защелке, одновременно устанавливается триггер события канал CnF (рис. 4.34). Триггер может быть считан программно, или генерируется запрос на прерывание, если прерывания от канала n модуля таймера разрешены.
Для настройки детектора события каждого канала на один из трех перечисленных режимов используются биты EDGnB:EDGnA в регистрах TCTL3 ($008A) и TCTL4 ($008B). Формат этих регистров представлен на рис. 4.34. Таблица рис. 4.35 устанавливает соответствие между режимом работы детектора события и кодом инициализации в разрядах EDGnB:EDGnA.
EDGnB: EDGnA | Режим детектора событий |
---|---|
00 | Входной захват не реализуется |
01 | Мониторинг нарастающего фронта |
10 | Мониторинг спадающего фронта |
11 | Мониторинг изменения уровня |
Рис. 4.35. Выбор режима работы детектора события
Подсистема входного захвата IC используемся в микропроцессорной технике для измерения различных временных характеристик импульсных сигналов, таких как период следования, коэффициент заполнения, длительность нулевого или единичного состояния. Так для того, чтобы измерить период импульсной последовательности, необходимо запомнить состояние счетчика временной базы в моменты двух соседних изменений сигнала с 0 на 1 (положительный фронт) или с 1 на 0 (отрицательный фронт). Разность этих значений и составит период повторения импульсного сигнала, выраженный в числе периодов частоты тактирования счетчика временной базы. Таким образом будет произведено измерение в относительных единицах конкретной микропроцессорной системы. Если измерение производится с целью управления, то представление временного параметра в относительных единицах обычно является достаточным. Однако, если измеренный параметр должен быть отображен на дисплее, то он должен быть представлен в универсальных единицах измерения, т.е. в микросекундах, миллисекундах и т.д. Для получения численного значения последнего необходимо полученное число относительных единиц умножить на длительность периода частоты тактирования счетчика временной базы. При программировании на Си операция умножения реализуется с использованием стандартной библиотеки. При программировании на ассемблере Вам потребуются дополнительные знания, поскольку операцию умножения необходимо будет исполнять над двухбайтовыми числами.
Если детектор события распознал изменение входного сигнала, которое указано в его текущей конфигурации, то аппаратные средства канала входного захвата автоматически совершают следующие действия:
1. Текущее состояние 16-разрядного счетчика временной базы запоминается в регистре-защелке канала и сразу копируется в 16-разрядный регистр данных канала TCn (n — номер канала). Поскольку данные в регистре TCn не изменяются, то они могут быть считаны побайтно (TCnH — старший байт регистра данных канала, TCnL — младший байт регистра данных), или в двухбайтовом формате. При программировании на Си рекомендуется использовать двухбайтовый формат, используя для этого переменную в формате unsigned integer.
2. Устанавливается флаг события канала CnF. Этот флаг «сообщает» основной программе о том, что событие произошло, и регистр данных канала TCn должен быть считан программой.
3. Если прерывания по флагу события CnF разрешены (бит CnI установлен), то генерируется запрос на прерывание.
Подсистема входного захвата может быть настроена для реализации разнообразных функций. Рассмотрим пример измерения длительности единичного состояния входного сигнала, т.е. импульса положительной полярности. Предположим, что длительность импульса не превышает периода переполнения счетчика временной базы таймера, исследуемая импульсная последовательность поступает на вход канала 2 модуля таймера, который предварительно настроен в режим входного захвата. Тогда для измерения длительности импульса должна быть реализована следующая последовательность действий:
1. Управляющая программа устанавливает режим работы детектора событий канала 2. Должен быть выбран режим мониторинга нарастающего фронта входного сигнала. Для этого следует установить биты EDG2B:EDG2A в регистрах TCTL3:TCTL4 в состояние 01.
2. Управляющая программа контролирует состояние триггера события C2F.
3. Если триггер C2F установился в 1, то контролируемый сигнал на линии PT2 изменился с 0 на 1. В момент изменения код счетчика временной базы был автоматически переписан в регистр защелку канала 2. Теперь этот код доступен для чтения из регистра данных TC2.
4. Управляющая программа обнаруживает, что триггер C2F установился. Тогда программа считывает двухбайтовый код из регистра данных канала TC2 и записывает его в двухбайтовую беззнаковую переменную rising_edge.
5. Управляющая программа сбрасывает триггер события C2F посредством записи в бит C2F единицы.
6. Управляющая программа изменяет режим работы детектора событий канала 2. Должен быть выбран режим мониторинга отрицательного фронта входного сигнала. Для этого следует установить биты EDG2B:EDG2A в регистрах TCTL3:TCTL4 в состояние 10.
7. Управляющая программа контролирует состояние триггера события C2F.
8. Если триггер C2F установился в 1, то сигнал на линии PT2 изменился с 1 на 0. В момент изменения код счетчика временной базы был опять автоматически переписан в регистр защелку канала 2.
9. Управляющая программа обнаруживает установленный триггер C2F, считывает двухбайтовый код из регистра данных канала TC2 и записывает его в двухбайтовую беззнаковую переменную falling_edge.
10. Управляющая программа сбрасывает триггер события C2F посредством записи в бит C2F единицы.
11. Управляющая программа вычисляет число периодов частоты тактирования счетчика временной базы между положительным и отрицательным фронтами исследуемого сигнала: TIME = falling_edge – rising_edge. Это число и есть искомая длительность импульса положительной полярности сигнала на входе PT2, выраженная числом периодов частоты тактирования счетчика временной базы.
12. При необходимости длительность импульса может быть представлена в общепринятых единицах измерения времени. Для этого управляющая программа должна выполнить операцию умножения числа TIME на длительность единицы измерения времени таймера, т.е. на длительность периода частоты тактирования счетчика временной базы: tIZM = TIME×1/fBASE.
Регистры специальных функций, связанные с подсистемой входного захвата, мы обсудим позже, после рассмотрения подсистемы выходного сравнения.
1. Какие изменения необходимо внести в рассмотренную выше последовательность действий, чтобы произвести измерение длительности нулевого состояния сигнала на входе PT2?
Ответ: В п.1. следует изменить инициализацию режима работы детектора событий. Должен быть выбран режим мониторинга отрицательного фронта входного сигнала. Также следует внести изменение в п. 6, в котором для детектора событий следует выбрать режим мониторинга нарастающего фронта входного сигнала.
2. Какие изменения необходимо внести для измерения периода повторяемости импульсного сигнала на входе PT2?
Ответ: Рассматриваем изменения исходной последовательности действий, которая приведена в предыдущем параграфе. Пункт 6 последовательности необходимо исключить. Тогда триггер события C2F будет в обоих случаях устанавливаться по положительному фронту исследуемого сигнала. Следовательно, в п.п. 11 и 12 будет вычисляться интервал времени между соседними положительным фронтами сигнала, т.е. период повторяемости этого сигнала.
3. Какие дополнительные изменения по отношению к вопросу 2 необходимо внести для измерения периода повторяемости импульсного сигнала, длительность которого превышает период переполнения счетчика временной базы?
Ответ: Необходимо организовать программный счетчик и вести наблюдение не только за состоянием триггера события канала входного захвата, но и триггера переполнения счетчика временной базы. Если триггер TOF установился. То следует программно инкрементировать программный счетчик. Также следует изменить формулу для подсчета длительности периода.
Подсистема выходного сравнения OC используемся в микропроцессорной технике для генерации на выводах МК импульсных сигналов с заданными временными характеристиками. Например, средствами подсистемы выходного сравнения может быть сформирован одиночный импульс предварительно вычисленной длительности, или импульсная последовательность определенной частоты с регулируемым по результатам расчетов в МК коэффициентом заполнения. Структура аппаратных средств подсистемы выходного сравнения OC, которая образуется после конфигурирования универсального канала модуля таймера на режим сравнения, представлена на рис. 4.36.
Рис. 4.36. Структура одного канала таймера в режиме выходного сравнения и регистры управления каналом TCTL1 и TCTL2
Цифровой компаратор подсистемы выходного сравнения непрерывно сравнивает код счетчика временной базы с 16 разрядным кодом в регистре данных канала TCn (n — номер канала). Момент равенства кодов в микропроцессорной технике называют событием выходного сравнения. Если цифровой компаратор определил равенство кодов, то аппаратные средства канала выходного сравнения автоматически совершают следующие действия:
1. Устанавливается флаг события канала CnF. Обратите внимание, события входного захвата и выходного сравнения отмечаются одним и тем же флагом. Это флаг события канала CnF. Смысловое значение флага (IC или OC) определяется ранее выбранным в процессе инициализации режимом работы канала. Флаг CnF «сообщает» основной программе о том, что событие выходного сравнения произошло, и в регистр данных канала TCn следует записать новое значение кода для сравнения.
2. Если прерывания по флагу события CnF разрешены (бит CnI установлен), то генерируется запрос на прерывание.
3. Формирователь уровня генерирует на выводе канала IOSn предварительно заданный логический уровень. Формирователь уровня в процессе инициализации может быть программно настроен на один из четырех режимов работы:
• Установка вывода в 1;
• Установка вывода в 0;
• Инвертирование уровня сигнала на выводе;
• Соответствующий вывод МК не подключен к каналу выходного сравнения и является выводом порта T.
OMn: OLn | Режим формирователя уровня |
---|---|
00 | Выход формирователя не соединен с выводом IOSn |
01 | Инвертирует сигнал на выходе |
10 | Устанавливает выход в 0 |
11 | Устанавливает выход в 1 |
Рис. 4.37. Выбор режима работы формирователя уровня
Для настройки формирователя уровня каждого канала на один из трех перечисленных режимов работы используются биты OMn:OLn в регистрах TCTL1 ($0088) и TCTL2 ($0089). Формат этих регистров представлен на рис. 4.36. Таблица рис. 4.37 устанавливает соответствие между режимом работы формирователя уровня и кодом инициализации в разрядах OMn:OLn.
Рассмотрим последовательность действий, которая должна быть реализована для генерации средствами подсистемы выходного сравнения «отрицательного» импульса заданной длительности. Под «отрицательным» импульсом мы будем понимать низкий логический уровень сигнала с последующим его изменением на высокий логический уровень.
1. Управляющая программа считывает текущее состояние счетчика временной базы из двухбайтового регистра TCNT.
2. Управляющая программа устанавливает выход используемого канала в 0.
3. Управляющая программа вычисляет длительность временного интервала, в течение которого на выходе должен удерживаться низкий логический уровень. Обратите внимание, полученная длительность временного интервала должна быть представлена в числе периодов тактирования счетчика временной базы.
4. Управляющая программа производит сложение ранее считанного кода счетчика и полученного кода длительности временного интервала. Полученное значение записывается в регистр данных канала выходного сравнения.
5. Управляющая программа задает режим работы формирователя уровня канала. Целесообразно выбрать режим установки выхода в 1, для чего необходимо записать в разряды OMn:OLn регистров TCTL1: TCTL2 комбинацию 11 (см. рис. 4.37).
6. Когда значение кода регистра данных совпадет с кодом счетчика временной базы, на выходе канала выходного сравнения автоматически, без участия программ установится 1.
До настоящего параграфа мы рассматривали все восемь каналов модуля таймера TIM, как полностью идентичные. Однако на самом деле полностью идентичными, работающими или в режиме входного захвата или в режиме выходного сравнения, являются лишь каналы 0…6. Канал 7 в режиме выходного сравнения обладает дополнительными возможностями. При этом рассмотренные режимы захвата/сравнения, совпадающие с режимами каналов 0…6, при соответствующей инициализации им полностью поддерживаются.
Если канал 7 находится в режиме выходного сравнения и его дополнительная функция разрешена, то в момент события в канале 7 устанавливается в назначенное состояние не только выход канала 7, но и любая комбинация выходов каналов 0…6. При этом выбранные для принудительной установки каналы также должны работать в режиме выходного сравнения. Два регистра специальных функций OC7M и OC7D используются для управления режимом принудительной установки по событию в канале 7. Каждый из битов регистра OC7M разрешает (при OC7Mn = 1) режим принудительной установки для одноименного (с номером n) канала. Соответствующий бит в регистре OC7D задает значение, которое должно быть установлено на выходе канала в момент принудительной установки. Например, если в регистре OC7M записан двоичный код 10110001, а в регистре OC7D – 01010101, то с каналом 7 в режиме принудительной установки будут связаны каналы 0, 4, 5. Тогда в момент события выходного сравнения на выходе канала 0 установится 1, на выходе канала 4 установится также 1, на выходе канала 5 установится 0 и на выходе канала 7 — тоже 0. На остальные каналы событие выходного сравнения в канале 7 влияния не окажет.
Свойство принудительной установки позволяет два раза за период работы счетчика временной базы изменять состояние на выходах каналов 0…6. Один раз по собственному событию выходного сравнения канала, второй раз — по событию в канале 7.
В данном разделе мы рассмотрим регистры специальных функций, которые используются для управления режимами работы универсальных каналов захвата/сравнения. Формат регистров управления счетчиком временной базы в составе модуля таймера был рассмотрены ранее.
Регистр режимов каналов захвата/сравнения TIOS (Timer Input capture/Output compare Register) располагается в памяти МК по адресу $0080. Формат регистра представлен на рис. 4.38. Каждый из битов регистра IOSn определяет режим работы канала с номером n. Если бит установлен в 1, то канал работает в режиме выходного сравнения. Если бит равен 0, то канал настроен на режим входного захвата.
Рис. 4.38. Формат дополнительных регистров управления таймером: TIOS, CFORC, OC7M, OC7D
Регистр принудительного события выходного сравнения CFORC (Timer Compare Force Register) располагается в памяти МК по адресу $0081. Формат регистра представлен на рис. 4.38. Установка бита FOCn в 1 немедленно вызывает событие выходного сравнения в канале с номером n, независимо от текущего состояния счетчика временной базы и регистра данных канала. Функция принудительной установки очень удобна для задания начального уровня выхода канала выходного сравнения.
Регистр разрешения работы под управлением канала 7 OC7M (Timer Output Compare 7 Mask Register) располагается в памяти МК по адресу $0082. Формат регистра представлен на рис. 4.38. Каждый из битов регистра OC7M разрешает (при OC7Mn = 1) режим принудительной установки для одноименного (с номером n) канала по событию в канале выходного сравнения 7. Если бит OC7Mn = 0, то канал с номером n работает в автономном режиме.
Регистр установки данных под управлением канала 7 OC7D (Timer Output Compare 7 Data Register) располагается в памяти МК по адресу $0083. Формат регистра представлен на рис. 4.38. Каждый из битов регистра OC7Dn задает значение, которое должно быть установлено на выходе канала с номером n в момент в момент события выходного сравнения в канале 7. При этом необходимо предварительно разрешить работу желаемых каналов под управлением канала 7 установкой соответствующих битов в регистре OC7M.
Регистры управления таймером TCTL1 и TCTL2 (Timer Control Register) располагаются в памяти МК по адресам $0088 и $0089. Форматы регистров приведены на рис. 4.39. Каждому каналу таймера поставлены в соответствие два бита OMn:OLn регистров TCTL1 и TCTL2. Биты OMn:OLn определяют один из четырех режимов работы формирователя уровня канала, если этот канал работает в режиме выходного сравнения. Комбинации кодов для битов OMn:OLn приведены на рис. 4.37.
Рис. 4.39. Формат основных регистров управления таймером:TCTL1, TCTL2, TCTL3, TCTL4
Регистры управления таймером TCTL3 и TCTL4 (Timer Control Register) располагаются в памяти МК по адресам $008A и $008B. Форматы регистров приведены на рис. 4.39. Каждому каналу таймера поставлены в соответствие два бита EDGnB:EDGnA регистров TCTL3 и TCTL4. Биты EDGnB:EDGnA определяют один из четырех режимов работы детектора события канала, если этот канал работает в режиме входного захвата. Комбинации кодов для битов EDGnB:EDGnA приведены на рис. 4.35.
Регистр масок таймера TMSK1 (Timer Mask Register 1) располагается в памяти МК по адресу $008C. Формат регистра приведен на рис. 4.40. Каждый бит этого регистра CnI разрешает или запрещает прерывания по событию в одноименном (с номером n) канале таймера. Если бит CnI равен 1, то прерывания разрешены. При CnI = 0 прерывания по событию в канале запрещены.
Рис. 4.40. Формат регистров масок таймера:TMSK1, TMSK2
Регистр масок таймера TMSK2 (Timer Mask Register 2) располагается в памяти МК по адресу $008D. Формат регистра приведен на рис. 4.40. Бит TOI разрешает прерывания по флагу переполнения счетчика временной базы TOF. Бит TCRE разрешает сброс счетчика временной базы (см. раздел 4.14.2, сброс счетчика временной базы). Биты PR2:PR1:PR0 устанавливают коэффициент деления программируемого делителя на входе счетчика временной базы в соответствие с табл. рис. 4.28.
Регистр флагов таймера TFLG1 (Timer Flag Register 1) располагается в памяти МК по адресу $008E. Формат регистра представлен на рис. 4.41. Каждому каналу таймера поставлен в соответствие флаг события CnF. Флаг CnF устанавливается в 1 автоматически, если в канале произошло событие входного захвата или выходного сравнения, в зависимости от текущего режима работы канала. Установленный бит события CnF вызовет прерывание, если в регистре TMSK1 установлен одноименный бит разрешения прерывания. Флаг события CnF должен быть сброшен под управлением программы, для чего в бит CnF должна быть записана 1. Существует альтернативный способ для сброса флагов события CnF. Если бит TFFCA в регистре TSCR установлен, то чтение или запись в регистр данных канала автоматически сбрасывает бит события этого канала.
Рис. 4.41. Формат регистров флагов таймера:TFLG1, TFLG2
Регистр флагов таймера TFLG2 (Timer Flag Register 2) располагается в памяти МК по адресу $008F. Формат регистра представлен на рис. 4.41. В регистре присутствует всего один флаг — флаг переполнения счетчика временной базы TOF. Этот флаг сбрасывается посредством записи 1 в уже установленный бит TOF.
Регистры данных каналов захвата/сравнения TCn — 16 разрядные. В памяти каждый регистр представлен двумя 8 разрядными регистрами: TCnH — старший байт регистра данных канала с номером n, TCnL — младший байт регистра данных канала с номером n. Если канал настроен на режим входного захвата, то в регистре данных TCn содержится код счетчика временной базы в момент последнего события входного захвата. Если же канал настроен на режим выходного сравнения, то в регистр данных TCn под управлением программы записывается код момента сравнения. Формат и адреса расположения в памяти восьми регистров данных каналов TC0…TC7 приведены на рис. 4.42.
Регистр данных канала 0: TC0H:TC0L | Адрес: $0090–0091 |
Регистр данных канала 1: TC1H:TC1L | Адрес: $0092–0093 |
Регистр данных канала 2: TC2H:TC2L | Адрес: $0094–0095 |
Регистр данных канала 3: TC3H:TC3L | Адрес: $0096–0097 |
Регистр данных канала 4: TC4H:TC4L | Адрес: $0098–0099 |
Регистр данных канала 5: TC5H:TC5L | Адрес: $009A–009B |
Регистр данных канала 6: TC6H:TC6L | Адрес: $009C–009D |
Регистр данных канала 7: TC7H:TC7L | Адрес: $009E–009FФормат регистров данных таймера:TCnH, TCnL |
Рис. 4.42.
1. Опишите два возможных способа для сброса флага события в регистре TFLG1.
Ответ: По первому способу биты флагов событий в каналах захвата/сравнения CnF в регистре TFLG1 сбрасываются посредством записи 1 в тот разряд регистра TFLG1В, который подлежит сбросу. Попытка записи 0 в разряд, который установлен в 1, не даст желаемого результата. п.1. По второму способу чтение или запись в регистр данных канала автоматически сбрасывает бит события этого канала, если в регистре TSCR установлен бит TFFCA.
2. Какой код должен быть записан в регистр режимов каналов захвата/сравнения TIOS, чтобы каналы с четными номерами работали в режиме входного захвата, а каналы с нечетными номерами в режиме выходного сравнения?
Ответ: $AA.
3. Какой код и в какие разряды регистра TCTL1 должен быть записан, чтобы настроить формирователь уровня канала 7 в режим установки 1?
Ответ: Код 11 в разряды OM7:OL7.
4. Какой код и в какие разряды регистра TCTL4 должен быть записан, чтобы настроить детектор события канала 1 в режим мониторинга за любым изменением уровня сигнала на входе канала 1?
Ответ: Код 11 в разряды EDG1B:EDG1A.
Познакомившись с основными подсистемами модуля таймера, мы рассмотрим несколько примеров применения. В первом примере мы будем использовать подсистему входного захвата для измерения частоты и периода следования импульсов некоторого логического сигнала. Во втором примере мы будем формировать на одном из выходов МК импульсную последовательность, используя для этого подсистему выходного сравнения и подсистему прерывания МК.
Для того чтобы воспользоваться аппаратными средствами универсального канала таймера для измерения частоты и периода следования импульсов, необходимо установить этот канал в режим входного захвата, а также выполнить ряд дополнительных установок конфигурации для счетчика временной базы, детектора события канала и подсистемы прерывания. Полное описание регистров специальных функций модуля таймера было приведено выше. В нашем примере мы будем использовать следующие биты и регистры управления:
• Бит разрешения работы модуля таймера TEN (регистр управления модулем таймера TSCR);
• Бит разрешения прерывания по переполнению счетчика временной базы TOI и биты выбора коэффициента деления программируемого делителя частоты на входе счетчика временной базы PR2:PR1:PR0 (регистр масок таймера TMSK2);
• Бит выбора режима работы канала IOSn (регистр режимов каналов захвата/сравнения TIOS). Если бит IOSn установлен в 1, то канал работает в режиме выходного сравнения. Если бит IOSn равен 0, то канал настроен на режим входного захвата;
• Биты выбора режима работы детектора события канала входного захвата EDGnB:EDGnA (регистры управления таймером TCTL3 и TCTL4);
• Бит события в канале CnF (регистр флагов таймера TFLG1);
• Бит разрешения прерывания по событию в канале CnI (регистр масок таймера TMSK1);
• Регистр данных канала TCn, в который автоматически записывается код счетчика временной базы в момент события входного захвата.
Предположим, что период исследуемого сигнала не превышает длительности периода переполнения счетчика временной базы. Тогда, для измерения частоты и периода следования импульсов логического сигнала, необходимо реализовать в микроконтроллере следующую последовательность действий:
1. Разрешить работу модуля таймера;
2. Выбрать частоту тактирования счетчика временной базы, для чего установить желаемый коэффициент деления программируемого делителя частоты на входе счетчика временной базы;
3. Установить один из каналов в режим входного захвата по нарастающему фронту импульса;
4. Сохранить в памяти МК код счетчика временной базы в момент появления первого фронта импульса;
5. Сохранить в памяти МК код счетчика временной базы в момент появления второго фронта импульса;
6. Взять разность полученных кодов, которая будет равна периоду исследуемого сигнала. Воспользовавшись операцией деления, вычислить частоту исследуемого сигнала. На рис. 4.43 приведена блок схема рассмотренного алгоритма. Ниже приведен программный фрагмент (timer1.c), который реализует этот алгоритм. В программе применен метод программного опроса триггера события входного захвата C2F. Когда программа «обнаруживает» установленный в 1 триггер события первый раз, она копирует регистр данных канала в переменную rising_1, сбрасывает триггер и ожидает следующей установки триггера события. Когда триггер события установится второй раз, программа копирует регистр данных канала в переменную rising_2. Разность двух зафиксированных в регистре данных канала входного захвата значений позволит вычислить период, а затем и частоту исследуемого импульсного сигнала.
Рис. 4.43. Блок схема алгоритма измерения периода и частоты исследуемого сигнала
Отметим три момента в стиле написания исходного текста представленного программного фрагмента для измерения периода и частоты импульсного сигнала:
• Основная программа «main» содержит вызовы трех функций, каждая из которых выполняет отдельную смысловую задачу;
• Имена функций и переменных выбраны в соответствии с их смысловым назначением;
• Представленный исходный текст программы достаточно полно документирован посредством комментариев перед записью каждой функции.
/*-------------------------------------------------------------------*/
/* filename: timer1.c */
/* МAIN PROGRAМ: Эта программа измеряет период и частоту импульсного */
/* сигнала. Сигнал подключается на вход 2 подсистемы таймера (IC2). */
/*-------------------------------------------------------------------*/
/*подключаемые файлы*/
#include <912b32.h>
#include
#include
/*используемые функции*/
void timer_init(void);
void measure_wave(void);
void period_freq(void);
/*глобальные переменные*/
unsigned long int rising_1;
unsigned long int rising_2;
void main(void) {
timer_init(); /*инициализация таймера*/
measure_wave(); /*определение времени двух фронтов сигнала*/
period_freq(); /*вычисление периода и частоты*/
}
/*----------------------------------------------------------------------*/
/* Функция timer_init производит инициализацию модуля таймера */
/* Канал 2 таймера настраивается на режим входного захвата по переднему */
/* фронту сигнала */
/* Частота тактирования счетчика временной базы устанавливается 2 МГц. */
/*----------------------------------------------------------------------*/
void timer_init(void) {
TMSK1 = 0x00; /*запретить прерывания от каналов таймера*/
TMSK2 = 0x02; /*назначить коэффициент деления 4*/
TIOS = 0х00; /*установить канал 2 в режим входного захвата*/
TSCR = 0х80; /*разрешить работу таймера*/
TCTL4 = 0х10; /*назначить режим детектора событий по*/
/*положительному фронту*/
TFLG1 = 0xFF; /*очистить флаги событий*/
}
/*-------------------------------------------------------------------*/
/* Функция measure_wave запоминает два последовательных момента */
/* нарастающего фронта исследуемого сигнала. Значения запоминаются с */
/* использованием глобальных переменных */
/*-------------------------------------------------------------------*/
void measure_wave(void) {
while((TFLG1 & 0х04) == 0) {
/*ожидать нарастающего фронта*/
;
}
rising_1 = TCNT; /*запомнить код счетчика временной базы*/
/*в переменной rising_1*/
TFLG1 = 0х04; /*сброс триггера события канала 2*/
while((TFLG1 & 0х04) == 0) {
/*ожидать нарастающего фронта*/
;
}
rising_2 = TCNT; /*запомнить код счетчика временной базы*/
/*в переменной rising_2*/
TFLG1 = 0х04; /*сброс триггера события канала 2*/
}
/*------------------------------------------------------------------------*/
/* Функция period_freq вычисляет период и частоту исследуемого импульсного*/
/* сигнала и отображает полученные значения на экране */
/*------------------------------------------------------------------------*/
void period_freq(void) {
unsigned long int new_rising;
unsigned long int new_falling;
float frequency;
float period;
unsigned int int_period;
unsigned int int_freq, freq_tenths;
if(rising_2 < rising_1) /*вычисление периода*/
{
new_rising = rising_2 + 0xFFFF;
period = ((float)new_rising (float)rising_l)*0.0000005;
} else {
period = ((float)rising_2 (float)rising_l)*0.0000005;
}
frequency = 1.0/period; /*вычисление частоты*/
int_freq = (int)(frequency/l000.0);
freq_tenths = (int)((frequency –(float) int_freq*1000)/100.0);
/*вывод результатов*/
printf("Frequency = %d.%d kHz \n\n" int_freq, freq_tenths);
int_period = (int) (1000000*period);
printf("Period = %d μs\n\n", int_period);
printf{"Period = %f ms\n\n", (period*1000))};
}
/*------------------------------------------------------------------------*/
Приведенная программа выдаст ошибочный результат для сигналов, период которых превышает период переполнения счетчика внешних событий. В одном из домашних заданий в конце данной главы мы попросим Вас изменить исходный текст программы так, чтобы измерение более «медленных» сигналов также стало возможным. Какие изменения в программу следует внести? Вы должны будете контролировать, сколько раз переполнился счетчик временной базы между двумя соседними событиями в канале входного захвата. Для этого следует организовать программный счетчик, который будет инкрементироваться каждый раз, когда счетчик переполнится. Переполнение счетчика Вы будете фиксировать по установленному флагу TOF. Этот флаг может программно считываться с последующим сбросом, или по флагу могут быть разрешены прерывания. В подпрограмме прерывания будет инкрементироваться программный счетчик. После того, как второй нарастающий фронт зафиксирован, программа должна выполнить вычисления, используя формулу:
Period = 216×n + (rising_2 – rising_1)
Рассматриваемая программа имеет также ограничение по измерению сигналов с достаточно высокой частотой. Как узнать максимальную частоту, которая может быть измерена? Для этого следует вспомнить, что в нашем учебном примере частота внутренней шины МК составляет 8 МГц. Вы должны просмотреть ассемблерный код функции измерения частоты measure_wave и определить, сколько машинных тактов необходимо для распознавания установленного в 1 флага события и считывания кода первого события из регистра данных канала. Именно этот интервал является минимальным периодом сигнала, который может быть измерен.
Для того, чтобы сформировать последовательность импульсов на одном из выходов МК, следует воспользоваться подсистемой выходного сравнения. В данном примере мы рассмотрим технику использования одного из каналов таймера в режиме выходного сравнения для генерации импульсной последовательности с заданной частотой и коэффициентом заполнения. В примере мы будем использовать следующие биты и регистры управления:
• Бит разрешения работы модуля таймера TEN (регистр управления модулем таймера TSCR);
• Бит разрешения прерывания по переполнению счетчика временной базы TOI и биты выбора коэффициента деления программируемого делителя частоты на входе счетчика временной базы PR2:PR1:PR0 (регистр масок таймера TMSK2);
• Бит выбора режима работы канала IOSn (регистр режимов каналов захвата/сравнения TIOS). Если бит IOSn установлен в 1, то канал работает в режиме выходного сравнения. Если бит IOSn равен 0, то канал настроен на режим входного захвата;
• Биты выбора режима работы формирователя уровня канала выходного сравнения OMn:OLn (регистры управления таймером TCTL1 и TCTL2);
• Бит события в канала CnF (регистр флагов таймера TFLG1);
• Бит разрешения прерывания по событию в канале выходного сравнения CnI (регистр масок таймера TMSK1);
• Регистр данных канала TCn, код которого автоматически сравнивается с кодом счетчика временной базы. Момент равенства кодов и является событием выходного сравнения.
В нашем примере мы будем формировать импульсную последовательность, параметры которой определяются числом и годом рождения разработчика. Допустим, Вы родились 19 мая 1977 года. Тогда частота генерируемого сигнала будет равна 519 Гц, коэффициент заполнения будет равен 77%. Для задания численных констант, определяющих частоту и коэффициент заполнения генерируемого импульсного сигнала, проведем следующие несложные расчеты:
1. Назначим в качестве источника тактирования для счетчика временной базы программируемый делитель, на вход которого подается fBUS=8 МГц;
2. Установим коэффициент деления программируемого делителя частоты на входе счетчика временной базы, равный 4. Тогда частота тактирования счетчика будет равна 2 МГц, что соответствует разрешающей способности счетчика 0,5 мкс. Выбранная таким образом разрешающая способность должна быть достаточна для формирования периода следования и длительности импульса;
3. По условию задачи частота формируемого сигнала составляет 519 Гц, что соответствует периоду следования Т = 1/519 = 0.0019268 с;
4. Вычислим длительность высокого и низкого уровня сигнала на интервале периода. По условию задачи коэффициент заполнения равен 77%. Длительность искомых временных интервалов составляет:
Длительность_1 = 0.77*(0.0019268) = 0.001484 с
Длительность_0 = 0.23*(0.0019268) = 0.0004432 с
5. Преобразуем полученные временные интервалы в целое число периодов частоты тактирования счетчика временной базы:
Код_1 = 0.001484 с/0.5 мкс = 2968 тактов
Код_0 = 0.0004432 с /0.5 мкс = 886 тактов
На рис. 4.44 приведена упрощенная блок схема алгоритма генерации импульсной последовательности. Ниже представлен исходный текст программы на Си (timer2.c), в котором используется метод программного опроса триггера события в канале выходного сравнения.
Рис. 4.44. Блок схема алгоритма генерации импульсной последовательности с заданными временными параметрами
/*------------------------------------------------------------------------*/
/* filename: timer2.c */
/* МAIN PROGRAМ: Эта программа генерирует импульсную последовательность */
/* с частотой 519 Гц и коэффициентом заполнения 77%. Сигнал формируется на*/
/* выходе 2 подсистемы таймера (IC2) */
/*------------------------------------------------------------------------*/
/*подключаемые файлы*/
#include <912b32.h>
/*используемые функции*/
void timer_init(void);
void half_cycle(unsigned int time);
void main(void) {
unsigned int high_time = 2968; /*число тактов высокого уровня*/
unsigned int low_time = 886; /*число тактов низкого уровня*/
timer_init();
half_cycle(low_time); /*генерация низкого уровня*/
while(1) {
half_cycle(high_time); /*генерация высокого уровня*/
half_cycle(low_time); /*генерация низкого уровня*/
}
}
/*--------------------------------------------------------------------*/
/* Функция timer_init производит инициализацию модуля таймера. */
/* Канал 2 таймера настраивается на режим выходного сравнения. */
/* Частота тактирования счетчика временной базы устанавливается 2 МГц.*/
/*--------------------------------------------------------------------*/
void timer_init(void) {
TMSK1 = 0x00; /*запретить прерывания от каналов таймера*/
TMSK2 = 0x02; /*назначить коэффициент деления 4*/
TIOS = 0х04; /*установить канал 2 в режим выходного сравнения*/
TSCR = 0х80; /*разрешить работу таймера*/
TCTL2 = 0х10; /*назначить режим формирователя уровня */
/*"инвертирование"*/
TFLG1 = 0x04; /*очистить флаг события канала 2*/
TC2 = TCNT; /*записать в регистр данных канала 2 текущее*/
/*состояние счетчика временной базы*/
}
/*------------------------------------------------------------------------*/
/* Функция half_cycle генерирует временной интервал заданной длительности */
/* Число тактов для отсчета должно быть определено вне функции */
/*------------------------------------------------------------------------*/
void half_cycle(unsigned int time) {
ТС2 += time; /*задать код сравнения в регистр данных канала*/
while ((TFLG1 & 0x04) == 0) /*ожидать события выходного сравнения*/
{
;
}
TFLG1 = 0x04; /*очистить флаг события канала 2*/
}
/*------------------------------------------------------------------------*/
Предложенный к рассмотрению программный фрагмент (timer2.c) отличается своей простотой и легкостью отладки. Это объясняется использованным методом программного опроса триггера события канала. Однако такой способ генерации импульсного сигнала становится непригодным, если по условию задачи управления необходимо формировать сразу несколько импульсных сигналов, и в каждом из них должны быть точно реализованы их временные параметры. Поэтому рассмотрим способ генерации импульсного сигнала с использованием подсистемы выходного сравнения таймера и подсистемы прерывания.
Цель рассматриваемого примера (timer3.c) — познакомить читателя с техникой генерации импульсных сигналов с использованием подсистемы выходного сравнения, перезагрузка регистра данных которой реализуется в подпрограмме прерывания по очередному событию в канале выходного сравнения. Ниже перечислены биты и регистры управления, которые используются в данном примере:
• Бит разрешения работы модуля таймера TEN (регистр управления модулем таймера TSCR);
• Бит разрешения прерывания по переполнению счетчика временной базы TOI и биты выбора коэффициента деления программируемого делителя частоты на входе счетчика временной базы PR2:PR1:PR0 (регистр масок таймера TMSK2);
• Бит выбора режима работы канала IOSn (регистр режимов каналов захвата/сравнения TIOS). Если бит IOSn установлен в 1, то канал работает в режиме выходного сравнения;
• Биты выбора режима работы формирователя уровня канала выходного сравнения OMn:OLn (регистры управления таймером TCTL1 и TCTL2);
• Бит события в канала CnF (регистр флагов таймера TFLG1);
• Бит разрешения прерывания по событию в канале выходного сравнения CnI (регистр масок таймера TMSK1);
• Регистр данных канала TCn, код которого автоматически сравнивается с кодом счетчика временной базы. Момент равенства кодов и является событием выходного сравнения.
В тексте примера timer3.c мы будем генерировать импульсный сигнал с произвольной частотой и коэффициентом заполнения. Проанализировав текст программа Вы объясните, какую форму и какие временные параметры будет иметь формируемый сигнал.
Прежде, чем знакомиться с текстом программы timer3.c, вспомним, как оформляются подпрограммы прерывания при программировании на Си. Сначала следует убедиться, что Ваш заголовочный файл содержит определения макросов, которые позволят Вам использовать одноименные с командами ассемблера функции для запрета и разрешения прерываний в системе (см. раздел 4.12):
#define CLI() asm("cli\n"); //разрешить маскируемые прерывания
#define SEI() asm("sei\n"); //запретить маскируемые прерывания
Также следует отметить, что специфика записи подпрограммы прерывания частично определяется типом используемого компилятора. В соответствии с предварительной договоренностью, в текстах примеров этой книги используется компилятор ICC12 компании ImageСraft.
/*----------------------------------------------------------------------*/
/* filename: timer3.c */
/* МAIN PROGRAМ: Эта программа генерирует импульсную последовательность */
/* в форме меандра с использованием таймера и подсистемы прерывания */
/* Сигнал формируется на выходе 2 таймера (IC2) */
/*----------------------------------------------------------------------*/
/*подключаемые файлы*/
#include <912b32.h>
/*используемые функции*/
void initialize(void); /*функция инициализации*/
void toggle_isr(void); /*подпрограмма прерывания toggle_isr*/
//объявление функции обслуживания прерывания
#pragma interrupt_handler toggle_isr
//инициализация вектора прерывания
#pragma abs_address: 0xF7EA
void (*Timer_Channel_2_interrupt_vector[]) () = {toggle_isr};
#pragma end_abs address
/*глобальные переменные*/
int с;
void main(void) {
с = 100;
initialize(); /*инициализация подсистемы таймера*/
TMSK1 = 0х04; /*разрешение прерывания по событию в канале 2*/
TFLG1 = 0xFF; /*сброс всех флагов событий от каналов*/
CLI(); /*разрешить прерывания*/
while(1) {
/*ожидание прерывания*/
;
}
}
/*-------------------------------------------------------------*/
/* Функция initialize задает начальные установки модуля таймера*/
/*-------------------------------------------------------------*/
void initialize(void) {
TMSK2 = 0x02; /*назначить коэффициент деления 4*/
TIOS = 0х04; /*установить канал 2 в режим выходного сравнения*/
TSCR = 0х80; /*разрешить работу таймера*/
TCTL2 = 0х10; /*назначить режим формирователя уровня */
/*инвертирование*/
}
/*----------------------------------------------*/
/* Функция toggle_isr – подпрограмма прерывания */
/*----------------------------------------------*/
void toggle_isr(void) {
TFLG1 = 0xFF;
/*сброс всех флагов событий от каналов*/
ТС2 = TC2 + c;
/*задать код сравнения в регистр данных канала*/
c = c + 100;
/*вычислить новое значение c*/
}
/*-----------------------------------------------*/
Проанализируйте функцию toggle_isr. Генерацию какого импульсного сигнала она обеспечивает?
В следующем примере timer4.c показаны потенциальные возможности подсистемы выходного сравнения, обслуживаемой по прерываниям. В примере генерируются сразу две импульсные последовательности с разными частотами и коэффициентами заполнения. Нетрудно видеть, что число одновременного генерируемых импульсных сигналов может быть увеличено.
/*------------------------------------------------------------------------*/
/*filename: timer4.c */
/*МAIN PROGRAМ: Эта программа генерирует две импульсных последовательности*/
/* с использованием таймера и двух каналов подсистемы прерывания */
/* Сигналы формируются на выходах 2 и 3 таймера. */
/*------------------------------------------------------------------------*/
/*подключаемые файлы*/
#include <912b32.h>
/*используемые функции*/
void initialize(void); /*функция инициализации*/
void toggle1_isr(void); /*подпрограмма прерывания toggle1_isr*/
void toggle2_isr(void); /*подпрограмма прерывания toggle2_isr*/
//объявление функции обслуживания прерывания
#pragma interrupt_handler toggle1_isr
#pragma interrupt_handler toggle2_isr
//инициализация векторов прерывания
#pragma abs_address: 0xF7E8
void (*Timer_Channel_3_interrupt_vector[]) () = {toggle2_isr};
void (*Timer_Channel_2_interrupt_vector[]) () = {toggle1_isr};
#pragma end_abs address
void main(void) {
initialize(); /*инициализация подсистемы таймера*/
TMSK1 = 0х0C; /*разрешение прерывания по событию в каналах 2 и 3*/
TFLG1 = 0xFF; /*сброс всех флагов событий от каналов*/
CLI(); /*разрешить прерывания*/
while(l) {
/*ожидание прерывания*/
;
}
}
/*-------------------------------------------------------------*/
/* Функция initialize задает начальные установки модуля таймера*/
/*-------------------------------------------------------------*/
void initialize(void) {
TMSK2 = 0x02; /*назначить коэффициент деления 4*/
TIOS = 0х0C; /*установить каналы 2 и 3 в режим выходного*/
/*сравнения*/
TSCR = 0х80; /*разрешить работу таймера*/
TCTL2 = 0х50; /*назначить режим формирователя уровня */
/*инвертирование для обоих каналов*/
}
/*------------------------------------------------------------------*/
/* Функция toggle1_isr подпрограмма прерывания по событию в канале 2*/
/*------------------------------------------------------------------*/
void toggle1_isr(void) {
TFLG1 = 0x04; /*сброс флага события канала 2*/
ТС2 += 9091; /*задать код сравнения в регистр данных канала*/
}
/*------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* Функция toggle2_isr подпрограмма прерывания по событию в канале 3 */
/*-------------------------------------------------------------------*/
void toggle2_isr(void) {
TFLG1 = 0x08; /*сброс флага события канала 3*/
ТС2 += 4854; /*задать код сравнения в регистр данных канала*/
}
/*-------------------------------------------------------------------*/
Проанализируйте функции toggle1_isr и toggle2_isr. Генерацию каких импульсных последовательностей они обеспечивают?
4.14.5. Счетчик событий
Счетчик событий или аккумулятор импульсов (Pulse Accumulator) — это подсистема модуля таймера, которая разработана специально для подсчета импульсов. Основной элемент счетчика событий — 16 разрядный счетчик, который может работать в двух режимах:
• Счетчик внешних событий. В этом режиме счетчик PACNT подсчитывает число событий, которое детектируется его аппаратными средствам на входе PAI. Тип события (только нарастающий или только спадающий фронт сигнала) определяется посредством программных установок.
• Стробируемый таймер. В этом режиме счетчик PACNT тактируется внутренними импульсами с частотой fBUS/64, а сигналы на входе PAI разрешают или запрещают счет.
Структурная схема подсистемы счетчика событий представлена на рис. 4.45. Изучив ее, вы увидите, что счетчик событий в качестве входа PAI, на который должны поступать внешние импульсы, использует линию PT7 порта PORT T. Таким образом, обслуживание подсистемы счетчика событий альтернативная функция линии 7 порта PORT T. Однако линия PT7 обладает еще одной альтернативной функцией. Она используется как вход или как выход канала 7 подсистемы захвата/сравнения модуля таймера. Какие программные установки в регистрах управления таймера необходимо выполнить, чтобы конфигурировать линию PT7 как вход PAI счетчика событий?
• Сбросить бит IOS7 в регистре TIOS ($0080), тогда в канале 7 будет запрещен режим выходного сравнения;
• Сбросить биты OM7:OL7 регистра TCNTL1($0088),тогда линия PT7 окажется отсоединенной от аппаратных средств канала 7;
• Сбросить бит OC7M7 в регистре OC7M ($0082).
Рис. 4.45. Структура и регистры управления счетчика вешних событий
Если все эти установки выполнены, то сигнал с лиги PT7 будет поступать на вход детектора событий подсистемы счетчика событий. В каждом из режимов работы счетчика детектор выполняет разные функции, однако в обоих режимах работы детектор становится активным при установке бита PAEN регистра управления счетчиком PACTL (рис. 4.45) в 1.
Если подсистема находится в режиме счетчика внешних событий, бит PEDGE определяет: по какому фронту сигнала, нарастающему (при PEDGE = 1) или спадающему (при PEDGE = 0) будет переключаться счетчик. Если детектор фиксирует на входе PAI заданное битом PEDGE изменение входного сигнала, то устанавливается флаг события PAIF.
Если подсистема работает в режиме стробируемого таймера, то бит PEDGE определяет уровень сигнала на входе PAI, при котором будет разрешен счет для внутреннего счетчика PACNT. Если бит PEDGE = 1, то счет разрешен при низком логическом уровне на входе PAI. При этом по нарастающему фронту сигнала на входе PAI будет устанавливаться флаг событий PAIF. Если же бит PEDGE = 0, счет разрешается при высоком уровне PAI, флаг PAIF устанавливается по спадающему фронту PAI.
Если работы подсистемы счетчика событий разрешена, то 16 разрядный счетчик начинает считать с нулевого значения. Текущий код счетчика может быть считан из 16-разрядного регистра текущего состояния счетчика PACNT, который в памяти размещается в двух ячейках памяти: PACNTH — старший байт счетчика событий, PACNTL — младший байт счетчика событий (рис. 4.45). Каждое переполнение 16-разрядного счетчика событий фиксируется установкой триггера переполнения PAOVF. Этот триггер сбрасывается посредством записи в установленный разряд PAOVF единичного значения.
Оба рассмотренных флага: флаг переполнения счетчика PAOVF и флаг события на входе счетчика PAIF, — способны генерировать запросы прерывания. Прерывания от указанных флагов разрешаются битами PAOVI и PAI соответственно. Биты PAOVI и PAI располагаются в регистре флагов счетчика событий PAFLG (рис. 4.45).
В данном разделе мы рассмотрим регистры специальных функций, которые используются для управления режимами работы счетчика событий.
Регистр управления счетчиком событий PACTL (Pulse Accumulator Control Register) располагается в памяти МК по адресу $00A0. Формат регистра представлен на рис. 4.45. Регистр PACTL используется для задания режима работы счетчика событий, для назначения режима работы его детектора событий, для разрешения прерываний от подсистемы счетчика событий, а также для выбора источника тактирования счетчика временной базы модуля таймера.
Бит PTAE разрешает работу подсистемы счетчика событий. При PTAE = 1 работа подсистемы разрешена, при PTAE = 0 подсистема счетчика находится в неактивном состоянии. Бит PAMOD служит для выбора режима работы. При PAMOD = 0 подсистема работает в режиме счетчика внешних событий, при PAMOD = 1 для подсистемы назначается режим стробируемого таймера.
Бит PEDGE управляет режимом работы детектора событий подсистемы счетчика. Если счетчик работает в режиме счетчика внешних событий (PAMOD = 0), то при PEDGE = 1 детектор события настраивается на распознавание положительного фронта сигнала, при PEDGE = 0 — отрицательного фронта. При работе в режиме стробируемого таймера (PAMOD = 1) бит PEDGE определяет вид сигнала, разрешающего переключение счетчика таймера. Если PEDGE = 1, то счет разрешается при подаче 1 на вход PAI, при этом флаг PAI устанавливается по отрицательному фронту входного сигнала. Если же PEDGE = 0, то счет разрешается при подаче 0 на вход PAI, при этом флаг PAI устанавливается по положительному фронту входного сигнала.
Биты CLK1:CLK0 назначают источник тактирования для счетчика временной базы модуля таймера (см. рис. 4.27).
Биты PAOVI и PAI (не путать с одноименным входом) разрешают прерывания по событию переполнения счетчика (флаг PAOVF) и по событию на входе PAI (флаг PAIF), тип которого определяется режимом работы и значением бита PEDGE.
Регистр флагов счетчика событий PAFLG (Pulse Accumulator Flag Register) располагается в памяти МК по адресу $00A1 и содержит всего два значимых бита (рис. 4.45). Флаг переполнения счетчика устанавливается, когда 16-разрядный счетчик подсистемы изменяет свое значение с $FFFF на $0000. Флаг события подсистемы PAIF устанавливается в 1 при каждом перепаде потенциала на входе PAI, который указан битом PEDGE и режимом работы счетчика. Оба этих бита сбрасываются посредством записи в установленный бит 1.
Регистр счетчика PACNT (Pulse Accumulator Counter Register) содержит текущий код 16-разрядного счетчика подсистемы. Поэтому он располагается в двух ячейках памяти: старший байт PACNTH — по адресу $00A2, младший байт PACNTL — по адресу $00A3. Поскольку изменение кода счетчика может произойти в произвольный момент времени, рекомендуется производить его чтение в двухбайтовом формата с использованием типа LDD или LDX/LDY.
Мы рассмотрим пример определения скорости движения велосипеда по сигналам датчика Холла, который установлен на колесе велосипеда. Датчики Холла доступны в различных модификациях. Обобщая сведения о датчиках Холла, можно выделить следующие три типа датчиков:
• Линейные датчики, напряжение на выходе которых пропорционально напряженности магнитного поля, в которое помещен датчик;
• Биполярные датчики, формируют выходной сигнал, находясь вблизи южного магнитного полюса, сбрасываются в 0, находясь вблизи северного магнитного полюса;
• Однополярные датчики, формируют выходной сигнал, находясь вблизи южного магнитного полюса, сбрасываются в 0 при отсутствии магнитного поля.
В нашем примере мы поместим магнит на спицу вращающегося колеса. Однополярный датчик Холла установим на вилке колеса, выход датчика соединим со входом (PT7) счетчика внешних событий МК семейства 68HC12 (рис. 4.46). Тогда на выходе датчика будет генерироваться один импульс при каждом полном обороте колеса. Если мы подсчитаем число импульсов с выхода датчика на известном временном интервале, мы сможем определить скорость движения и расстояние, которое было преодолено за время измерения.
Рис. 4.46. Колесо велосипеда с датчиком Холла
Читателю предлагается самостоятельно написать программу расчета скорости и преодоленного расстояния, используя следующие подсказки:
• В первую очередь определите связь между одним оборотом колеса и пройденной дистанцией пути. Предположите, что диаметр колеса равен 66,04 см (26 дюймов).
• Произведите инициализацию подсистемы счетчика внешних событий:
a. Подсистема счетчика событий использует вход PT7 для подключения внешнего импульсного сигнала. Для конфигурирования линии PT7 на ввод установите бит 7 регистра TIOS в 0, также в 0 должны быть установлены биты 6 и 7 регистра PCTL1.
b. Запрограммируйте на выбранный режим регистр управления счетчиком событий PACTL. Определите необходимое состояние каждого бита самостоятельно.
• Считайте под управлением программы текущее состояние счетчика внешних событий, используя регистр PACNT.
• Сформируйте временной интервал, длительность которого должна быть достаточна накопления в счетчике событий нескольких десятков отсчетов. Тогда точность измерения скорости будет приемлемой (несколько единиц %).
• Считайте под управлением программы новое текущее состояние счетчика событий.
• Получите разность кодов и вычислите скорость и пройденное расстояние. Приведенный ниже программный фрагмент поможет Вам выполнить инициализацию подсистемы счетчика событий.
/*------------------------------------------------------------------------------*/
/* Функция initialize_PA задает начальные установки подсистемы счетчика событий */
/*------------------------------------------------------------------------------*/
void initialize_PA(void) {
TIOS = 0x00; /*конфигурировать вход PT7 для работы */
TCTL1 = 0х00; /*в качестве источника сигналов для счетчика*/
OC7M = 0x00 /*внешних событий – 3 команды*/
TSCR = 0х80; /*разрешить работу всего модуля таймера*/
PACTL = 0х70; /*разрешить работу в режиме счетчика внешних*/
/*событий по положительному фронту сигнала*/
}
/*-------------------------------------------------------------------------------*/
4.15. Модуль меток реального времени