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

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

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

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

Добавлен: 16.06.2025

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

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

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

ветвлений. Кто ее "осилит", тот существенно "продвинется вперед".

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

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

Нужно просто некоторое время "повариться в этом соку".

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

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

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

Так что, всему свое время. Дойдет дело и до вычитания.

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

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

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

Лучше всего, специально под это дело, создать, например, из программы Multi.asm, программу-заготовку, в "шапке" которой "оптом прописать" наиболее востребованные регистры специального назначения, определить место сохранения результатов операций и присвоить названия наиболее востребованным битам регистров специального назначения.

Например, C equ 0, DC equ 1, Z equ 2, RP0 equ 5, GIE equ 7 и т.д.

Даже если часть из этого использоваться не будет, то ничего страшного. Это не является ошибкой.

Примечание: если воспользоваться соответствующей директивой, которая "оптом прописывает всё, что шевелится", можно обойтись без этого. Эта директива комфортна, но на мой взгляд, изначально вредна. Так как расхолаживает. Это вовсе не говорит о том, что ее вообще не нужно применять. Нужно. Но позднее. Когда произойдет "вживание/вживление в шапку".

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

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

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

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

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

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

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

А как же иначе?

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

Очччень дорогой, любимый и приносящий много радости.

"Родами" займемся позднее, а пока продолжим "курс молодого бойца".

207


Циклический сдвиг

Циклическим сдвигом "рулят" две команды: RLF (циклический сдвиг влево) и RRF (циклический сдвиг вправо).

Обе эти команды байт-ориентированные.

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

Вней, в строках команд RLF и RRF, Вы найдете блок-схему циклического сдвига влево и вправо.

Механизм сдвига - кольцевой.

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

Вданном случае, работа флага С сводится к работе простейшего, однобитного (не путайте с однобайтным) регистра, в который, после исполнении команды циклического сдвига, копируется значение старшего или младшего бита (в зависимости от направления сдвига) байта регистра, к которому обращается команда RLF или RRF.

А можно и "зайти с другого конца", как бы введя бит С в состав регистра, к которому обращается команда RLF или RRF, с присвоением ему "статуса" бита № 8.

Вэтом случае, речь идет о составном (комплексном) 9-битном регистре, с раздельным отображением байта (биты с №№ 0 … 7) и бита с № 8, замкнутом в кольцо обратной связи. Числовое значение байта можно проконтролировать, просмотрев содержимое регистра, к которому обращается команда RLF или RRF, а состояние бита с № 8 можно проконтролировать, просмотрев содержимое флага С.

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

Если до начала этой процедуры, не применялись команды, воздействующие на флаг С (ADDWF, ADDLW, SUBWF, SUBLW), то о сбросе флага С можно не заботиться: он будет сброшен по умолчанию.

Если эти команды применялись, то на момент начала процедуры циклического сдвига, нужно проконтролировать состояние бита флага С, и если в нем установлена 1, то нужно сбросить бит С в 0 командой bcf Status,0(C).

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

Для того чтобы понять, как происходит процедура циклического сдвига, достаточно провести аналогию с работой реверсивного, сдвигового регистра с предустановкой типа ....ИР.. .

Хотя микросхем 9-разрядных регистров ИР и нет, но, предположим, что такой регистр существует.

Сейчас я Вам "обрисую" аналог процедуры циклического сдвига.

"Закольцовываем" регистр, соединяя выход 9-го разряда со счетным входом 1-го разряда. 8-битное исполнительное устройство, назовем его А, подключаем к выходам с 1-го по 8-й, а 1-битное исполнительное устройство, назовем его В, подключаем к 9-му выходу регистра.

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

Записываем все это в регистр.

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

Это соответствует применению команды RLF.

На тактовый вход регистра подается один тактовый импульс. Это соответствует исполнению команды RLF.

Происходит сдвиг, предварительно записанной информации, в сторону старших разрядов (влево).

Из-за наличия "закольцовки", бит с № 8 "занимает место" бита с № 0, а бит с № 7 "занимает место" бита с № 8 (остальные сдвигаются соответственно).

На управляющие входы исполнительных устройств А и В подаются уровни, сдвинутые на такт влево.

Таких тактовых импульсов (команд RLF) можно сформировать (исполнить) несколько, и

208


соответственно, содержимое 9-разрядного регистра сдвинется влево на такое же количество разрядов.

На 10-м сдвиге, в регистре установится исходное число. А теперь поближе к ПИКам.

В одном регистре общего назначения, можно отобразить только 8 битов этого "виртуального" (условно), 9-битного числа (начиная с младшего), а 9-й (старший) бит находится как бы "за кулисами".

А теперь давайте проанализируем "механику этого действа" и какую практическую выгоду можно из этого извлечь.

