Главная страница

Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.


Скачать 3.49 Mb.
НазваниеСистема команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
АнкорСамоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf
Дата30.01.2017
Размер3.49 Mb.
Формат файлаpdf
Имя файлаСамоучитель по программированию PIC контроллеров для начинающих .pdf
ТипПрограмма
#1195
КатегорияПромышленность. Энергетика
страница42 из 57
1   ...   38   39   40   41   42   43   44   45   ...   57
"
Тексты программ. Она выглядит так
;
ПРИМЕР
ИСПОЛЬЗОВАНИЯ
ФЛАГА
"C"
В
ОПЕРАЦИИ
УМНОЖЕНИЯ
НА
10
;********************************************************************************
; Подпрограмма умножения 8-
битных чисел на 10
;********************************************************************************
;================================================================================
; Подпрограмма умножения на 10
однобайтных двоичных чисел (.00 ... .255)
;================================================================================
; Подготовительные операции.
;--------------------------------------------------------------------------------
bcf Status,C
; Предварительный сброс флага
С
.
movf RegL,W
; Копирование содержимого регистра RegL
; в регистр W.
clrf RegH
; Предварительный сброс содержимого ; регистра RegH.
;--------------------------------------------------------------------------------
; Три последовательных умножения на 2 (умножение на 8).
;--------------------------------------------------------------------------------
rlf RegL,F
; Умножение на 2 числа, записанного в ; регистре RegL, с сохранением результата

213
; в нем же.
btfsc Status,C
;
Флаг
С
поднят или опущен ?

rlf RegH,F
; Если поднят, то циклический сдвиг влево ; содержимого регистра RegH с переносом в
его
; младший разряд 1 избита флага
С
, с ; сохранением результата в
нем же (в RegH).

;--------------------------------------------------------------------------------
rlf RegL,F
; Если опущена также после исполнения ; предшествующей команды, то умножение на 2
; числа, записанного в
регистре
RegL, с ; сохранением результата в
нем же.

btfsc Status,C
;
Флаг
С
поднят или опущен ?

rlf RegH,F
; Если поднят, то циклический сдвиг влево ; содержимого регистра RegH, с переносом в ; его младший разряд 1 избита флага
С
, с ; сохранением результата в
нем же (в RegH).

;--------------------------------------------------------------------------------
rlf RegL,F
; Если опущена также после исполнения ; предшествующей команды, то умножение на 2
; числа, записанного в
регистре
RegL, с ; сохранением результата в
нем же.

btfsc Status,C
;
Флаг
С
поднят или опущен ?

rlf RegH,F
; Если поднят, то циклический сдвиг влево ; содержимого регистра RegH, с переносом в ; его младший разряд 1 избита флага
С
, с ; сохранением результата в
нем же (в RegH).

; Если опущена также после исполнения ; предшествующей команды, то программа ; исполняется далее (переход к
суммированиям
)
;--------------------------------------------------------------------------------
; 2 последовательных суммирования сохраненного в
регистре
W множимого к результату умножения множимого на 8.
;--------------------------------------------------------------------------------
addwf RegL,F
; Сложить результат умножения на 8 и множимое ; (сохраненное в
регистре
W), с сохранением ; результата в
регистре
RegL.
btfsc Status,C
;
Флаг
С
поднят или опущен

incf RegH,F
; Если флаг
С
поднят
, то инкремент ; содержимого регистра RegH, с сохранением ; результата в
нем же.

