Когда устройство на микроконтроллере требует реализации больших задержек по времени, разработчик может выбрать несколько вариантов решения этой задачи.
Одно из решений состоит в использовании встроенного в кристалл микроконтроллера AVR аппаратного таймера. Поскольку максимальная разрядность таймера обычно не превышает 16 бит (иногда 24 бита), то для получения длинных задержек выбирается минимальное значение для частоты тактирования. Например, 24-разрядный таймер, работающий на частоте 1 МГц, может дать задержку только несколько десятков секунд. Для многих приложений этого может оказаться недостаточным.
Другое решение - подсчет количества переполнений таймера. Однако это усложняет программное обеспечение, и не дает ядру оставаться в режиме низкого энергопотребления, когда происходит ожидание истечения задержки.
Третье решение - задействовать внешний низкочастотный генератор. Для этого таймер конфигурируется на подсчет внешних событий, и на его считающий (тактовый) вход подается сигнал низкой частоты. Такой способ может генерировать достаточно длительные задержки. Однако стоимость и аппаратная сложность системы возрастают, так как нужно устанавливать дополнительные электронные компоненты.
Здесь представлено решения для генерации и обработки длинных задержек на микроконтроллерах серии AVR AT90 (AT90S2313, AT90S4414 и AT90S8515). Используются встроенные таймеры без участия программного обеспечения, что позволяет ядру находиться в режиме пониженного энергопотребления во время генерации задержки. Поскольку таймеры тактируются от системной частоты, то не требуется каких-то внешних дополнительных компонентов. Для увеличения генерируемого времени задержки используется каскадное включение таймеров AVR.
Вместе с возможностью генерации очень больших временных задержек эта реализация сочетает высокую скорость системы. Например, микроконтроллер, работающий со скоростью 20 Mips, может генерировать задержки длиной до получаса.
Вот список примерных приложений, где могут понадобиться длинные задержки:
• Таймауты в интерфейсе между человеком и машиной • Измерения в окружающей среде (уровень звука, загрязнение) • Регулировка и управление процессом
Прим. переводчика: на самом деле предложенное решение имеет довольно ограниченное применение - оно хорошо подходит только для тех случаев, когда от системы требуется пониженное энергопотребление, и когда используемые таймеры/счетчики негде не должны быть задействованы. Для тех случаев, когда микроконтроллер не входит режим сна, предложенное решение бесполезно, потому что задержки любой длительности элементарно реализуются с помощью обычных счетчиков.
[Таймеры/счетчики микроконтроллеров AVR]
Далее будут коротко рассмотрены таймеры, используемые в AVR. Для дополнительной информации пожалуйста обращайтесь к даташиту "AVR Enhanced RISC Microcontroller Data Book".
Таймеры/счетчики. Серия AT90 предоставляет 2 таймера/счетчика (T/C) общего назначения, один 8-разрядный T/C, и один 16-разрядный T/C. Таймеры/счетчики имеют индивидуальный выбор поделенной тактовой частоты от одного и того же 10-битного предделителя (прескалера). Оба таймера/счетчика могут либо тактироваться от внутренней базовой тактовой частоты, или работать ка счетчик импульсов на внешнем выводе.
Прескалер для T/C. На рис. 1 показана схема основного прескалера для T/C. Есть 4 различных варианта выбора поделенной счетчиком частоты: CK/8, CK/64, CK/256 и CK/1024, где CK тактовая частота генератора. Для двух таймеров/счетчиков еще добавлены к вариантам выбор CK, внешнего тактового сигнала и остановка таймера.
Рис. 1. Прескалер для таймеров/счетчиков.
[8-Bit Timer/Counter0]
На рис. 2 показана блок-диаграмма Timer/Counter0.
Рис. 2. Блок-схема T/C0.
Для 8-разрядного Timer/Counter0 можно выбрать тактирование от CK, поделенной (через прескалер) CK, или от внешнего входа. Дополнительно таймер может быть остановлен, как указано в описании регистра управления Timer/Counter0 Control Register (TCCR0) [2]. Флаги состояния переполнения находятся в регистре Timer/Counter Interrupt Flag Register (TIFR). Управляющие флаги находятся в регистре управления Timer/Counter0 Control Register (TCCR0). Настройки для разрешения/запрета прерывания для Timer/Counter0 находятся в регистре Timer/Counter Interrupt Mask Register (TIMSK).
Когда Timer/Counter0 тактируется от внешнего входа, внешний сигнал тактов синхронизируется с частотой тактового генератора ядра (системными тактами) CK. Чтобы гарантировать корректную выборку внешних тактов, минимальное время между двумя переходами уровня внешнего сигнала тактов должно быть как минимум одному интервалу периода CK. Внешний тактовый сигнал таймера анализируется по нарастанию уровня внутренней системной частоты CK.
[16-Bit Timer/Counter1]
На рис. 3 показана блок-диаграмма Timer/Counter1.
Рис. 3. Блок-схема T/C1.
Для 16-bit Timer/Counter1 можно выбрать тактирование от CK, поделенной (через прескалер) CK, или от внешнего входа. Дополнительно таймер может быть остановлен, как указано в описании регистров управления Timer/Counter1 Control Registers (TCCR1A и TCCR1B). Различные флаги состояния (overflow, compare match и capture event) и управляющие сигналы находятся в регистрах TCCR1A и TCCR1B. Настройки для разрешения/запрета прерываний Timer/Counter1 находятся в регистре Timer/Counter Interrupt Mask Register (TIMSK).
Когда Timer/Counter1 тактируется от внешнего входа, внешний сигнал тактов синхронизируется с частотой тактового генератора ядра (системными тактами) CK. Чтобы гарантировать корректную выборку внешних тактов, минимальное время между двумя переходами уровня внешнего сигнала тактов должно быть как минимум одному интервалу периода CK. Внешний тактовый сигнал таймера анализируется по нарастанию уровня внутренней системной частоты CK.
16-битный Timer/Counter1 сочетает как высокую разрешающую способность (и соответственно высокую точность), так и возможность выбора различных коэффициентов деления входной тактовой частоты. Выбор высокого коэффициента деления тактовой частоты делает Timer/Counter1 полезным для низкоскоростных функций или для точной синхронизации нечасто выполняемых действий.
Timer/Counter1 поддерживает 2 функции сравнения Output Compare с использованием регистров Output Compare Register 1 A и B (OCR1A и OCR1B) в качестве источника данных для сравнения со значением счетчика Timer/Counter1. Функции Output Compare включают опциональную очистку счетчика при совпадении (compare match), и действия для выводов Output Compare для обоих сравнений (compare match A и B).
[Конфигурация аппаратуры]
Чтобы произвести длинную задержку от быстрой системной частоты тактирования CK, каскадируются прескалер и два встроенных в кристалл микроконтроллера таймера/счетчика. Конфигурация аппаратуры показана на рис. 4.
Рис. 4. Конфигурация микроконтроллера AVR для поддержки генерации длинных задержек.
Timer/Counter1 конфигурируется как таймер. Он программируется для деления системной частоты с заданным пользователем коэффициентом, и переключает вывод OC1A каждый раз, когда значение счетчика достигает значения, записанного в регистр сравнения output compare (OCR1AH-OCR1AL). Когда выход OC1A переключается, регистр Timer/Counter1 (TCNT1H-TCNT1L) перезагружается нулевым значением, и начинает счет сначала.
Поскольку переключающийся выходной порт OC1A подключен ко входу T0 счетчика, то частота на выходе OC1A может создавать тактирование для Timer/Counter0. Последний конфигурируется как счетчик, и инкрементируется по каждому нарастающему фронту на входе T0. Тогда Timer/Counter0 переполняется, устанавливается соответствующий флаг в TIFR, и происходит прерывание. Этот момент говорит о том, что запрограммированная задержка истекла.
Самая большая задержка может быть вычислена при следующих условиях:
Максимальный коэффициент деления прескалера для Timer1: 1024 Максимальный коэффициент деления для Timer1: 65536 Переключение OC1A подразумевает дополнительный коэффициент деления на 2 Максимальный коэффициент деления для Counter0: 256.
Для общего случая величина программируемой задержки может быть вычислена по следующей формуле:
T = 2 / CK * T1P * OCR1A * (256 – TCNT0)
где:
CK = системная тактовая частота T1P = коэффициент деления прескалера, заданны в TCCR1B (может быть либо 8, либо 64, либо 256, либо 1024).
Эта короткая программа показывает, как сконфигурировать таймеры/счетчики для реализации задержки на 1 час при работе от системной тактовой частоты CK = 1 МГц (вычислительная мощность аналогична 80C51). Во время фазы запуска конфигурируются таймеры/счетчики и контроллер прерываний. Затем происходит вход в режим сна (idle mode). После истечении часа произойдет прерывание. Это событие разбудит ядро, которое запустит выбранную программистом задачу. В этом примере для простоты только лишь переключается ножка выходного порта (PA0). Когда эта задача завершена, ядро снова входит в режим сна. Этот цикл продолжается бесконечно. Ниже приведен прокомментированный исходный код.
; Определения констант ----------------------------------------.EQUPORTA = $1B.EQUDDRA = $1A.EQUDDRD = $11.EQUTCCR1A = $2F.EQUOCR1AH = $2B.EQUOCR1AL = $2A.EQUMCUCR = $35.EQUTIMSK = $39.EQUTCCR0 = $33.EQUTCCR1B = $2E.EQUTCNT1L = $2C.EQUTCNT1H = $2D.EQUTCNT0 = $32.EQUSREG = $3F.EQUSPH = $3E.EQUSPL = $3D; Векторы обработчиков прерываний -----------------------------.ORG$0000rjmpstartreti; обработка INT0 (не используется)reti; обработка INT1 (не используется)reti; обработка T/C1 (не используется)reti; обработка T/C1 compare match A (не используется)reti; обработка T/C1 compare match B (не используется)reti; обработка T/C1 overflow (не используется)reti; обработка T/C0 overflowreti; обработка SPI transfer complete (не используется)reti; обработка приема UART (не используется)reti; обработка опустошения данных регистра UART (не используется)reti; обработка передачи UART (не используется)reti; обработка события компаратора (не используется); Конфигурация периферийных устройств --------------------------start:ldir17, $01; инициализация регистраldir16, $01; PORTA0 работает как выходoutDDRA, r16ldir16, $01; инициализация указателя стека ..outSPH, r16; .. на 0x100ldir16, $00outSPL, r16ldir16, $20; OC1A работает как выходoutDDRD, r16ldir16, $40; TCCR1A программируется на переключение ..outTCCR1A, r16; .. OC1A на каждом событии compare matchldir16, $6D; Программирование регистра output compare ..outOCR1AH, r16; .. на коэффициент деления ..ldir16, $DD; .. 28125outOCR1AL, r16ldir16, $20; Конфигурирования режима снаoutMCUCR, r16ldir16, $02; Разрешить прерывание от переполнения T/C0outTIMSK, r16ldir16, $80; Общее разрешение прерыванийoutSREG, r16; Бесконечный цикл ----------------------------------------------loop:rcallmain; Вызов основной подпрограммыldir16, $06; Перезагрузить счетчик 0 для коэффициентаoutTCNT0, r16; .. деления 250ldir16, $06; Запуск счетчика 0 для работы от частоты ..outTCCR0, r16; .. внешнего вывода T0ldir16, $00; Сброс значения таймера 1outTCNT1H, r16ldir16, $00outTCNT1L, r16ldiR16, $0C; Запуск таймера 1 для коэффициента деления ..outTCCR1B, r16; .. 256sleep; Запуск ожидания окончания задержкиldir16, $00; Останов таймера 1outTCCR1B, r16ldir16, $00; Останов таймера 0outTCCR0, r16rjmploop; Основная подпрограмма ----------------------------------------; Она всего лишь переключает вывод PORTA0main:inr16, PORTAeorr16, r17outPORTA, r16ret