====== Переодическое прерывание ====== //Необходимые знания: [HW] [[et:hardware:homelab:controller]], [HW] [[et:hardware:homelab:digi]], \\ [AVR] [[et:avr:interrupts]], [AVR] [[et:avr:timers]], [LIB] [[et:software:homelab:library:pin]], [LIB] [[et:software:homelab:library:delay]], \\ [LIB] [[et:software:homelab:library:timer]], [PRT] [[et:examples:timer:software_delay]]// ===== Теория ===== Цель данного практического упражнения продемонстрировать использование прерываний на примерах счетчиков. Прерывания – это части программ, реагирующие на различные события, происходящие в микроконтроллере. Прерывания обычно используют для быстрого реагирования на события, но их так же можно использовать для выполнения многих параллельных процессов и действий, требующих точного времени, а так же для экономии тока. К примеру, с помощью прерываний можно заставить мигать 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 #include #include #include // // Обозначение выводов 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-а. Именно по этой причине нежелательно создавать часовые счетчики и другие точно скоординированные по времени действия с задержкой, а следует использовать прерывание счетчика.