====== Переодическое прерывание ======
//Необходимые знания: [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-а. Именно по этой причине нежелательно создавать часовые счетчики и другие точно скоординированные по времени действия с задержкой, а следует использовать прерывание счетчика.