Переривання на контролері AVR Atmel AVR Studio. Навчальний курс. Концепція переривання. Подаємо голос мікроконтролером ______________________________ Переривання ___________________________

До складу AVR мікроконтролерів входить велика кількість периферійних пристроїв (ADC, Timer/Counters, EXTI, Analog Comparator, EEPROM, USART, SPI, I2C і т.д.), кожна з яких може виконувати певні дії над даними/сигналами та ін. . Ці пристрої вбудовані в мікроконтролер для підвищення ефективності застосування та зниження витрат при розробці різноманітних пристроїв на базі AVR мікроконтролерів.

Процесор спілкується/керує периферійними пристроями за допомогою регістрів вводу/виводу (I/O Registers), які розміщуються у пам'яті даних (Data Memory), що дозволяє використовувати їх як звичайні змінні. Кожен пристрій має свої регістри вводу/виводу.

Усі регістри вводу/вывода (I/O Registers) можна розділити втричі групи: регістри даних, регістри управління і регістри стану.

За допомогою регістрів управління (Control Registers) реалізується налаштування пристрою для роботи в тому чи іншому режимі, з певною частотою, точністю і т.д., а за допомогою регістрів даних (Data Registers) зчитується результат роботи даного пристрою (аналог-цифрове перетворення, прийняті дані, значення таймера/лічильника тощо). Здається, нічого складного тут немає (взагалі-то тут і справді нічого складного немає:)), ввімкнув пристрій, вказав бажаний режим роботи, а потім тільки залишається стригти купони читати готові дані і використовувати їх у обчисленнях. Все питання полягає в тому "коли" читати ці самі дані (завершив пристрій роботу або все ще обробляє дані), адже всі периферійні пристрої працюють паралельно з ядром мікроконтролера, та ще й на різних частотах. Постає питання реалізації спілкування та синхронізації між процесором та периферійним пристроєм.

Як ви вже напевно здогадалися, для реалізації спілкування та синхронізації між пристроєм і процесором використовуються "регістри стану" (Status Registers), в яких зберігається поточний стан роботи того чи іншого пристрою. стану” (прапор), поточне значення якого, "говорить" про поточний стан даного пристрою або його окремо взятої функції (робота завершена/не завершена, помилка при обробці даних, регістр порожній і т.д.).

Механізм спілкування між процесором і периферійним пристроєм реалізується шляхом опитування прапорів (flag polling), що відповідають за ту чи іншу функцію даного пристрою. Залежно від значення того чи іншого прапора (стан пристрою) можна змінювати хід виконання програми (розгалуження). Наприклад:

Перевірка якщо певний прапор встановлено (відбулася певна подія):

if (RegX & (1<< Flag) ) // якщо прапор у регістрі RegX встановлено
{
// роби щось
}

Очікування завершення будь-якої дії (подія):