addwf RegL,F
; Если флаг
С
опущен
(а также после ; исполнения предшествующей команды, то ; сложить результат предшествующего ; суммирования и
множимое
, с сохранением ; результата в
регистре
RegL.
btfsc Status,C
;
Флаг
С
поднят или опущен

incf RegH,F
; Если флаг
С
поднят
, то инкремент ; содержимого регистра RegH, с сохранением ; результата в
нем же.

;--------------------------------------------------------------------------------
........................; Если флаг
С
опущен
(а также после ........................; исполнения предшествующей команды, то ; программа исполняется далее.
......................................
......................................
;********************************************************************************
end
; Конец программы
.
В
свое время, когда я
разбирался с
умножением
, мне нужно было выбрать или найти готовую
ПП
умножения
, или составить ее самому
Я
выбрал последнее
Так "родилось сие творение ".
И
дело даже не в
том
, что наиболее вероятным результатом подобного рода работы является "изобретение колеса ", а
в том что после нее, наступает сильнейшее "просветление ", и
приобретается ценный опыт
В
конечном итоге, такой "въедливый " и
достаточно трудоемкий (на первых порах) стиль

214 разборок с
непонятностями ", оказывается гораздо эффективнее, чем достаточно "мутный и
ограниченный " стиль работы, связанный с
поиском чего- то готового
При этом, частенько, программист не вдается в
детали того, что он находит
По этой причине, велика вероятность возникновения затруднительных ситуаций
Вплоть до "тупиков ". Намой взгляд, критерием успешности является что- то типа этого "Зачем искать готовую, нужную программу
/
подпрограмму
? Проще, быстрее и
качественнее составить ее самому" Итак, предположим, что нужно составить подпрограмму умножения
Наиболее сложный "участок уже пройден ". Простейший принцип умножения сформулирован
Ну ив чем дело Как говорится, "впереди с песней "! Конструируем подпрограмму умножения однобайтного двоичного числа на 10
. Определяемся с
регистрами общего назначения
Так как множимое является числом, отображаемым одним байтом (.00 ... .255), то такое множимое может быть записано в
один регистр общего назначения
Так как множимое может принять любое значение из диапазона чисел от .00 дотов результате циклических сдвигов, может происходить событие переноса
Таким образом, максимальное значение произведения не может превысить числах То есть, для отображения такого числа, одного регистра общего назначения мало и
необходимо назначить еще один регистр общего назначения
И
в самом деле, двухбайтный регистр способен отобразить число от 0 дохи число .2550 попадает в
этот числовой диапазон
Так как регистров общего назначения стало 2, то нужно определиться с
порядком старшинства
Под младший байт произведения (он же - байт множимого, "прописываем " регистр общего назначения с
названием
, например,
RegL
В
этом байте будет осуществляться циклический сдвиг влево, ион же будет младшим байтом произведения
Под старший байт произведения, "прописываем " регистр общего назначения с
названием
, например,
RegH
В
этот байт, входе последовательных процедур умножения на 2, будут осуществляться переносы
Теперь нужно определиться с
начальными условиями
Для этого нужно ответить на вопрос "Какие числа должны быть записаны в
регистры
RegL, ив бит флага
С
на момент начала исполнения первого, циклического сдвига" Ответ в
регистр
RegL
будет записываться число множимого
Байт регистра
RegH
нужно сбросить в 0 (
clrf RegH
).
В
противном случае, это равносильно наличию переносов, которых не было, что неприемлемо (увеличенное, по сравнению с
истинным
, значение произведения. Бит флага
С
нужно сбросить в 0 (
bcf Status,C
).
В
противном случае, результат умножения будет неверен Посмотрите в
текст программы
В
"подготовительных операциях ", Вы увидите обе этих команды
В
"шапке " программы, Вы увидите, что регистры, RegH

, а
также и
регистр
Status,
"
введены в
эксплуатацию " (прописаны "). Исходя из сформулированных выше условий,
ПП
умножения должна содержать не только группы команд умножения на 2, но и
группы команд суммирования, причем, одним из слагаемых обязательно должно быть множимое, и
операции сложения должны исполняться после завершения операции умножения на 8 (3- х
операций умножения на 2). Следовательно, в "подготовительных операциях " нужно сохранить множимое в
каком
- то регистре
Под это дело, можно "прописать " еще один (третий) регистр общего назначения, а
можно и
скопировать множимое в
регистр
W
, так как он, при исполнении процедур умножения на 2, не задействуется
Поэтому
, необходимости в
увеличении количества задействованных регистров общего назначения, нет
Вполне можно обойтись и
двумя
Следовательно
, с
целью дальнейшего использования множимого в
группах команд

215 суммирования, в "подготовительных операциях ", с
помощью команды нужно сохранить множимое в
регистре
W
Итак
, группа команд "подготовительных операций " сформирована
Порядок их расположения, в
этой группе, не имеет значения
Можно "перетасовать их, как карты ". Это не отразится на результате работы подпрограммы, так как все 3 команды "развязаны " относительно друг друга
Теперь можно заняться "конструированием " группы команд умножения на 2. Возникает вопрос "Какие именно команды должны входить в
группу команд умножения на 2 ив каком порядке, в
пределах этой группы, они должны располагаться" Исходя из сказанного ранее, однозначным является то, что первой должна следовать команда циклического сдвига влево RegL,F

, а
второй
, команда опроса бита флага
С
(
btfsc Status,C
), а
также и
то
, что перенос, в
случае его наличия, должен осуществляться в
младший разряд старшего байта (в регистр. Что дальше Каким образом должно происходить "взаимодействие " младшего и
старшего байтов при переносах На момент начала первого циклического сдвига влево, в
регистре
RegH
установлен
0, ив дальнейшем, от переноса к
переносу
, значения чисел, "лежащих " в
регистре
RegH
, должны только увеличиваться
Вопрос
:
"По какому закону" Могут быть следующие варианты суммирование, инкремент, циклический сдвиг влево
Суммирование отпадает, так как в
этом случае, задача, в
конечном итоге, сводится к "привязке " к
нескольким значениям констант, практически реализовать которую очень затруднительно
Инкремент
, на первый взгляд, для операции суммирования, приемлем, нов этом случае, результат умножения будет отличаться от истинного
Чтобы проверить правильность этого высказывания, давайте немного "погоняем нули с
единицами на бумаге ". Умножим, например, число .194 (
11000010
) на 8 (2
х
2
х
2), применив, для переносов в
старший байт, команды инкремента 11000010
; множимое, в бите
С
- ноль.
388
00000001 10000100
; вбит С "пришла" 1 из старшего бита младшего байта, следовательно, инкремент старшего байта.
521
00000010 00001001
; избита С "ушла" 1 в младший бит младшего байта, вбит С "пришла" 1 из старшего бита младшего байта, следовательно, инкремент старшего байта.
531
00000010 00010011
; избита С "ушла" 1 в младший бит младшего байта, вбит С "пришел" 0 из старшего бита младшего байта, следовательно, инкремента старшего байта нет.
В
идеале
, должен получиться результат ха получилось .531.
Вывод
:
при организации умножения посредством последовательных, "многоступенчатых " процедур умножения на 2, операции инкремента, для организации переносов в
старший байт, применять нельзя
Проанализировав результат (нужно .1552, а
получилось
.531), можно прийти к
выводу
, что при формировании нескольких переносов, наращивание значений чисел, формируемых в
регистре
RegH
, должно происходить значительно бОльшими "темпами ", чем в
случае применения операций инкремента
Исходя из этого, на "роль палочки - выручалочки претендует " все та же операция циклического сдвига влево, только применяемая по отношению к
содержимому старшего байта
И
в самом деле, она эквивалентна операции умножения на 2, что обеспечивает более высокие "темпы прироста ", чем при применении операции инкремента
Таким образом и "родилась " группа команд умножения на 2, которые можно последовательно
("
цепочкой ") соединять между собой
Посмотрите в
текст программы
Вы видите "цепочку " из трех групп команд умножения на 2 (умножение на 8). Может возникнуть вопрос "Как два байта делят между собой один бит флага
С
, ведь они оба работают с
ним
?" Атаки работают - по очереди

216 Чтобы это было наглядно, давайте умножим на 8 все тоже число .194 (
11000010
), только с
использованием
, для переносов в
старший байт, не команды, а
команды
RLF
194
00000000 11000010
; множимое, в бите
С
- ноль.
388
00000001 10000100
; сдвиг в
младшем байте 0 избита С "уходит" в младший бит младшего байта, сдвигая все биты влево,

1 старшего бита младшего байта "приходит" вбит С. сдвиг в
старшем байте 1 избита С "уходит" в младший бит старшего байта, сдвигая все биты влево,

0 старшего бита старшего байта "приходит" вбит С.
776
00000011 00001000
; сдвиг в
младшем байте 0 избита С "уходит" в младший бит младшего байта, сдвигая все биты влево,

1 старшего бита младшего байта "приходит" вбит С. сдвиг в
старшем байте 1 избита С "уходит" в младший бит старшего байта, сдвигая все биты влево,

0 старшего бита старшего байта "приходит" вбит С.
1552
00000110 00010000
; сдвиг в
младшем байте 0 избита С "уходит" в младший бит младшего байта, сдвигая все биты влево,

0 старшего бита младшего байта "приходит" вбит С. сдвиг в
старшем байте 0 избита С "уходит" в младший бит старшего байта, сдвигая все биты влево,

0 старшего бита старшего байта "приходит" вбит С. Вывод получен верный результат умножения числа .194 на .8, равный .1552. Если анализировать изменения, происходящие с 16- битным числом (2 байта в
комплексе
), тов его пределах, происходят все те же циклические сдвиги влево, что свидетельствует о
том
, что посредством "цепочки " групп команд умножения на 2, удалось "привязать " младший байт к
старшему таким образом, что конечный результат умножения в
точности будет равен 2 в
степени
N (где N - число групп команд умножения на 2). Проще говоря, если представить себе некий "барьер " между старшим битом младшего байта и
младшим битом старшего байта, препятствующий получению истинного результата умножения на 8, тов случае применения, упомянутой выше, "цепочки " групп команд умножения на 2, этот "барьер разрушается ".
В
результате
, циклические сдвиги влево происходят в "пределах " 16- ти битов (2- х
байтов
). То есть, два 8- битных регистра "полноценно " объединились в
один
16- битный регистр
Вот
Вам и
достаточно немудреная суть работы всей "цепочки " (это относится и
к "цепочке " групп команд, и
к "цепочке " рассуждений. Для того чтобы закрыть тему умножения на 2 в
степени
N, остается только выяснить, как происходит взаимодействие групп команд умножения на 2 между собой
Посмотрите в
текст программы
При опросе бита флага
С
,
применяется бит- ориентированная команда ветвления
btfsc
Если флаг
С
поднят
, то рабочая точка программы переходит на команду RegH,F

, а
после ее исполнения, на первую команду следующей группы команд умножения на 2 (
rlf RegL,F
). Это первый сценарий
Если флаг
С
опущен
, то рабочая точка программы "перескакивает " команду вспоминайте про "виртуальный "
NOP
) и
устанавливается на первой команде следующей группы команд умножения на 2 (
rlf RegL,F
). Это - второй сценарий
Разница между этими двумя сценариями очень простая в
первом сценарии, команда исполняется, а
во втором, не исполняется (вместо нее исполняется "виртуальный "
NOP
).
В
зависимости от величины множителя и
выбранного способа его разложения, количество групп команд умножения на 2 может быть различным
Например
, если требуется 2 группы команд умножения на 2, то из текста программы нужно убрать одну группу команд умножения на 2, а
если требуется 4, 5 или более, тов текст программы нужно добавить одну, две или более группы команд умножения на 2 соответственно
После "отработки " команд умножения на 8, рабочая точка программы устанавливается на первую команду первой группы команд суммирования результата умножения на 8 и
множимого
Вот здесь- то содержимое регистра (множимое) и
становится востребованным

217 Вовремя исполнения групп команд умножения на 2, регистр
W
не задействовался
, и
поэтому
, на момент начала исполнения групп команд суммирования, в
нем находится, записанное в
него ранее, значение множимого (в данном случае, .194). Работу этих групп команд я
объяснял ранее, так что повторяться не буду
Происходит следующее
В
аккумуляторе
(
W
) предварительно записано множимое .194 (
11000010
).
1552
00000110 00010000
; результат умножения на 8.
1746
1   ...   38   39   40   41   42   43   44   45   ...   57


написать администратору сайта