Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 16.06.2025

Просмотров: 3588

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

команды, характеризующий ее суть, состоит, в большинстве случаев, из 3-х букв, а последние две буквы показывают, откуда и куда копируется (переписывается) число или с какими регистрами нужно произвести определяемое командой действие.

Например, команду ADDWF можно условно разделить на 2 части: корень ADD, который обозначает операцию сложения, и WF, где первая буква обозначает регистр W (аккумулятор), а вторая - регистр F, то есть регистр, к которому обращается команда.

Следовательно, из самого названия команды становится понятным, что складывается содержимое регистров W и F.

В качестве этого условного регистра F, используются регистры общего или специального назначения.

Например, если в "шапке" программы определено название какого-нибудь регистра общего назначения как ABCD, и по ходу исполнения программы, в него было записано какое-нибудь число, которое необходимо сложить с числом, находящимся в аккумуляторе (W), с сохранением результата сложения в том же регистре ABCD, то это будет выглядеть так:

addwf ABCD,1

При этом следует отметить, что в регистр W программист может переписать содержимое любого другого регистра, и по своей сути, такого рода операция есть операция сложения чисел, находящихся в двух регистрах (через регистр W), с выбором места сохранения ее результата.

Рассмотрим команду ADDLW:

ADD - операция сложения, L - признак того, что в ней участвует константа, W - признак того, что в ней участвует регистр - аккумулятор.

Например:

addlw k

Это означает то, что складывается содержимое регистра W и некая константа, заданная программистом.

Если она равна, например, числу 3, то это будет выглядеть так: addlw 3

Так как константа не является регистром, то место сохранения результата операции однозначно - регистр W.

Другой пример: операция копирования содержимого одного регистра в другой. movwf ABCD

Расшифровка: MOV - обозначение команды копирования.

Копирование данных производится из регистра W в регистр F (то есть, в регистр ABCD). Так как никакой логической операции при этом не совершается, то и вопроса о сохранении результата неосуществленной логической операции не возникает.

Просто происходит банальное копирование данных в указанный в команде регистр. Обращаю Ваше внимание на то, что в системе команд для ПИКов, при простом перемещении данных из одного регистра в другой (то есть при операции без логических действий), речь идет именно о копировании, без вырезания данных из регистра - отправителя.

Конечным результатом этой операции является числовое равенство содержимого обеих регистров.

Аналогично:

AND - операция побитного "И" содержимого двух регистров, CLR - сброс в ноль содержимого регистра,

COM - инверсия всех битов регистра,

DEC - декремент содержимого регистра (минус 1),

INC - инкремент содержимого регистра (плюс 1),

IOR - побитное "ИЛИ" содержимого двух регистров, NOP – "пустой" машинный цикл (ничего не происходит), RLF - циклический сдвиг содержимого регистра влево, RRF - циклический сдвиг содержимого регистра вправо, SUB - операция вычитания,

XOR - побитное "исключающее ИЛИ" содержимого двух регистров,

BTF - команды ветвления по значению выбранного в регистре бита, RET - возврат с загрузкой константы в W,

4 буквы в корне команды:

SWAP - поменять местами полубайты регистра,

CALL - переход по условию (с задействованием стека),

27


GOTO - переход без условия,

5 букв в корне команды:

SLEEP - уход в режим пониженного энергопотребления,

6 букв в корне команды:

RETURN - возврат из подпрограммы (кроме подпрограмм обработки прерываний), RETFIE - возврат из подпрограммы обработки прерываний.

1 буква в корне команды:

B - операции с битом. Имеются ввиду команды BCF и BSF.

Вторая буква в этих командах является признаком операций с битом:

-C - установить бит в 0,

-S - установить бит в 1,

-F - признак регистра.

Получается: сбросить (0) или установить (1) какой-то из битов регистра, к которому обращается команда.

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

На данном этапе обучения, от Вас требуется только общее понимание смысла действий, производимых командой и заучивание их названий.

В дебри лезть незачем, иначе навредите сами себе.

"Хозяином" этих команд Вы станете позднее - тогда, когда пойдет работа по составлению программ, а пока "вживайтесь" в команды ассемблера.

На первых порах, наибольшие трудности, обычно, вызывают команды ветвления. Сразу следует уяснить, что ветвления, то есть выбор какого-то одного из двух сценариев работы программы, могут быть результатом выполнения различных действий.

Байт – ориентированные команды ветвления: DECFSZ, INCFSZ.

Вподавляющем своем большинстве, эти команды обращаются к регистрам общего назначения.

Самый распространенный случай: внутри полного цикла программы, имеется еще один внутренний цикл, и рабочая точка программы должна "прокрутиться" по этому внутреннему циклу, например, 10 раз, чтобы после этого выйти на полный цикл программы.

Вкачестве счетчика такого рода "проходов" ("колец"), назначается какой-нибудь из регистров общего назначения.

Назовем его, например, XYZ.

Вначале полного цикла программы, в него записывается число "проходов", то есть, число 10. Предположим, что программа работает и ее рабочая точка вышла на 1-й внутренний цикл.

А в его конце стоит команда DECFSZ, в результате действия которой, содержимое регистра XYZ уменьшается на единицу и становится равным 9-ти.

Эта девятка сохраняется в том же регистре XYZ.

Так как это число не равно 0, то происходит переход на начало 2-го внутреннего цикла программы и все повторяется снова до тех пор, пока, после очередного вычитания единицы, в регистре XYZ не установится число 0.

Как только это произойдет, будет осуществлен переход не на начало следующего внутреннего цикла программы, как это было ранее (первый сценарий работы программы), а на второй сценарий работы программы, который, в общем виде, называется "программа исполняется далее".

По этому сценарию, в пределах дозволенного, могут осуществляться какие угодно действия (определяется замыслом программы).

Из этого примера видно, что происходит то, что называется ветвлением программы. Еще один пример.

К выводам порта В подключен 7-сегментный индикатор.

Полный цикл программы равен, например, 1 сек., а его сегменты высвечиваются в течение 0,1 сек., а остальное время погашены. Требуется увеличить это соотношение. Следовательно, необходимо "встроить" ("врезать") в тот участок программы, в котором индикатор активен, подпрограмму задержки, функция которой заключается в "закольцовке" рабочей точки программы внутри этой подпрограммы.

А как же иначе, ведь рабочая точка программы всегда должна находиться в движении? Вот и пусть она "мотает" заданное программистом количество "кругов" в подпрограмме задержки, ведь время-то идет...

Такие подпрограммы имеют в своей основе все те же команды DECFSZ (INCFSZ), только

28


безусловные переходы при этом гораздо "скромнее" - всего на несколько команд, а не на десятки, то есть, рабочая точка программы, на время задержки, "крутится" по относительно малому (с малым количеством команд) кольцу подпрограммы задержки.

Выглядит это так.

Подпрограмма задержки, в простейшем случае, начинается с команды DECFSZ (INCFSZ) и обращается к регистру общего назначения, в который, перед ее началом (в промежутке времени между моментом активации индикатора и до начала подпрограммы задержки), закладывается некое число (константа), которое и будет определять время задержки (количество "колец").

Предположим, что в регистр XYZ заложено число (константа) 250.

СтОит только рабочей точке программы войти в подпрограмму задержки, она не выйдет из нее до тех пор, пока задержка не будет полностью отработана.

Смысл этой "закольцовки" заключается в том, что при выполнении, например, команды DECFSZ и отсутствии нулевого результата операции декремента, переход, в конечном итоге, происходит на все ту же команду DECFSZ и все повторяется по новой, пока число 250 не уменьшится до нуля, а это требует времени.

Вот Вам и задержка.

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

Зная длительность машинного цикла, можно точно просчитать время задержки. Этот пример, конечно, простейший, так как для относительно больших задержек, при длительности машинного цикла = 1мкс (кварц 4 Мгц.), одного регистра не достаточно (необходимо несколько регистров с последовательным их декрементом).

С этим мы разберемся позднее.

Сейчас главное - прочувствовать "кольцевую природу" программ и представить себе, как в главном "кольце" (цикле) программы, образуются большие и маленькие "кольца", и как рабочая точка программы в них "входит, выходит, идет по прямой, заходит в другое кольцо" и т.д.

Примечание: все, сказанное выше, относится и к команде INCFSZ. Отличие - только в направлении счета (+1).

Оставшиеся две команды ветвления BTFSC и BTFSS ориентированы на операции с битами регистров.

При применении этих команд, никаких действий с байтами не производится. Критерием ветвления является значение выбранного бита (0 или 1).

