Використання переривань в Arduino(початок), Апаратна платформа Arduino
Використання переривань в Arduino (початок)
Часто під час роботи з проектами на мікроконтролерах потрібно запускати фонову функцію через рівні проміжки часу. Це часто реалізується установкою апаратного таймера для вироблення переривання. Це переривання запускає програму обробки переривань (Interrupt Service Routine, ISR) для управління періодичним перериванням. У цій статті я описую установку 8-бітного таймера 2 для вироблення переривань на мікроконтролері ATMega168 Arduino. Я пройдусь по етапах, необхідних для встановлення програми обробки переривань і всередині неї самої.
Переривання?
Як підказує назва, переривання - це сигнали, що переривають нормальний перебіг програми. Переривання зазвичай використовуються для апаратних пристроїв, що потребують негайної реакції на появу подій. Наприклад, система послідовного порту або UART (універсальний асинхронний приймач) мікроконтролера повинен бути обслужений при отриманні нового символу. Якщо цього не зробити швидко, новий символ може бути втрачено.
При надходженні нового символу UART генерує переривання. Мікроконтролер зупиняє виконання основної програми (вашої програми) і перескакує на програму обробки переривань (ISR), призначену для переривання. У разі це переривання за отриманим символом. Ця ISR захоплює новий символ UART, поміщає в буфер, потім очищає переривання і виконує повернення. Коли ISR виконує повернення, мікроконтролер повертається в основну програму та продовжує її з точки виклику. Все це відбувається у фоновому режимі та не впливає безпосередньо на основний код вашої програми.
Якщо у вас запускається багато переривань або переривання генерує швидкодіючий таймер, ваша основна програмабуде виконуватися повільніше, тому що мікроконтролер розподіляє свій машинний час між основною програмою та всіма функціями обробки переривань.
Ви можете замислитись, чому б не просто перевіряти новий символ час від часу, замість використання такого складного процесу переривання. Давайте обчислимо приклад, щоб побачити, наскільки важливими є процеси переривання. Скажімо, у вас є послідовний порт зі швидкістю передачі даних 9600 бод. Це означає, що кожен біт символу надсилається з частотою 9600 Гц або близько 10 кГц. На кожен біт йде 100 мкс. Близько 10 біт потрібно послати один символ, так що ми отримуємо один повний символ кожну мілісекунду або близько того. Якщо наш UART буферизований, ми повинні отримати останній символ до завершення прийому наступного, це дає нам на всю роботу 1 мс. Якщо наш UART не буферизований, ми повинні позбавитися символу за 1 біт або 1 мкс. Розглянемо спочатку буферизований приклад.
Ми повинні перевіряти отримання байта швидше, ніж кожну мілісекунду, щоб запобігти втраті даних. Що стосується Arduino це означає, що наша функція циклу повинна звертатися для читання статусу UART і, можливо, байта даних, 1000 разів на секунду. Це легко можна здійснити, але сильно ускладнить код, який вам потрібно написати. Доки ваша функція циклу не вимагає більше 1 мс до завершення, вам це може зійти з рук. Але уявіть, що вам потрібно обслуговувати кілька пристроїв введення-виводу, або що необхідно працювати на більшій швидкості передачі. Бачите, які неприємності незабаром може принести.
З перериваннями вам не потрібно відстежувати надходження символу. Апаратура подає сигнал за допомогою переривання і процесор швидко викличе ISR, щоб вчасно захопити символ. Замість виділення величезної часткипроцесорного часу на перевірку статусу UART ви ніколи не повинні перевіряти статус, ви просто встановлюєте апаратне переривання і виконуєте необхідні дії в ISR. Ваша головна програма безпосередньо не торкається, і апаратний пристрій не потребує особливих можливостей.
Переривання за таймером
У цій статті я зосереджуся на використанні програмного таймера 2 для періодичних переривань. Вихідна ідея полягала у використанні цього таймера для створення частоти биття в звукових проектах Arduino. Щоб виводити тон або частоту, нам потрібно перемикати порт вводу-виводу на узгодженій частоті. Це можна робити за допомогою циклів затримки. Це просто, але означає, що наш процесор буде зайнятий, нічого не виконуючи, але очікуючи на точний час перемикання висновку. З використанням переривання по таймеру ми можемо зайнятися іншими справами, а висновок нехай перемикає ISR, коли таймер подасть сигнал, що настав час.
Нам потрібно лише встановити таймер, щоб подавав сигнал із перериванням у потрібний час. Замість прокручування марного циклу для затримки часу, наша головна програма може робити щось інше, наприклад, контролювати датчик руху або керувати електроприводом. Що б не потрібно нашому проекту, більше нам не потрібен процесорний час для отримання затримок.
Я опишу в ISR загалом лише те, що стосується переривань таймера 2. Більш детально про використання переривань в процесорах AVR можна прочитати в посібнику користувача avr-libc(англ). На даному етапі не потрібно повного розуміння, але, зрештою, ви можете захотіти отримати можливість прискорити використання переривань, оскільки це важливий інструмент для програм на мікроконтролерах.