"Прогоним" по полному циклу сдвигов влево, например, число .09 (00001001).

00001001

C=0

9

Начальная установка.

00010010

C=0

9х2= 18

х2

00100100

C=0

18х2=36

х4

01001000

C=0

36х2=72

х8

10010000

C=0

72х2=144

х16

00100000

C=1

144х2=288-256=32

Выход на 2-й "виток" цикла счета.

01000001

C=0 32х2+1{перенос, из бита С, в младший разряд байта}=65

10000010

C=0

65х2=130

00000100

C=1 130х2=260-256=4.

Выход на 2-й "виток" цикла счета.

.................................

00001001

С=0

2+1{перенос, из

бита С, в младший разряд байта}=9

.................................

Первое, что бросается в глаза, это движение единиц.

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

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

После анализа результатов циклического сдвига влево числа .09 (или других чисел), можно сделать следующие выводы:

-Циклический сдвиг влево, на 1 такт (позицию), связан с операцией умножения

"предшествующего" ("лежащего" в регистре до этого сдвига) числа на 2.

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

-Если в бите С находится 1, то результат следующего циклического сдвига,

сучетом умножения на 2, увеличивается на 1.

Вслучае использования однобайтного регистра, "закольцованного", через бит С, на самого себя (рассмотренный выше случай), последовательно исполняя несколько команд RLF, можно умножить исходное число на 2, 4, 8 … , но только при условии отсутствия переносов (см. приведенный выше пример).

Например, после умножения на 2 (один сдвиг) чисел до .127 включительно, в регистре общего назначения, к которому обращается команда RLF, будет "лежать" число, точно отображающее результат выполнения арифметической операции умножения на 2, а бит флага С всегда будет нулевым (старший бит байта всегда будет равен нулю).

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

Вэтом случае, для получения истинного результата умножения на 2, необходимо к числу,

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

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

Вопрос: "Как"?

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

209


(1 сдвиг – х2, 2 сдвига – х4, 3 сдвига – х8 и т.д.), причем, эта кратность может быть достаточно большой (зависит от количества задействованных регистров).

После окончания сдвигов, результат кратного умножения на 2 считывается из N-байтного регистра.

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

Поэтому, нужен комплексный подход.

А как, например, умножить на 7 или на 10 и т.д.?

Вэтом случае, используется несколько последовательных умножений на 2 (сдвигов влево), с учетом остатка.

Для этого нужно составить разложение числа (множителя). Арифметика этого разложения простая.

Например, приемлемые варианты для 7: 7=2х2+1+1+1 или 7=2х2х2-1.

Впервом случае, посредством двух сдвигов влево, множимое умножается на 4.

Далее, к этому результату, 3 раза, последовательно прибавляется множимое. Во втором случае, посредством трех сдвигов влево, множимое умножается на 8. Далее, из этого результата, один раз вычитается множимое.

Какой вариант выбрать?

Лучше выбрать второй вариант, так как в этом случае, группа команд умножения будет содержать меньшее количество команд, чем в случае использования первого варианта. При умножении на 10 могут быть такие варианты: 2х2х2+1+1, 2х2х2х2-1-1-1-1-1-1, (2х2+1)+(2х2+1), 2х2+1+1+1+1+1+1 и т.д.

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

Вот его-то, в качестве примера, давайте и реализуем (простейшая ПП умножения).

Файл программы умножения на 10, с формализованными комментариями, называется

Rlf.asm (находится в папке "Тексты программ").

Она выглядит так:

;********************************************************************************

;ПРИМЕР ИСПОЛЬЗОВАНИЯ ФЛАГА "C" В ОПЕРАЦИИ УМНОЖЕНИЯ НА 10

;********************************************************************************

; Rlf.asm

Подпрограмма умножения 8-битных чисел на 10

;********************************************************************************

;Множимое: числа от .00 до .255, которые закладываются в регистр RegL на момент

;начала подпрограммы перемножения на 10.

;Множитель: 10 (2*2*2+1+1).

;Произведение: результат трех умножений на 2 и двух суммирований. На момент

;окончания ПП умножения на 10, записывается в двухбайтный регистр RegL/RegH

;(двухбайтное двоичное число).

;********************************************************************************

;

"ШАПКА ПРОГРАММЫ"

;********************************************************************************

;.............................................................

;.............................................................

;================================================================================

; Определение положения регистров специального назначения.

;================================================================================

Status equ 03h ; Регистр Status.

;.............................................................

;.............................................................

;================================================================================

; Определение названия и положения регистров общего назначения.

;================================================================================

RegL

equ

0Ch

; Регистр

множимого.

;

Он же -

регистр младшего байта.

RegH

equ

0Eh

;

Регистр

старшего байта.

;.............................................................

;.............................................................

210