Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Как вы увидите в главе 13, внутри процедуры incom возникновение прерываний нам не страшно. Так что неприятность случится только, если прерывание возникнет между командами cpi и breq, т. е. если оно появится за время выполнения команды cpi (и то, напомним, только когда в прерывании есть команда, модифицирующая значение — в данном случае — флага нуля z). Процедура in_com для приема байта по UART при скорости 9600 бит/с может длиться порядка одной миллисекунды (и весь цикл займет примерно столько же), тогда, при типовом времени выполнения команды cpi порядка долей микросекунды, вероятность неблагоприятного стечения обстоятельств составит всего несколько случаев на 10 000 поданных команд. Если предположить, что внешний компьютер непрерывно "бомбардирует" МК командами, то вероятность сбоев достаточно велика, если же подача команды осуществляется пользователем вручную раз в сутки (в месяц, в год), то, скорее всего, на такую возможность можно не обращать внимания: гораздо удобнее выстроить "правильный" протокол взаимодействия, подразумевающий контроль обмена командами (о чем мы будем говорить в главе 13) — это все равно потребуется, потому что сбои могут происходить и по иным причинам. Но в очень критичных к сбоям системах лучше застраховать себя от всех возможных ситуаций.

И еще заметим "до кучи", что команды, заведомо не модифицирующие значение соответствующего флага в регистре SREG, можно "вклинивать" между командами, его изменяющими, и командами условного перехода, его проверяющими. Так, между проверкой "на ноль" и ветвлением по этому условию (например, парой dec ... brne) можно вставить сколько угодно команд пересылки данных или, к примеру, извлечения/сохранения регистра в стеке. Сам переход по командам Ьгхх также не модифицирует содержимого SREG, И возможны конструкции, когда ставятся подряд две и более команд перехода по одному условию.

Команды проверки-пропуска
Это чрезвычайно распространенная группа команд, которые осуществляют пропуск следующей по порядку команды в зависимости от состояния отдельного бита в РОН или РВВ. Основные из них— пары команд sbrs/sbrc (для РОН) и sbis/sbic (для РВВ). Они очень удобны для организации процедур, аналогичных оператору выбора CASE в языках высокого уровня, но, к сожалению, обладают непривычной логикой: "пропустить следующую команду, если условие выполняется", и потому для новичка могут показаться слишком заумными. В качестве примера приведу довольно сложную по логике работы, но характерную для микроконтроллерной техники процедуру, в которой задача формулируется так: при наступлении некоторого условия мигать попеременно зеленым и красным светодиодами (СД).

Введем несколько предположений.
3 Условие мигания задается состоянием бита 3 в некоем рабочем регистре, который, как и в предыдущей главе, назовем регистром флагов' — Flag. Если бит 3 регистра Flag равен единице (установлен) — надо мигать, если нет (сброшен) — оба СД погашены.

Не путать с "официальным" регистром флагов SREG, описанным ранее.
□ Красный СД подсоединен к выходу порта D номер 7, а зеленый — к выходу порта С номер 7 (разумеется, это могут быть любые другие выводы других портов).
□ Текущее состояние СД задается битом 4 в том же регистре флагов Flag. Алгоритм работы такой программы реализуется типичным вложенным оператором выбора, листинг 6.5 содержит код программы на языке высокого уровня.

Листинг 6.5
case <бит 3 per. Flag> of О: <погасить оба СД> 1: case <бит 4 per. Flag> of 1: устанавливаем PortC, вых. 7>; //зажечь зеленый СД <сбрасываем PortD, вых. 7>;
//зажечь красный СД <сбрасываем бит 4 Flag>; {следующий раз горим красным} 0: устанавливаем PortD, вых. 7>; //погасить красный СД <сбрасываем PortC, вых. 7>;
//погасить зеленый СД устанавливаем бит 4 Flag>; //следующий раз горим зеленым end;
end;
Разобравшийся в алгоритме читатель уже, несомненно, задает вопрос — а как обеспечить цикличность? Для этого подобный код включают в обработчик события по таймеру с секундным, например, интервалом. Причем, что харак-. терно, и в микроконтроллере, и в операционной системе Windows это происходит абсолютно одинаково: инициализируется системный таймер, задается интервал его срабатывания (в Windows это одна команда, в МК их несколько больше) и— вперед! Но с таймерами мы будем еще разбираться дополнительно, а пока посмотрим, как тот же алгоритм реализовывается в AVR (листинг 6.6).

sbrs Flag,3 ;если флаг 3 стоит, будем мигать
rjmp dark ;иначе будем гасить
sbrs- Flag,4 ;если флаг 4 стоит, будем гореть зеленым
rjmp set4 ;иначе красным
cbr Flag, ОЬОООЮООО ; следующий раз горим красным
cbi PortD,7 ;гасим зеленый
sbi PortC, 7 ;горим зеленым
rjmp continue ;все готово
set4:
sbr
;если флаг 4 не стоит, будем гореть красным" Flag, ОЬОООЮООО ; следующий раз горим зеленым
cbi sbi
rjmp
dark:
PortC,7 ;гасим красный PortD,7 ;горим красным continue ;все готово
cbi cbi
PortC,7 ;гасим оба PortD,7
:ontinue:

С используемыми здесь командами установки и сброса отдельных битов (sbi, sbr и т. п.) мы подробнее познакомимся чуть позже, а здесь задержимся на ключевой команде всего алгоритма— sbrs, что расшифровывается, как Skip if Bit in Register is Set— "пропустить, если бит в регистре установлен". Повторим, что "пропустить" нужно следующую команду, в зависимости от состояния бита (в данном случае — если он установлен в 1). В качестве последней обычно выступает одна из команд ветвления, как здесь, но далеко не всегда— так удобно, например, организовывать выход из прерывания или подпрограммы по какому-то условию, если поставить следующей после sbrs команду reti или, соответственно, ret (пример см. в листинге 5.13 предыдущей главы в программе с задержкой по таймеру).



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru