Програмування переривань Bascom-8051

Система переривань процесора 8051 забезпечує ефективну обробку зовнішніх подій і процесів з тимчасовим поділом За допомогою програм переривань вирішується широке коло завдань, в основі яких лежить паралельна відпрацювання кількох процесів, і звязок дій і подій з відмітками реального часу Bascom дозволяє повністю використовувати можливості системи переривань як стандартних, так і більш старших моделей При програмуванні переривань можливо кілька підходів:

а) створення максимально швидко працюючих програм обробки переривань, що використовують мінімальні ресурси памяті Розробка таких програм не відрізняється від традиційного програмування на Асемблері Асемблерні програми переривання необхідно застосовувати тоді, коли час реакції на переривання дуже критично і потрібно повністю контролювати використання ресурсів памяті Складність створення асемблерних програм обробки переривання (та й всіх інших вставляються асемблерних програм) полягає у необхідності підглядати за операторами Bascom (за допомогою дисассемблер), щоб зрозуміти і правильно організувати передачу даних Бейсік або зчитування даних з змінних Бейсика

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

в) комбінування достоїнств асемблера і Бейсика Це самий практичний і рекомендований підхід – максимально використовувати Бейсік, вставляючи асемблерні команди тільки в самі «гарячі» ділянки програми туди, де компілятор дає явно неоптимальний код або використовує ресурси памяті неприпустимим чином

Правила опису програм переривання не менше актуальні і для Бейсика:

а) гранична стислість – буде менше помилок

б) здійснювати якомога менше дій – переміщати дані між змінними (обєктами) і встановлювати прапори для виклику програм обробки цих даних, управляти зовнішніми пристроями, таймерами і портами (зчитувати або завантажувати, зупиняти або запускати) і, нарешті, обслужити пристрій викликало переривання (скинути прапор виклику, перезавантажити таймер)

в) використовувати мінімальну кількість змінних (регістрів)

г) бути уважним і не забувати про стек, в якому вже зберігається перервана завдання, і в який буде завантажена поточна задача, якщо трапиться переривання більш високого рівня Переповнення стека або порушення послідовності завантаження-вилучення даних призводить роботу програми до фатального результату Компілятор і навіть відладчик помилки такого роду не виявляє

д) в програмі переривання, описаної операторами Bascom, повинна бути тільки одна точка виходу, тому що компілятор тільки в одному місці (і тільки один раз) поставить команду RETI І ця точка виходу повинна позначатися тільки оператором RETURN Якщо точок виходу кілька, то потрібно замість операторів RETURN

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

перший оператор RETURN, який він зустріне, після мітки, що позначає вектор переривання

е) допускається використання в програмі переривань блоку регістрів 3 Щоб правильно його використовувати, потрібно зберегти значення регістра PSW і встановити біти RS0 і RS1 (Psw = & h18) Якщо в програмі використовуються оператори множення чисел у форматі з плаваючою точкою, то необхідно зберігати і регістр з адресою 18H (R0 третього банку)

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

Бейсике Рекомендації по можливості застосування операторів Bascom і допустимості скоєних дій

виглядаючих наступним чином:

а) можна без обмеження застосовувати оператори перезапису даних (без перетворення форматів), встановлювати і змінювати значення змінних, здійснювати перетворення і обчислення в регістрах, використовуються в поточному перериванні Допускається робити зміна стан SFR, таймерів і портів, якщо цього вимагає алгоритм програми переривання і передбачено в перерваної програмі

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

в) зовсім небажано використовувати операції з символьними змінними Внутрішні змінні Bascom, що використовуються для цього, розташовується поза області автоматичного збереження в стеку Ще більшою мірі це відноситься до сімейства операторів виведення даних (PRINT, LCD) Вони використовують ще більше не зберігаються регістрів і периферійні пристрої Критерієм можливості застосування таких дій є тільки однозначне поділ у часі (навіщо тоді це робити у перериванні) або використання у всій програмі тільки однієї операції, що працює з символьними змінними Взагалі, складності безпомилкового використання в перериваннях і перериваються програмах процедур обробки і виведення символьних рядків настільки значні, що вирішувати їх краще радикально – просто не застосовувати в програмах обробки переривання

