12.4. Прерывания по таймеру

Аппаратные прерывания - не единственный вид прерываний, который возможен для Arduino. Существуют также прерывания по таймеру. В контроллере ATmega328 (установленном на Arduino Uno) есть три аппаратных таймера. На самом деле Arduino по умолчанию использует эти таймеры для функции millis(), работы с delay() и для включения ШИМ при вызове analogWrite(). Хотя в языке программирования Arduino отсутствуют специальные конструкции для работы с таймерами, управляя таймерами вручную, можно генерировать произвольные ШИМ-сигналы на любом контакте и делать многое другое. Далее мы расскажем, как с помощью сторонних библиотек (библиотека TimerOne) управлять 16-разрядным таймером Timer1 в ATmega328. Подобные библиотеки есть и для плат Leonardo, но здесь опишем только работу с Arduino Uno.

ПРИМЕЧАНИЕ

Таймер Timer1 служит для включения ШИМ-сигнала на выводах 9 и 10, поэтому при работе с библиотекой TimerOne выполнить функцию analogWrite() для этих контактов не удастся.

12.4.1. Общие сведения о прерываниях по таймеру

Так же, как секундомер в ваших часах, таймеры в Arduino начинают отсчет с нуля, увеличивая значение с каждым тактом кварцевого резонатора. Timer1 16-разрядный таймер, следовательно, значения в нем меняются от 0 до 216 - 1 (или 65 535). Как только это число будет достигнуто, значения сбрасываются в 0 и отсчет начинается снова. Время, через которое таймер достигает максимального значения, зависит от делителя частоты. Поскольку тактовая частота равна 16 МГц, то при отсутствии делителя переполнение и сброс Timer1 произойдет много раз в секунду. Библиотека TimerOne берет на себя все нюансы работы с таймером и позволяет установить любой интервал времени в микросекундах для срабатывания прерывания по таймеру.

12.4.2. Установка библиотеки

Для начала загрузите библиотеку TimerOne либо со страницы сайта Wiley для этой главы, либо непосредственно со страницы https://code.google.com/p/arduinotimerone/downloads. Распакуйте архив в папку с названием TimerOne и скопируйте в папку библиотек Arduino. Размещение этой папки по умолчанию отличается для разных операционных систем:

• Windows - Documents/ Arduino/libraries;

• Mac - Documents/ Arduino/libraries;

• Linux - /homeNOUR USER NAME/sketchbook/libraries.

Если в момент распаковки архива и копирования папки TimerOne среда Arduino IDE была открыта, перезапустите ее и убедитесь, что библиотека загрузилась.

Теперь все готово для работы с Timer1 на Arduino.

- 265 -

12.4.3. Одновременное выполнение двух задач

Важно понимать, что с помощью Arduino нельзя реализовать "истинную" многозадачность. Прерывания создают лишь видимость одновременного выполнения нескольких операций, позволяя переключаться между несколькими задачами чрезвычайно быстро. Использование библиотеки TimerOne позволит заставить мигать светодиод по таймеру, пока в цикле loop() выполняются другие задачи. В конце главы мы опишем проект, где в основном цикле loop() данные выводятся в последовательный порт с задержкой delay(), а по прерываниям таймера осуществляется управление светодиодом и пьезозуммером. Чтобы убедиться, что библиотека работает правильно, можно загрузить программу, приведенную в листинге 12.2, на плату Arduino Uno. Светодиод, подключенный к контакту 13 платы Arduino, будет мигать раз в секунду и управляться с помощью таймера. Если вставить какой-либо фрагмент кода в цикл loop(), то он будет выполняться одновременно.

// Использование прерывания по таймеру

Листинг 12.2. Прерывания по таймеру для проврки blink-timer1.ino

#include <TimerOne.h>

const int LED=13;

void setup()

{

pinMode(LED, OUTPUT);

Timer1.initialize(1000000); // Значение для переполнения 1000000 мкс

// (1 секунда)

Timer1.attachInterrupt(blinky); // Выполнять blinky()при переполнении

}

void loop()

{

// Вставьте сюда любой код

}

// Обработка прерываний по таймеру

void blinky()

{

digitalWrite(LED, !digitalRead(LED)); // Переключить статус светодиода

}

В функции Timer1.initialize() задается временной интервал таймера в микросекундах. В этом примере установлено значение 1 с (1000000 мкс). Аргумент команды Timer1.attachInterrupt() - имя функции, которая будет выполняться по истечении заданного интервала времени. Очевидно, что функция обработки займет меньше времени, чем интервал между прерываниями.

- 266 -

Больше книг — больше знаний!

Заберите 30% скидку новым пользователям на все книги Литрес с нашим промокодом

ПОЛУЧИТЬ СКИДКУ