Например, если на момент исполнения команды BTFSC, значение выбранного бита регистра XYZ (например, бита №2) равно 1, то в соответствии с логикой команды BTFSC, выполняется следующая команда, а если значение этого бита равно 0, то вместо следующей команды, исполняется "пустышка", в виде команды NOP (нет действия или операции. Задержка

на 1 м.ц.).

После этого "пустого" машинного цикла, выполняется следующая команда (вторая после

BTFSC).

Обращаю Ваше внимание на то, что в этом случае, команда NOP как бы "виртуальна" (формируется аппаратными средствами ПИКа), так как в тексте программы команды NOP нет, хотя, по факту, она и заменяет, в случае равенства 2-го бита нулю, следующую, после BTFSC , команду.

Получается, что в этом случае, команда присутствует в тексте программы, но не исполняется (вместо нее, исполняется "виртуальный" NOP).

Итоговый смысл:

-в случае равенства 2-го (в данном случае) бита единице, исполняется следующая, после команды BTFSC, команда,

-в случае равенства 2-го (в данном случае) бита нулю, происходит как бы "скачёк" через эту "следующую" команду (посредством исполнения, вместо нее, "виртуального" NOPа).

Естественно, что никакого "скачка" через команду не происходит, ведь "виртуальный" NOP исполняется, но впечатление "скачка" создается.

Кстати, это очень полезное впечатление, от которого не нужно отмахиваться, а нужно использовать в своей работе (очень удобно), не забывая при этом про "виртуальный NOP. Примечание: словосочетания "виртуальный NOP" Вы нигде не найдете, так как это моя

29


фантазия. Слово "виртуальный" означает, что то, на что указывает это слово, исполняется не программно, а аппаратно.

Ведь нужно же, "для порядка", кратко и емко "обозначить это явление"?

В соответствии со сказанным, время исполнения команды BTFSC, в зависимости от сценария ее исполнения, будет составлять либо 1, либо 2 машинных цикла.

Вот Вам и объяснение того, что Вы видите в 4-м столбце таблицы команд, в строке с командой BTFSC {1(2)}.

То же самое, с учетом специфики команд, относится и к остальным командам ветвления

(DECFSZ, INCFSZ, BTFSS).

А если, после команды BTFSC, исполняется команда безусловного перехода, как это и происходит во многих случаях?

Пример самого распространенного варианта: btfsc XYZ,2 goto Cycle

----------

1-й сценарий: если 2-й бит регистра XYZ равен 1, то происходит безусловный переход в подпрограмму, например, Cycle.

2-й сценарий: если 2-й бит регистра XYZ равен 0, то перехода в подпрограмму Cycle не происходит (вместо этого - "виртуальный NOP") и программа исполняется далее (дальнейшие команды программы обозначены ---- ----).

Еще один вариант:

btfsc XYZ,2 goto Cycle goto Mem

1-й сценарий: если 2-й бит регистра XYZ равен 1, то происходит безусловный переход в подпрограмму Cycle.

2-й сценарий: если 2-й бит регистра XYZ равен 0, то происходит безусловный переход в подпрограмму Mem. Команда goto Cycle игнорируется (вместо нее исполняется

"виртуальный NOP").

Еще один вариант:

btfsc XYZ,2 movwf PortB

----------

1-й сценарий: если 2-й бит регистра XYZ равен 1, то содержимое аккумулятора (W)

копируется в защелки порта В.

После этого копирования, программа исполняется далее.

2-й сценарий: если 2-й бит регистра XYZ равен 0, то копирования содержимого аккумулятора в защелки порта В не происходит (вместо этого - "виртуальный NOP"), и программа исполняется далее.

Впервых двух вариантах, используются переходы, а в последнем, не используются.

Влюбом из этих случаев, происходит ветвление, так как имеется два сценария работы. Все, что сказано выше, относится и к команде BTFSS.

Единственное различие в том, что критерий анализа меняется на противоположный (сценарии меняются местами).

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

Сначала нужно освоить ее, а потом переходить к изучению команды условного перехода

CALL.

Впринципе, при составлении программ, можно вообще не применять команду CALL, а пользоваться только командой GOTO как по своему прямому назначению, так и заменяя ей команду CALL.

Обе эти команды, "стратегически", осуществляют переход по одному и тому же принципу (типа "куда захочу, туда и перейду"), но есть "тактические" отличия.

Команда GOTO "гуляет сама по себе" (стек не задействован), а команда CALL - только в "связке" с командой возврата RETURN или RETLW.

30