г) заборонено застосовувати оператори очікування подій, наприклад, з сімейств WAIT і INPUT

Події, що відбуваються, навпаки, повинні викликати переривання

д) неможливо правильне одночасне використання в переривається програмі і програмах переривання операторів RESTORE і READ

е) дуже складно передбачити наслідки використання в перериваннях складних програмних конструкцій (OPEN . CLOSE, DO . LOOP, WHILE . WEND, SELECT . CASE) Тому краще їх не застосовувати

ж) з дуже великою ймовірністю будуть правильно працювати оператори перевірки умов (IF . THEN),

оператори циклів (FOR . NEXT), оператори INCR, DECR стосовно бітовим і байтовим змінним Допустимо застосування цих операцій і з двох-і чотирьохбайтового змінними, хоча при цьому падає швидкість обробки, виходить більш громіздкий код і потрібно більш ретельна перевірка правильності

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

тим більше, символьні

з) виконання операторів GET і PUT, що використовують послідовний програмний інтерфейс, не повинно взагалі перериватися, інакше відбудеться порушення синхронізації

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

програми модулі програм переривання

Розглянемо приклади оформлення програм переривань Спочатку будуть представлені фрагменти ініціалізації переривань різних типів Потім будуть дані приклади програм обробки переривань

Програмування зовнішніх переривань INT0 (або INT1) за рівнем або спаду:

On Int0 Int_0_int виконувати зовнішнє переривання INT0 (INT1 – аналогічно)

Rem On Int0 Int0_int Nosave те ж саме без збереження і восстановл регістрів Rem Set Tcon0 додати, щоб виконувати переривання по спаду (Tcon0 = 1) Enable Int0 дозволити переривання INT0 (Ie0 = 1)

Enable Interrupts вирішити всі переривання (Ie7 = 1) ——————————-

‘Підпрограма обробки зовнішнього переривання

Int_0_int:

Reset P17 : Buf = P0 : Set P17 : Set New_data

Return

‘——————————-

Програмування переривання таймера 0 (або таймера 1):

Config Timer0 = Timer, Gate = Internal, Mode = 1 режим 16-разрний

On Timer0 Timer_0_int виконувати переривання від Таймера0 (Timer1 – аналогічно) Counter = 0 щоб переривання настало через 65 мс

Enable Timer0 дозволити переривання INT0 (Ie1 = 1) Enable Interrupts вирішити всі переривання (Ie7 = 1)

‘——————————-

‘Підпрограма обробки переривання таймера

Timer_0_int:

Counter0 = & hD8F0 перезавантажити на інтервал 10 мс (при кварці 12 МГц) Incr Rtime: Set B_10_mc повідомити, що пройшло 10 мс

Return

‘——————————-

Показаний більш докладний приклад програмування переривання послідовного каналу У його

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

Ri Alias ​​Scon0 біт RI Ti Alias ​​Scon1 біт TI

Dim R_ch As Byte прийнятий символ Dim R_cch As Byte покажчик буфера Dim R_lin As String * 6 введений рядок

‘——–

‘TIMER2 в режимі 16-біт таймера з внутр тактується для синхронізації UART

$ Crystal = 12000000 при кварці 12 МГц

$ Baud = 9600 швидкість 96 кБ

Config Timer2 = Timer , Gate = Internal , Mode = 2

Timer2 = & HFFA5: Start Timer2 встановимо швидкість

On Serial Ser_int Nosave виконувати переривання остан каналу

Enable Serial дозволити переривання остан каналу

Enable Interrupts дозволити переривання

‘Обробка переривання послідовного інтерфейсу

Ser_int:

$asm

Intsr:

Ints1: Ints2:

Intse: Ints3:

Ints4:

Ints5: Intst:

$end Asm

Jbc {Ri}, Intsr шукаємо джерело переривання

Jbc {Ti}, Intst заодно і скидаємо біт викликав переривання

Reti

Push Psw переривання приймача

Push Acc

Mov {R_ch}, Sbuf зберегти прийнятий символ

Mov A , {R_ch}

Cjne A , #&amph0d , Ints3

Setb {N_dat} 0Dh – прийнята рядок

Mov A, {R_cch} покажчик буфера

Xch A, R0 зберегти R0

Mov @ R0, # & h00 записати в буфер кінець рядка

Xch A, R0 відновити R0

Mov {R_cch}, # {R_lin} переініціалізіровать покажчик буфера

Pop Acc Pop Psw Reti

Cjne A , #&amph0a , Ints4

Sjmp Intse 0Ah – ігнорувати

Mov A, {R_cch} покажчик буфера

Xch A , R0

Mov @ R0, {R_ch} все інше записувати в буфер

Xch A , R0

Mov A , #{R_lin+6}

Cjne A , {R_cch} , Ints5

Sjmp Intse

Inc {R_cch} якщо буфер незаполнен – ​​змінимо покажчик

Sjmp Intse

Setb {B_entx} переривання передавача

Return цей ​​оператор, компілятор замінить командою Reti

‘——————————-

Програмування таймера 2 для отримання такого ж результату, як вище в прикладі

програмування таймера 0:

Config Timer2 = Timer , Gate = Internal , Mode = 0

On Timer2 Timer_2_int виконувати переривання від таймера 2

Load Timer2, 10000 кожні 10 мс (завантажує 65536-10000) Enable Interrupts дозволити використовувані переривання Enable Timer2 дозволити переривання таймера 2

‘——————————- Підпрограма обробки переривання таймера 2

Timer_2_int:

Reset T2con7 скинути біт, що викликав переривання

Incr Rtime: Set B_10_mc повідомити, що пройшло 10 мс

Return

‘——————————-

Програмування нестандартного переривання, наприклад, від лічильника PCA процесора 87C51FA

Компілятор не підтримує ініціалізацію нестандартних переривань, тому необхідно завантажити безпосередньо регістри конфігурації, які повинні бути описані у відповідному файлі:

‘Вибрати файл 8051fadat

On Pca Pca_int виконувати переривання від PCA

Cmod = & h01 дозволити переривання від PCA

Enable Interrupts дозволити використовувані переривання

Ch = & hD8: Cl = & hF0 завантажити на інтервал 10 мс (при кварці 12 МГц) Ccon6 = 1 дозволити рахунок

‘——————————-

‘Підпрограма обробки переривання від PCA Pca_int:

Reset Ccon7 скинути біт, що викликав переривання Ch = & hD8: Cl = & hF0 знову завантажити на інтервал 10 мс Incr Rtime: Set B_10_mc повідомити, що пройшло 10 мс

Return

‘——————————-

Для підвищення ефективності генерованого коду деякі операції в програмах переривань

рекомендується замінювати асемблерними командами (можна і не тільки в програмах переривань) Нижче в таблиці представлені такі приклади

Запис у Bascom

Асемблерний еквівалент

If Bn = 1 Then якщо 1

Reset Bn: Goto Mf скинути і перейти

End If

Jbc {Bn} , Mf

If Rn = 0 Then Goto Mf нуль – Перейти

End If

Mov A , {Rn} Jz Mf

Rb = High (Rw) Rw-двухбайтовая перем

Mov {Rb} , {Rw + 1}

Відсутня простий доступ до частин мультибайтних

змінних, наприклад, R_Long

Не завжди зручний варіант, що дозволяє тільки

зчитувати:

Tmpw = Loww(R_Long) : Acc = Hi(Tmpw)

Mov {R_long + 2}, # & hf0 запис

Mov A, {R_long + 1} зчитувати

Джерело: МЛКуліш, ДОВІДНИК З ПРОГРАМУВАННЯ BASCOM-8051, Краснодар 2001

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*