Необходимые знания: [HW] Kontrollermoodul, [HW] Kasutajaliidese moodul,
[AVR] Katkestused, [AVR] Loendurid/Taimerid, [LIB] Sisend-väljundviigud, [LIB] Viide,
[LIB] Taimerid, [PRT] Tarkvaraline viide
Цель данного практического упражнения продемонстрировать использование прерываний на примерах счетчиков. Прерывания – это части программ, реагирующие на различные события, происходящие в микроконтроллере. Прерывания обычно используют для быстрого реагирования на события, но их так же можно использовать для выполнения многих параллельных процессов и действий, требующих точного времени, а так же для экономии тока. К примеру, с помощью прерываний можно заставить мигать LED, частота мигания которого не зависит от того, что в данный момент происходит в программе.
Следующая программа показывает, как настроить счетчик для создания прерывания. В программе используются два LED-а модуля «Дигитальные входы-выходы», где состояние красного меняется периодически с программной задержкой и состояние зеленого - при создании прерывания. Для мигания LED-а с программной задержкой существует отдельное упражнение и в данном разделе это не разъясняется. Главной задачей является объяснение использования библиотеки счетчика и прерываний.
В начале программы происходит настройка 16-битового счетчика/таймера 1 функцией timer1_init_ctc. С помощью этой функции счетчик устанавливается в режим CTC (на английском языке clear timer on compare match) где максимальным значением не является 216 - 1, а его можно выбирать. В данном случае максимальным значением обозначается значение регистра ICR1. Делителем счетчика является 1024 и значением ICR1 - 14400, в результате чего, в случае тактовой частоты 14,7456 Mhz, периодом счетчика является ровно 1 секунда. Это можно легко вычислить по формуле:
f = 14745600 Hz / 1024 / 14400 = 1
После разрешения прерыванию достигать максимального значения счетчика 1, придется так же разрешить создание прерывания глобально, т.е. по всему микроконтроллеру. Для глобального разрешения прерывания используется функция sei и для запрета cli. Для обозначения раздела программы этих функций и прерываний следует привлечь в программу так же заголовочный файл avr/interrupt.h. Раздел программы прерывания обозначается макрофункцией ISR, где параметром является имя вектора прерывания. При названной настройке вектором прерывания достижения максимального значения счетчика 1 является TIMER1_CAPT_vect.
// // Пример мигающего LED-а Домашней Лаборатории, // который мигает из-за прерывания счетчика. // Для сравнения LED-а мигающего с прерыванием // параллельно работает и LED, мигающий с программной задержкой. // #include <homelab/pin.h> #include <homelab/delay.h> #include <homelab/timer.h> #include <avr/interrupt.h> // // Обозначение выводов LED-ов // pin led_red = PIN(C, 5); pin led_green = PIN(C, 3); // // Прерывание // ISR(TIMER1_CAPT_vect) { // Изменение состояния зеленого LED-а pin_toggle(led_green); } // // Основная программа // int main(void) { // Настройка выводов LED-ов выходом pin_setup_output(led_red); pin_setup_output(led_green); // Настройка таймера в CTC режим timer1_init_ctc( TIMER1_PRESCALE_1024, TIMER1_CTC_TOP_ICR); // Максимальное значение таймера 14400, // что делает длинной периодa 1s // Формула 14,7456Mhz / 1024 = 14400 timer1_set_input_capture_value(14400); // Разрешение прерывания при достижении значения timer1_input_capture_interrupt_enable(true); // Разрешение глобального прерывания sei(); // Бесконечный цикл while (true) { // Программная пауза 1000 миллисекунд sw_delay_ms(1000); // Изменение состояния красного LED-а pin_toggle(led_red); } }
При запуске программы видно, что не зависимо от того, что делает микроконтроллер в основной программе, происходят прерывания и зеленый LED мигает.
Если дать программе поработать несколько минут, выяснится важный аспект, который не был так легко заметен в упражнении программной задержки. Несмотря на то, что задержка мигания красного LED-а 1000 мс, то действительное время, которое расходуется на выполнение каждого цикла, немного дольше. Причина в том, что изменение состояния LED-а, вызов функции задержки и заполнение цикла занимают у процессора время выполнения в несколько тактов. В результате мигание красного LED-а отстает от мигания зеленого LED-а. Именно по этой причине нежелательно создавать часовые счетчики и другие точно скоординированные по времени действия с задержкой, а следует использовать прерывание счетчика.