while (! (RegX & (1<

Опитування прапорів – заняття досить ресурсомістке, як у плані обсягу програми, і у плані швидкодії програми. Оскільки загальна кількість прапорів в AVR мікроконтролерах досить велика (перевага), то реалізація спілкування між процесором і пристроєм шляхом опитування прапорів призводить до зниження ККД (швидкість коду/розмір коду) написаної вами програми, до того ж програма стає дуже заплутаною, що сприяє появі помилок, які важко виявити навіть при детальному налагодженні коду.

Для того, щоб підвищити ККД програм для AVR мікроконтролерів, а також полегшити процес створення та налагодження даних програм, розробники забезпечили всі периферійні пристрої "джерелами переривань" ( Interrupt sources), деякі пристрої можуть мати кілька джерел переривання.

За допомогою джерел переривань реалізується механізм синхронізаціїміж процесором і периферійним пристроєм, тобто процесор почне прийом даних, опитування прапорів та ін дії над периферійним пристроєм тільки тоді, коли пристрій буде до цього готовий (повідомить про завершення обробки даних, помилку при обробці даних, регістр порожній, і т.д. д.), шляхом генерації "запиту на обробку переривання" ( Interrupt request), залежно від значення деякого прапора (стан пристрою/функції/події).

У літературі, дуже часто, весь ланцюжок подій, починаючи від "запиту на обробку переривання" (IRQ) і до "процедури обробки переривання" (ISR), скорочено називають - переривання ( Interrupt).

Що таке переривання?


Переривання (Interrupt) – сигнал, що повідомляє процесору про настання будь-якої події. При цьому виконання поточної послідовності команд припиняється і управління передається процедурі обробки переривання, що відповідає даній події, після чого виконання коду триває рівно з того місця, де він був перерваний (повернення управління). (Wiki)

Процедура обробки переривання(Interrupt Service Routine) – це ні що інше як функція/підпрограма, яку слід виконати у разі виникнення певної події. Будемо використовувати саме слово "процедура", щоб підкреслити її відмінність від усіх інших функцій.

Головна відмінність процедури від простих функцій полягає в тому, що замість звичайного "повернення з функції" (ассемблерова команда RET), слід використовувати "повернення з переривання" (асемблерна команда RETI) - " RETurn from Interrupt".

Властивості AVR переривань:

  • Кожен периферійний пристрій, що входить до складу AVR мікроконтролерів, має як мінімум одне джерело переривання (Interrupt source). До всіх цих переривань слід віднести і переривання скидання – Reset Interrupt, призначення якого відрізняється від інших.
  • За кожним перериванням, суворо закріплений вектор (посилання), що вказує на процедуру обробки переривання (Interrupt service routine). Всі вектори переривань розташовуються на самому початку пам'яті програм і разом формують "таблицю векторів переривань" (Interrupt vectors table).
  • Кожному перериванню відповідає певний "біт активації переривання" (Interrupt Enable bit). Таким чином, щоб використовувати певне переривання, слід записати в його біт активації переривання - лог. одиницю. Далі, незалежно від того чи активували Ви чи ні певні переривання, мікроконтролер не почне обробку цих переривань, поки в "біт загального дозволу переривань" (Global Interrupt Enable bit в регістрі стану SREG) не буде записана лог. одиниця. Також, щоб заборонити всі переривання (На невизначений час), в біт загального дозволу переривань слід записати - бал.

Переривання Reset, на відміну всіх інших, не можна заборонити. Такі переривання ще називають Non-maskable interrupts.

  • У кожного переривання є певний пріоритет. Пріоритет переривання залежить від його розташування в "таблиці векторів переривань". Чим менше номер вектора в таблиці, тим вище пріоритет переривання. програм. Зовнішнє переривання INT0, що йде слідом за перериванням Reset в "таблиці векторів переривань", має пріоритет менше ніж у Reset, але вище ніж у всіх інших переривань і т.д.

Таблиця векторів переривань, крім вектора Reset, може бути переміщена на початок Boot розділу Flash пам'яті, встановивши біт IVSEL у регістрі GICR. Вектор скидання також може бути переміщений на початок Boot розділу Flash пам'яті, шляхом програмування біта фьюз – BOOTRST.



Таблиця векторів переривань ATmega16

Прототип процедури обробки переривання


Щоб оголосити деяку функцію як процедуру обробки того чи іншого переривання, необхідно дотримуватися певних правил прототипування, щоб компілятор/компонувальник змогли правильно визначити і пов'язати необхідне переривання з процедурою її обробки.

По-перше, процедура обробки переривання не може нічого приймати як аргумент (void), а також не може нічого повертати (void). Це пов'язано з тим, що всі переривання в AVR асинхронні, тому не відомо де буде перервано виконання програми, у кого приймати і кому повертати значення, а також для мінімізації часу входу та виходу з переривання.

void isr (void)

По-друге, перед прототипом функції слід зазначити, що вона є процедурою обробки переривання. Як вам відомо, у мові Сі виконується лише той код, що використовується у функції main. Оскільки процедура обробки переривання функції main ніде не використовується, то для того щоб компілятор не "викинув" її за непотрібністю, перед прототипом процедури слід вказати що ця функція є процедурою обробки переривання.

Прототип процедури обробки переривання у середовищі AVR Studio

#include

ISR (XXX_vect)
{

}

В AVR Studio (AVR GCC), кожна процедура обробки переривання починається з макровизначення ISR, після чого в круглих дужках слідує конструкція:

XXX_vect

де "XXX" це ім'я вектора переривання. Всі імена векторів, для певного AVR мікроконтролера, можна знайти в "таблиці векторів переривань" даташита даного мікроконтролера або його заголовному файлі. Наприклад, "таблиця векторів переривань" для мікроконтролера ATmega16 наведена на рис.1, де в колонці Source, наведені всі імена векторів переривань. Також імена можна подивитися в заголовному файлі даного мікроконтролера (C: Program Files Atmel AVR Tools AVR Toolchain\avr\include\avr\iom16.h), див. рис.2. Все що нам треба зробити, це знайти в таблиці ім'я потрібного нам вектора і до нього додати суфікс "_vect".


Рис.2 Заголовковий файл ATmega16 для AVR Studio

Наприклад, напишемо процедуру обробки переривання прийому байта через USART (USART, Rx Complete) :

ISR (USART_RXC_vect)
{
// Тіло оброблювача переривання
}

До речі: перед тим як використовувати будь-яке переривання в AVR Studio, слід включити в проект заголовки io.h і interrupt.h:

#include
#include

Докладніше про обробників переривань в AVR Studio (AVR GCC) можна почитати у розділі Introduction to avr-libc's interrupt handling.

Прототип процедури обробки переривання у середовищі ImageCraft

#pragma interrupt_handler : iv_XXX
void< handler_name>(void)
{
// Тіло оброблювача переривання
}

У середовищі ImageCraft прототип процедури обробки переривання виглядає наступним чином:

void< handler_name>(void)

де , це будь-яке ім'я, яке ви захочете дати цьому обробнику переривання. Одна з вимог щодо оголошення процедур обробки переривань свідчить, що перед прототипом функції слід зазначити, що вона є обробником переривання. Це робиться за допомогою pragma-директиви interrupt_handler :

#pragma interrupt_handler : iv_XXX

де це ім'я тієї функції, що буде використовуватися як обробник переривання, а конструкція "iv_XXX", це ім'я вектора переривання (XXX) з префіксом "iv_". Як і у випадку з AVR Studio, всі імена векторів, для певного AVR мікроконтролера, можна знайти в "таблиці векторів переривань" даташита даного мікроконтролера або його заголовному файлі (див. рис.3).


Рис.3 Заголовковий файл ATmega16 для ImageCraft IDE

Наприклад, процедура обробки переривання по прийому байта через USART (USART, Rx Complete) в середовищі ImageCraft буде виглядати так:

#pragma interrupt_handler usat_rxc_isr: iv_USART_RXC
void usat_rxc_isr(void )
{
// Тіло оброблювача переривання
}

Більш детально про процедури обробки переривання в ImageCraft IDE можна знайти в меню Help->Programming the AVR->Interrupt Handlers середовища розробки.

Іноді, якщо кілька обробників переривання повинні робити те саме, то для економії пам'яті програм, можна направити кілька векторів переривання на ту саму процедуру обробки переривання.

У середовищі AVR Studio це виглядає так:

ISR (INT0_vect)
{
// Do something
}
ISR(INT1_vect, ISR_ALIASOF(INT0_vect) );

Спочатку йде процедура обробки переривання для певного вектора, у разі INT0. Всі інші процедури можуть посилатися на будь-який обробник переривання за допомогою конструкції:

ISR (YYY_vect, ISR_ALIASOF(XXX_vect) );

де YYY це ім'я вектора переривання, який посилається на раніше оголошений обробник переривання для вектора XXX.

У середовищі ImageCraft це виглядає так:

#pragma interrupt_handler : iv_XXX : iv_YYY
void< handler_name>(void)
{
// Тіло оброблювача переривання
}

#pragma interrupt_handler : iv_XXX
#pragma interrupt_handler : iv_YYY
void< handler_name>(void)
{
// Тіло оброблювача переривання
}

де вектори XXX і YYY посилаються на той самий обробник переривання .

Як працює переривання в мікроконтроллерах AVR?

1. Припустимо, відбувся " запит на обробку переривання” (IRQ).

До речі: якщо одночасно відбудуться кілька запитів на обробку переривання, то першим буде оброблено переривання з найвищим пріоритетом, решта запитів буде оброблена після завершення високопріоритетного переривання.

2. Перевірка.

Якщо біт активації даного переривання встановлений (Interrupt enable bit), а також I-біт (біт загального дозволу переривань) регістру стану процесора (SREG) встановлений, то процесор починає підготовку процедури обробки переривання, при цьому біт загального дозволу переривань (I-біт регістра) SREG) скидається, забороняючи таким чином всі інші переривання. Це відбувається для того, щоб ніяка інша подія не змогла перервати обробку поточного переривання.

До речі: якщо в процедурі обробки переривання встановити I-біт стан лог. одиниці, будь-яке активоване переривання може у свою чергу перервати обробку поточного переривання. Такі переривання називаються вкладеними (Nested interrupts).

3. Підготовка.

Процесор завершує виконання поточної асемблерної команди, після чого поміщає адресу наступної команди в стек (PC-> STACK). Далі процесор перевіряє, яке джерело переривання подав "запит на обробку переривання" (IRQ), після чого скориставшись вектором даного джерела (посилання) з таблиці векторів (який залізно закріплений за кожним джерелом переривання), переходить у процедуру обробки переривання (інструкція JMP). все, про все процесор витрачає мінімум 4 такти (залежно від моменту появи запиту та тривалість виконання поточної інструкції).

До речі: якщо IRQ станеться, коли мікроконтролер перебуває у сплячому режимі (sleep mode), час реакції на IRQ збільшується ще чотири такту, плюс час закладене у ф'юз бітах SUT1 і SUT0 (Start-Up Time).

Стек є область пам'яті, яку ЦПУ використовує для збереження та відновлення адрес повернення з підпрограм.
Практично у всіх мікроконтролерів AVR стек розміщується у SRAM. Для адресації поточного елемента (вершини стека) використовується покажчик стека SP (Stack Pointer). Це однобайтовий РВВ SPL у моделей з обсягом пам'яті даних до 256 байт, або двобайтовий SPH:SPL (SPH – старший байт, SPL – молодший байт).

Коли мікропроцесор зустрічає одну з інструкцій викликів rcall/call/ecall/icall/eicall, то адреса наступного слова в пам'яті програм апаратно копіюється в стек. У момент виходу з підпрограми за командою ret адреса повернення відновлюється зі стека до програмного лічильника. У моделях з об'ємом пам'яті програм 128 і 256 к/слів для збереження PC в стеку потрібно 3 байти, для всіх інших - 2 байти. При збереженні кожного байта вміст SP зменшується на одиницю, а при відновленні відповідно збільшується.

Рис.9 Розташування стека у пам'яті даних

Програміст повинен самостійно визначити місце розташування стека на самому початку програми. З точки зору максимальної його глибини, вершину стека потрібно помістити в самому кінці SRAM, як показано на рис.9:

Include "m8def.inc" ldi temp,low(RAMEND) ;встановлюємо SP = RAMEND out SPL,temp ;для ATmega8 SP = 0x045F ldi temp,high(RAMEND) out SPH,temp

Константа RAMEND із стандартного заголовного файлу m8def.inc має значення адреси останнього осередку SRAM.

У діапазоні адрес SRAM між РВВ і поточним положенням SP розміщуються змінні прикладної програми. Тому дуже важливо заздалегідь оцінити максимальний розмір стеку (глибину стека). Може статися так, що вершина стека підніметься занадто високо і почне "затирати" дані користувача, а це одна з найбільш складних помилок!

Стек AVR, крім збереження адрес повернення, має ще одне дуже важливе призначення. Він дозволяє зберігати будь-які дані спеціально призначеними для цього командами push Rr (завантаження в стек) та pop Rd (вивантаження зі стеку). Щоразу під час виконання push Rr вміст Rr копіюється в стек, після чого SP зменшується на одиницю. При виконанні pop Rr вміст комірки стека, яку вказує SP, відновлюється в Rr, а саме значення SP інкрементується. Стек подібного роду має організацію Last In First Out (Останній Увійшов Перший Вийшов): регістр, збережений останньою командою push, буде відновлено першою командою pop:

; SP Рівень стека після команди push R16; зберігаємо R16 0x045F R16? ? push R17 ;зберігаємо R17 0x045E R16 R17 ? push R18 ;зберігаємо R18 0x045D R16 R17 R18 ̣̣̣̣̣̣̣̣ pop R18 ;відновлюємо R18 0x045D R16 R17 ? pop R17; відновлюємо R17 0x045E R16? ? pop R16; відновлюємо R16 0x045F? ? ?

Через стек дуже легко можна обміняти вміст регістрів місцями:

; Обмін R16<->R17 SP Рівень стека після команди push R16 ;зберігаємо R16 0x045F R16 ? push R17 ;зберігаємо R17 0x045E R16 R17 pop R16 ;відновлюємо R16 0x045E R16 ? pop R17; відновлюємо R17 0x045F? ?


Рис.10 Приклад роботи стека

На рис.10 наведено невеликий фрагмент коду, в якому покроково розглянуто процес зміни стека при вході та виході з підпрограми toggle та збереження та відновлення регістра R17. Це типовий приклад, де можуть знадобитися інструкції push/pop. Підпрограма toggle використовує РОН R17 у своїх потребах, але цей регістр може використовуватися і в ході основної програми. Тому, щоб уникнути пошкодження даних, R17 перед модифікацією завантажується в стек і відновлюється перед командою ret.


Поговоримо про переривання.Слово переривання говорить саме за себе, відбувається зупинка якогось процесу на якийсь час, для того щоб виконати додаткові дії. Переривання можуть бути зовнішніми чи внутрішніми. Наведу простий приклад, почутий з вуст мого друга.

Зібрався він помити посуд на кухні, взявся з азартом, засукавши рукави ... але посуд виявився жирним і він був змушений перерватися, щоб знайти на одній з полиць кухонного гарнітура засіб для миття жирного посуду, після чого знову продовжив своє заняття. Але в якийсь момент задзвонив телефон, і він знову перервався від своєї роботи, підняв трубку, дзвонила теща і сказала, що прийде в гості, отже, треба сходити в магазин купити продукти до її приходу. Сходив до магазину і тільки після цього домив посуд.

На цьому прикладі видно два види переривань, перше – пов'язане з виконанням основної роботи – пошук засобу для жирного посуду – внутрішнє переривання, друге – телефонний дзвінок – зовнішнє переривання.
У мікроконтролері зовнішні переривання виникають за рахунок сигналів, що надходять від інших джерел, внутрішні – за рахунок пристроїв, вбудованих у сам мікроконтролер. Чим же такі привабливі переривання?
Перше - те, що ми можемо зупинити основний процес до виконання будь-яких інших функції, з наступним продовженням цього процесу.
Другим, і, напевно, у багатьох випадках основним вважається прискорення процесу виконання всіх функцій, за рахунок внутрішніх додаткових пристроїв. Повернемося до нашого прикладу. Допустимо, мій друг взявся мити посуд, коли його дружина вже прийшла додому. Побачивши жирний посуд, він просить його знайти засіб для миття посуду, і доки він миє, вона вже принесе йому цей засіб. Але, ось задзвонив телефон, слухавку підніме дружина, поговорить із мамою і сходить до магазину. Спільно всі справи зроблено дуже швидко!
А ще простіше зациклиться - тобто. основної програми немає.
Мій друг сидить на дивані і нічого не робить, доморобітниця побачивши брудний посуд, говорить йому про це, і отримавши дозвіл, починає мити сама. Коли дзвонить телефон, він каже дружині, щоб вона підняла слухавку, дружина розмовляє телефоном, і поле розмови йде до магазину за продуктами… Краса! У такому разі в мікроконтролері одночасно працюють кілька пристроїв введення-виводу (у сучасних мікроконтролерах їх може бути досить багато) і загальна продуктивність процесора зростає у багато разів, але переривання від пристроїв обробляються послідовно один за одним (не одночасно), залежно від пріоритету ( у нашому прикладі дружина має більший пріоритет, ніж доморобітниця).

За управління перериваннями відповідають кілька регістрів
SREG - регістр статусу(Стану). Дивимося таблицю пристроїв вводу-виводу. Сьомий біт регістру SREG – прапор I (interrupt), який називається прапором глобального дозволу переривань.Якщо прапор опущений (сьомий біт дорівнює нулю), всі переривання заборонені. Якщо підняти прапор (встановити I в 1), ми дозволимо переривання.

Встановлюється та скидається прапор І командами:
SEI - дозволити переривання
CLI - заборонити переривання
Які з переривань працюватимуть, задається за допомогою регістрів званих – масками переривань.
Позначаються маски переривань наступним чином:
TIMSK,..,..,.. – керування перериваннями від таймерів та інших вбудованих пристроїв.
GIMSK (GIKR у сімействі Mega) - управління всіма зовнішніми перериваннями.
Маски переривань у свою чергу залежать від прапорів переривань:
TIFR та GIFR відповідно(Не плутайте з прапором глобального дозволу переривань).

Послідовність виконання переривань:
При включенні мікроконтролера всі прапори переривань скинуті в 0. Для включення переривань програма має встановити прапор I регістру SREG в 1. Після цього прописати регістри маски зі встановленими локальними перериваннями (переривання, які нам потрібні).
Коли приходить (сигнал) запит на переривання, він піднімає прапор переривання (навіть у разі якщо переривання заборонено, в організацію вкладених переривань і пріоритету між різними перериваннями). Якщо немає заборони переривань, то контролер звернеться до відповідного (Interrupt Vectors) - вектор переривань, призупиняючи поточну програму.
Вектор переривання– це фіксований рядок програмної області, куди переходить програма у разі переривання.
Весь список векторів переривання – називається таблицею векторів переривання, який розташовується на початку програмного коду.
Отже, у момент звернення до вектора переривання, прапор I регістру SREG і прапор, що викликав переривання, скидається в 0, забороняючи інші переривання. Якщо в процесі виконання переривання виникли інші запити переривань, прапори цих переривань залишаються піднятими. Після закінчення виконання поточного переривання прапор I регістру SREG піднімається, дозволяючи виконання наступного. Якщо надійшло кілька запитів, і їхні прапори виявляться піднятими, то першим буде виконано переривання, чий вектор менший за адресою в таблиці, ближче до початку пам'яті. За ним другий, і таке інше. Крім цього, програміст може організувати так зване вкладене переривання, коли в процесі виконання програми переривання виникає ще одне переривання. Тоді припиняється виконання поточного переривання та виконується нове, після завершення якого поновлюється виконання зупиненого переривання.

Як приклад наведена таблиця векторів переривання для ATtiny2313

Таблиця векторів переривання для Атмега16 виглядає так:

При порівнянні таблиці зовсім не збігаються.
У сімействі ATtiny рядок вектора переривання займає 16 біт, а в сімействі Mega займають 32 біти (зверніть увагу на адреси векторів переривання, нагадаю, що адресний рядок у програмній області представлений 16 бітним словом).

Програмний код для ATtiny2313 може виглядати так:
.cseg .org 0 rjmp Reset rjmp INT_0 rjmp INT_1 rjmp Timer1_capt1 rjmp Timer1_comp1 rjmp Timer1_OVF1 rjmp Timer0_OVF0 rjmp UART_RX rjmp UART_UDRE rjmp UART compB rjmp Timer0_compA rjmp Timer0_compB rjmp USI_START rjmp USI_OVERFLOW rjmp EE_READY rjmp WDT_ OVERFLOW

Як бачимо, вектор переривання створює відносний перехід на мітки програм переривань. Нижче у таблиці показані варіанти; 1. Коли немає переривань; 2, 3. із зовнішнім перериванням по входу INT_1.
Якщо мітки «порожні» (під міткою немає програми), то нічого не відбувається, і програма послідовно «пробігшись» по мітках, що залишилися, благополучно доходить до команди RETI- Interrupt return - вихід з обробника перериванняяк показано у першому стовпці таблиці.

Щоб виконати програму переривання, наприклад на вході INT_1, потрібно мітку INT_1: винести зі списку. Це схематично показано у другому стовпці таблиці.
Але, програмісту незручно щоразу прописувати всі переривання та окремо мітки до них, особливо в останніх моделях, де таблиця досить велика, простіше в рядку вектора переривання відразу написати команду RETI, якщо переривання не використовується. Тоді програма буде виглядати, як показано у третьому стовпці таблиці.

В AVR-контролерах залежно від моделі може бути від 1 до 8 входів зовнішніх переривань.
Розглянемо систему керування зовнішніми перериваннями. Для цього передбачені такі комбінації I/O-регістрів залежно від моделі (див. відповідний DataSheet):
- GIMSK, EIFR, PCMSK, MCUCR;
- GIKR, GIFR, MCUCR;
- EIMSK, EICR, EIFR;
GIMSK, GIKR, EIMSK - маски переривань,
EIFR, PCMSK, GIFR, EIFR – прапори переривань
Для дозволу чи заборони зовнішніх перериваньпризначені керуючі регістри: GIMSK-(General Interrupt Mask Register)(Tiny), GICR-(General Interrupt Control Register)(Mega), MCUCR - (MCU Control Register)




EIFR- External Interrupt Flag Register: 1- дозволено, 0 – заборонено. Кожен біт (прапор) дозволяє відповідному висновку працювати як джерело переривань.

Біти управління регістра GIMSK:
Біт 7 - INT1: External Interrupt Request 1 Enable – біт дозволу переривання INT1: 1 – дозволено, 0 – заборонено. Переривання буде формуватися, навіть якщо висновок INT1 налаштований як вихід. Біт INT1 налаштовуються на переривання у регістрі прапорів EIFR. Висновок INT1 синхронізований із тактовим генератором.

Біт 6 - INT0: External Interrupt Request 0 Enable - біт дозволу переривання INT0: 1 - дозволено, 0 - заборонено. Переривання буде формуватися, навіть якщо висновок INT0 налаштований як вихід. Біт INT0 налаштовуються на переривання у регістрі прапорів EIFR. Висновок INT10 синхронізований із тактовим генератором.

Біт 5 - PCIE: Pin Change Interrupt Enable - біт дозволу переривання на висновках PCINT0 ... 7: 1 - дозволено, 0 - заборонено. Будь-яка зміна на будь-якому висновку PCINT0…7 буде формувати переривання. Висновки PCINT0 ... 7 налаштовуються на переривання індивідуально, бітами в регістрі прапорів PCMSK.

PCMSK- Pin Change Mask Regiser - регістр прапорів PCMSK: 1- дозволено, 0 – заборонено. Кожен біт (прапор) дозволяє відповідному висновку працювати як джерело переривань. Висновки PCINT0 ... 7 не синхронізовані з тактовим генератором, тобто. переривання настає за фактом зміни на будь-якому висновку.

Mega8

та відповідний йому регістр прапорів


Біт 7

Біт 6 - INT0: External Interrupt Request 0 Enable - біт дозволу переривання INT0: 1 - дозволено, 0 - заборонено. Переривання буде формуватися, навіть якщо висновок INT0 налаштований як вихід. Біт INT0 налаштовуються на переривання у регістрі прапорів GIFR



GIFR - General Interrupt Flag Register: 1- дозволено, 0 - заборонено. Кожен біт (прапор) дозволяє відповідному висновку працювати як джерело переривань.

Біти управління регістру GICR:
Біт 7– : External Interrupt Request 1 Enable – біт дозволу переривання INT1: 1 – дозволено, 0 – заборонено. Переривання буде формуватися, навіть якщо висновок INT1 налаштований як вихід. Біт INT1 налаштовуються на переривання у регістрі прапорів GIFR

Біт 6 - INT0: External Interrupt Request 0 Enable - біт дозволу переривання INT0: 1 – дозволено, 0 – заборонено. Переривання буде формуватися, навіть якщо висновок INT0 налаштований як вихід. Біт INT0 налаштовуються на переривання у регістрі прапорів GIFR

Біт 5 - INT2: External Interrupt Request 2 Enable - біт дозволу переривання INT2: 1 – дозволено, 0 – заборонено. Переривання буде формуватися, навіть якщо висновок INT2 налаштований як вихід. Біт INT2 налаштовуються на переривання у регістрі прапорів GIFR

Функціями входів INT0 та INT1 у всіх контролерах управляють молодші біти регістру MCUCR

MCUCR-MCU Control Register
Біти управління:
Біти 1, 0 – ISC01, ISC00 (Interrupt Sense Control 0 Bit 1 and Bit 0) – стан даних бітів визначає подію виведенні INT0, у якому формується переривання INT0:
ISC01 = 0, ISC00 = 0 - рівень логічного нуля;
ISC01=0, ISC00=1 – будь-яка зміна логічного стану;
ISC01 = 1, ISC00 = 0 - по спадаючому фронту;
ISC01 = 1, ISC00 = 1 - по наростаючому фронту.

Біти 3, 2 – ISC11, ISC10 (Interrupt Sense Control 1 Bit 1 and Bit 0) – стан даних бітів визначає рівень сигналу на виведенні INT1, яким формується переривання INT1:
ISC11 = 0, ISC10 = 0 - рівень логічного нуля;
ISC11=0, ISC10=1 – будь-яка зміна логічного стану;
ISC11=1, ISC10=0 – по спадаючому фронту;
ISC11 = 1, ISC10 = 1 - по наростаючому фронту.

Ну от, начебто з мінімумом про зовнішні переривання поговорили.
Зрозуміло, що для того, щоб переривання працювали, потрібно їх відповідно прописувати.
Допишемо розпочату для tiny, ініціалізацію переривання на INT1 по зростаючому фронту сигналу:

Ldi r16,0x80; запишемо в r16 число 0b10000000 ldi r17,0x0C; запишемо в r17 число 0b00001100 out MCUCR, r17; переривання сформується по наростаючому фронту ISC11 = 1, ISC10 = 1 out GIMSK, r16; виставимо маску INT0 sei
До речі на tiny2313 можна сформувати переривання на будь-яких висновках PCINT0…7, на Mega до 48 серії ці можливості відсутні.
Є такі операції, при виконанні яких переривання, що виникли, можуть викликати збій програми. У разі перед початком виконання операції пишемо CLI, а після SEI. Називаються такі операції. атомарними.
Бажано, щоб програми переривань були компактними та виконувались з максимальною швидкістю, тому що метою будь-яких переривань є фіксація події. Якщо з різних причин програма виконується повільно, достатньо зафіксувати подію і обробити її трохи пізніше.

Щоб не захаращувати зайвою інформацією викладений матеріал, рекомендую читачам користуватися даташитами, а якщо не все зрозуміло, то частіше запитувати на форумах.
Далі детально розглянемо внутрішні переривання на основі вбудованих таймерів. читачів. Для участі у голосуванні зареєструйтесь та увійдіть на сайт із вашими логіном та паролем.

Системи переривань - важлива частина будь-якої системи, що управляє.

Від роботи багато в чому залежить те, наскільки ефективно мікропроцесорна система виконує свої функції. Загальна структура системи переривань МК-51 представлена ​​на рис. 14.3.

Мікроконтролери сімейства МК-51 забезпечують підтримку п'яти джерел переривань:

* двох зовнішніх переривань, що надходять по входах INT0 та INT1 (лінії порту Р3: Р3.2 та Р3.3 відповідно);

* двох переривань від таймерів/лічильників Т/С0 та Т/С1;

* Переривання від послідовного порту.

Запити на переривання фіксуються в регістрах спеціальних функцій мікроконтролера: прапори IE0, IE1, TF0, TF1 запитів на переривання від INT0, INT1, T/C0 та T/C1 містяться в регістрі управління TCON (табл. 14.4), а прапори RI та TI запитів на переривання від послідовного порту - у регістрі SCON управління послідовним портом.

Таблиця 14.4. Формат регістру TCON

0 IT0 Налаштування виду переривання INT0

1 IE0 Прапор запиту переривання INT0

2 IT1 Налаштування виду переривання INT1

3 IE1 Прапор запиту переривання INT1

4 TR0 Увімкнення таймера/лічильника 0

5 TF0 Прапор переповнення (запит переривання) таймера/лічильника 0

6 TR1 Увімкнення таймера/лічильника 1

7 TF1 Прапор переповнення (запит переривання) таймера/лічильника 1

Прапори TF0 і TF1 встановлюються апаратно при переповненні відповідного таймера/лічильника (точніше, при переході T/Cx зі стану "усі одиниці" у стан "усі нулі").

Прапори IE0 та IE1 встановлюються апаратно від зовнішніх переривань IT0 та IT1 відповідно. Зовнішній запит може викликати встановлення прапора або за низького рівня сигналу на відповідному вході, або при перемиканні цього сигналу з високого рівня на низький (з частотою, що не перевищує половини частоти зовнішньої синхронізації МК).

Налаштування на тип запиту здійснюється програмною установкою біт IT0 та IT1 у регістрі управління TCON. Установка ITx = 0 налаштовує систему переривання на запит за низьким рівнем сигналу, ITx = 1 - запит переривання по спаду сигналу.

Прапори TI та RI встановлюються апаратно схемою послідовного інтерфейсу після закінчення передачі або після закінчення прийому відповідно.

Усі вказані прапори запитів на переривання програмно доступні для встановлення та скидання. Програмна установка прапора запиту на переривання призводить до такої реакції мікроконтролера, що і апаратна установка того ж прапора.

Прапори TF0 і TF1 скидаються апаратно під час передачі управління програмі обробки відповідного переривання.

Скидання прапорів IEx виконується апаратно при обслуговуванні переривання лише в тому випадку, якщо переривання було налаштоване на сприйняття спаду сигналу INTx. Якщо переривання було налаштоване на сприйняття рівня сигналу запиту, то скидання прапора IEx має виконувати програму обслуговування переривання, впливаючи на джерело переривання для зняття запиту.

Прапори TI та RI скидаються лише програмним шляхом.

Кожен вид переривання індивідуально дозволяється або забороняється установкою або скиданням відповідних розрядів регістру дозволу переривання IE. Цей регістр містить і біт загальної заборони всіх переривань. ФорматреєструIE наведено в табл. 14.5.

Таблиця 14.5. Призначення розрядів регістру IE

Позиція у регістрі

Мемоніка бита

Функція

Заборона переривання від усіх джерел

Не використовується

Не використовується

Заборона переривання від послідовного порту

Заборона переривання від таймера/лічильника T/C1

Заборона переривання від зовнішнього джерела INT1

Заборона переривання від таймера/лічильника T/C0

Заборона переривання від зовнішнього джерела INT0

Кожному виду переривання може бути програмно присвоєний один із двох можливих пріоритетів: 0 – нижчий або 1 – вищий.

Налаштування пріоритетів здійснюється встановленням або скиданням відповідного біта регістру пріоритетів переривань IP. Формат цього регістру наведено у табл. 14.6.

При одночасному надходженні запитів переривання від джерел, що мають різні пріоритети, спочатку обробляється запит від пріоритетного джерела.

У разі одночасного надходження кількох запитів на переривання з однаковим пріоритетом порядок їхньої обробки визначається апаратними засобами мікроконтролера і не може бути змінений програмно. Цей порядок відповідає послідовності опитування прапорів запитів переривань, що має такий вигляд:

IT0 -> TF0 -> IT1 -> TF1 -> (RI, TI)

Таблиця 14.6. Призначення розрядів регістру IP

Позиція в регістрі Мнемоніка біта Функція

7 - Не використовується

6 - Не використовується

5 - Не використовується

4 PS Пріоритет переривання від послідовного порту

3 PT1 Пріоритет переривання від таймера/лічильника T/C1

2 PX1 Пріоритет переривання від зовнішнього джерела INT1

1 PT0 Пріоритет переривання від таймера/лічильника T/C0

0 PX0 Пріоритет переривання від зовнішнього джерела INT0

Апаратно реалізований виклик обробника переривань складається з наступних дій:

* Збереження значення програмного лічильника в стеку;

Точки входу в обробник переривання для кожного джерела переривань апаратно зафіксовані. Їх значення наведено у табл. 14.7.

Таблиця 14.7. Адреси точок входу в обробники переривань

Джерело переривання

Адреси точок входу в обробники переривань

Зовнішнє переривання ( ITO)

Таймер-лічильник (TFO)

Зовнішнє переривання (IT1)

Таймер-лічильник (TF1)

Послідовний порт (R1 або T1)

За вказаною адресою повинна розміщуватись перша команда обробника переривання. Як правило, такою командою є команда безумовного переходу в місце програми, де фактично розташовується обробник.

При переході на підпрограму обробки переривання автоматично незалежно від стану регістру IE забороняються всі переривання, які мають рівень пріоритету, що дорівнює рівню пріоритету переривання, що обслуговується, - тобто вкладені переривання з рівним рівнем пріоритету заборонені. Таким чином, низькопріоритетне переривання (має "0" у відповідному розряді регістра IP) може перериватися високопріоритетним (має "1" у відповідному розряді регістра IP), але не низькопріоритетним. Обслуговування високопріоритетного переривання може бути перервано іншим джерелом.

Повернення з обробника переривань здійснюється за допомогою команди RETI, яка відновлює зі стека значення програмного лічильника PC, збереженого там у момент виклику обробника переривання, та логіку пріоритетів переривань.

Для чого потрібні зовнішні переривання

Переривання — це подія яким переривається виконання основного коду програми (наприклад функції main) і управління передається функції обробнику переривання. Відповідно зовнішні переривання - це деякі зовнішні події, що переривають виконання основного коду програми.

Зовнішні переривання дозволяють отримати швидку, гарантовану реакцію зовнішні події. Тому найчастіше застосування зовнішніх переривань це реалізація лічильників імпульсів, вимірювання частоти або тривалості імпульсів, програмна реалізація uart, one-wire, i2с, spi, а також обробка сигналів від зовнішніх периферійних пристроїв.

Принцип роботи зовнішніх переривань в AVR

Для того щоб мікроконтролер дізнався про зовнішні події використовуються дискретні входи INT0 INT1 і т.д. Дискретні означає, що вони працюють з логічними рівнями: 0 і 1.
0 - це відсутність напруги на вході
1 — наявність на вході напруги, яка дорівнює напруги живлення мікроконтролера.

Зовнішні переривання можна поділити на два типи:

  • зовнішні переривання за рівнем
  • зовнішні переривання фронтом

Зовнішні переривання за рівнем

Спрацювання зовнішнього переривання може бути налаштоване на низький чи високий рівень логічного. Наприклад, якщо переривання налаштовано на низький логічний рівень, воно виникає коли на вході INT напруга дорівнює нулю. Якщо ж переривання налаштовано на високий рівень, воно виникає коли на вході логічна 1.
При роботі з перериваннями за рівнем треба пам'ятати, що доки на вході INT відповідний рівень, переривання буде постійно. Тобто. якщо виникло переривання, наприклад за низьким рівнем і програма його обробила, але якщо при виході з обробника переривання на вході залишається низький рівень, то переривання спрацює ще раз, і знову буде викликаний обробник переривання, і так буде продовжуватися до тих пір, поки на вході не з'явиться найвищий рівень. Щоб цього не відбувалося, потрібно в обробнику забороняти цей вид переривань, або переналаштовувати його на інший рівень.

Зовнішні переривання фронтом

Переривання по передньому фронту або, як іноді кажуть, наростання сигналу виникає коли відбувається зміна рівня сигналу на вході INT з 0 на 1. Переривання по задньому фронту (спаду сигналу), виникає при зміні рівня сигналу на вході INT з 1 на 0.
Також можна налаштувати переривання що він реагувало будь-яку зміну на вході INT тобто. воно виникатиме і по передньому і задньому фронту.

Налаштування зовнішніх переривань в AVR

Зовнішні переривання в avr atmega8 налаштовуються за допомогою біт ISCxx регістра MCUCR .

Залежність умови спрацьовування зовнішнього переривання INT0 від біт ISC0x регістра MCUCR в avr atmega8

Для зовнішнього переривання INT1 , налаштування проводитися так само, тільки використовуються біти ISC11 ISC10 .

прикладналаштування зовнішнього переривання для avr atmega8:

//Скидаємо всі біти ISCxx MCUCR & amp;= ~( (1 <& lt; ISC11) | (1 & lt;& lt; ISC10) | (1 & lt;& lt; ISC01) | (1 & lt;& lt; ISC00) ) MCUCR | = (1 & lt; & lt; ISC01) | (1 & lt; & lt; ISC00) ;

// скидаємо всі біти ISCxx MCUCR &= ~((1<

Дозвіл зовнішніх переривань в avr atmega

Для того щоб зовнішні переривання заробили їх треба дозволити, встановивши в 1 відповідні біти в регістрі GICR .

Біт INT0 відповідає за дозвіл/заборону зовнішнього переривання INT0 , а біт INT1 відповідно за зовні переривання INT1 .

Так само необхідно щоб був виставлений прапор глобального дозволу переривань.

Приклад коду, що дозволяє зовнішнє переривання INT0 для avr atmega8:

//Дозволяємо зовнішнє переривання INT0 GICR |= (1<

Приклад використання зовнішніх переривань у AVR atmega

Як приклад наведу програму лічильника імпульсів. Програма підраховує кількість імпульсів на вході INT0 і раз на секунду виводить результат підрахунку в uart.

#include #include #include #include //Змінна лічильник volatile unsigned long int0_cnt = 0; //Налаштування зовнішнього переривання INT0 void int0_init( void ) ( //налаштовуємо на спрацьовування INT0 на передньому фронті MCUCR | = (1 & lt; ISC01) | (1 & lt; & lt; ISC00) ; //Дозволяємо зовнішнє переривання INT0 GICR | = (1 & lt; & lt; INT0); ) //функція обробник зовнішнього переривання INT0 ISR( INT0_vect ) ( int0_cnt++; ) //налаштування UART void uart_init( void ) ( //Настроювання швидкості обміну UBRRH = 0; UBRRL = 3; //115200 при кварці 7.3728 МГц //8 біт даних, 1 стоп біт, без контролю парності UCSRC = (1 & lt; URSEL) | (1 & lt; & lt; UCSZ1) | (1 & lt; & lt; UCSZ0); //дозволити прийом та передачу даних UCSRB = (1 & lt; & lt; TXEN) | (1<<RXEN); ) //Передача байта по UART int uart_putc(char c, FILE * file) ( //Чекаємо закінчення передачі попереднього байта while ( (UCSRA & amp; (1 & lt; & lt; UDRE)) == 0); UDR = c; return 0; ) FILE uart_stream = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE ); int main( ) ( //Тимчасова змінна unsigned long tmp; stdout = & uart_stream; int0_init(); uart_init(); sei(); while (1 ) ( //на час копіювання значення лічильника забороняємо переривання cli(); tmp = int0_cnt; //дозволяємо переривання sei(); printf ( "int0_cnt = %lu \r \n ", tmp); //пауза 1 секунда _delay_ms(1000); ) return 0; )

#include #include #include #include //Змінна лічильник volatile unsigned long int0_cnt = 0; //налаштування зовнішнього переривання INT0 void int0_init(void) ( //налаштовуємо на спрацьовування INT0 по передньому фронту MCUCR |= (1<