Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Листинг 13.2:
push var_1 ;переменная var_1 в программе помещается в стек
push var_2 ;переменная var_2 в программе помещается в стек
rcall procedure ;вызывается процедура
pop var_2 ;после нее результат извлекается из стека
pop var_1 ;второй результат извлекается из стека
…
procedure: ;в процедуре извлекается локальная
pop var_loc2 ;переменная var_loc2 со значением var_2
pop var_loc1 ;и переменная var_loc1 со значением var_1
… ;расчеты, расчеты…
push var_loc1 ;результат — в стек
push var_loc2 ;результат — в стек
ret ;возврат из процедуры
В качестве переменных var_1и var_2возможны любые регистры, при этом действия внутри процедуры всегда будут совершаться с заданными регистрами var_loc. Обратите внимание, что когда таких переменных несколько, важно соблюдать правильный порядок их помещения в стек и извлечения оттуда, согласно принципу «первым вошел — последним вышел» (в программах на языках высокого уровня за порядком переменных в стеке следят специальные форматы вызова функций типа stdcallи подобные).
Аналогично происходит обработка прерываний, только специальной команды, как вы знаете, там нет, вызов производится обычным переходом rjmpили jmp, но поскольку он осуществляется с определенного адреса (там, где стоит вектор прерывания), то контроллер делает то же самое: сохраняет в стеке адрес командного счетчика, на котором выполнение основной программы было грубо нарушено, начинает выполнять прерывание и ожидает команды возврата, здесь она записывается как reti(return interrupt).
Еще одна важнейшая группа команд ветвления программы — команды перехода по состоянию отдельного бита в указанном регистре ( sbrs, sbicи т. п.). Они очень удобны для организации процедур, аналогичных оператору выбора CASE в языках высокого уровня, но, к сожалению, обладают непривычной логикой: «пропустить следующую команду, если условие выполняется» и для новичка могут показаться слишком заумными. В качестве примера приведу довольно сложную по логике работы, но характерную для микроконтроллерной техники процедуру, в которой задача формулируется так: при наступлении некоторого условия мигать попеременно зеленым и красным светодиодами (СД).
Предположим, что условие мигания задается состоянием бита 3 в некоем рабочем регистре, который назовем регистром флагов — Flag(не путать с «официальным» регистром флагов SREG, о котором далее). Если бит 3 регистра Flagравен единице (установлен), надо мигать, если нет (сброшен) — оба СД погашены.
Красный СД подсоединен к выходу порта В номер 5, а зеленый — к выходу порта С номер 7 (разумеется, это могут быть любые другие выводы других портов).
Текущее состояние СД задается битом 4 в том же регистре флагов Flag.
Алгоритм работы такой программы на языке Pascal (листинг 13.3) описывается типичным вложенным оператором выбора.
Листинг 13.3
case <���бит 3 per. Flag> of
0: <���погасить оба СД>
1: case <���бит 4 per. Flag> of
1: <���устанавливаем Port С, вых. 7>; //горим зеленым <���сбрасываем
Port В, вых. 5>;//гасим красный
<���сбрасываем бит 4 Flag>;{ следующий раз горим красным }
0: устанавливаем Port В, вых. 5>;//горим красным
<���сбрасываем Port С, вых. 7>;//гасим зеленый
<���устанавливаем бит 4 Flag>;// следующий раз горим зеленым
end;
end;
Разобравшийся в алгоритме читатель уже, несомненно, задает вопрос — а как обеспечить цикличность? Для этого подобный код включают в обработчик события по таймеру с секундным, например, интервалом. Причем, что характерно, и в микроконтроллере, и в операционной системе Windows это происходит абсолютно одинаково: инициализируется системный таймер (в МК для этого надо разрешить соответствующее прерывание), задается интервал его срабатывания (в Windows это одна команда, в МК их несколько больше) и — вперед! Но с таймерами мы будем разбираться далее по ходу дела, а пока посмотрим, как тот же алгоритм реализовывается в МК (листинг 13.4).
Листинг 13.4
sbrs Flag,3 ;если флаг 3 стоит, будем мигать
rjmp dark ;иначе будем гасить
sbrs Flag,4 ;если флаг 4 стоит, будем гореть зеленым
rjmp set4 ;иначе красным
cbr Flag, 0Ь00010000 ;следующий раз горим красным
cbi PortB,5 ;гасим зеленый
sbi PortC,7 ;горим зеленым
rjmp continue ;все готово
set4: ;если флаг 4 не стоит, будем гореть красным
sbr Flag, 0Ь00010000 ;следующий раз горим зеленым
cbi PortC,7 ;гасим красный
sbi PortB,5 ;горим красным
rjmp continue ;все готово
dark:
cbi PortC,7 ;гасим оба
cbi PortB,5
continue:
…
С используемыми здесь командами установки и сброса отдельных бит ( sbi, sbrи т. п.) мы плотнее познакомимся чуть позже, а сейчас задержимся на ключевой команде всего алгоритма — sbrs, что расшифровывается, как Skip if Bit in Register is Set («пропустить, если бит в регистре установлен»). Имеется в виду, что по состоянию бита (если он установлен в единицу) пропустить нужно следующую команду. В качестве последней обычно также выступает одна из команд ветвления, как здесь, но далеко не всегда. Удобно, например, организовывать выход из прерывания или подпрограммы по какому-то условию, если поставить следующей после sbrsкоманду retiили, соответственно, ret(примеры мы еще встретим).
Противоположная по логике процедура записывается, как sbrc(Skip if Bit in Register is Cleared — «пропустить, если бит в регистре очищен», т. е. равен нулю). Наконец, есть еще пара аналогичных команд — sbisи sbic, которые применяются, когда нужно отследить состояние бита в регистре ввода/вывода (I/O), а не в регистре общего назначения. Все эти команды мы будем активно применять в дальнейшем.
Наконец, в самой обширной группе команд ветвления имена начинаются с букв Ьг(от слова branch — «ветка»). Это команды условного перехода, которые считаются одними из самых главных в любой системе программирования, т. к. позволяют организовывать циклы — базовое понятие, программистских наук. По смыслу все эти команды сводятся к банальному if… then(«если… то»). Мы будем пользоваться лишь частью этих команд, потому что они во многом взаимозаменяемы, и здесь подробно разберем только одну пару команд. Смысл остальных вам будет понятен по ходу дела.
Это наиболее часто употребляемая пара brne(Branch if Not Equal, «перейти, если не равно») и breq(Branch if Equal, «перейти, если равно»). Уже из смысла этих команд понятно, как они пишутся: после команды следует метка, на которую нужно перейти. Вопрос только такой: откуда здесь берется собственно условие? Для этого все команды ветвления обязательно употребляют в паре с одной из команд, устанавливающих флаг нуля Z в регистре флагов SREG. Обычно (и это наиболее наглядно) для этой цели служит команда ср (от compare— «сравнить»), которая сравнивает регистры, или cpi(«сравнить с непосредственным значением»). Например, вот так будет вы глядеть простейший цикл, в котором переменная temp последовательно принимает значения от 1 до 10:
Читать дальшеИнтервал:
Закладка: