Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
Скачать 3.49 Mb.
|
9999), то речь идет о 2- байтном регистре ( например , TimerM/TimerL ). Таким образом, в счетчик числа проходов, необходимо записать константу х. В этом случае, лишние LED ы ( LED4...7 ) и группы команд, которые работают сих содержимым, нужно убрать Должны остаться только регистры LED0, LED1, LED2, и те группы команд, которые "работают " сих содержимым Соответственно , в ПП преобразований , вплоть до ее концовки (до процедуры распределения полубайтов, нужно использовать только регистры LED0 и LED1 То есть, в этом случае, из текста программы, нужно "изъять " некоторые команды Для того чтобы стало понятно, какие именно команды нужно "изымать " или добавлять ( в случае работы с двоичными числами, отображаемыми более чем в 4- х байтах ), нужно поподробнее разобраться со стратегией работы ПП преобразований чисел ( Bin2_10 ). ПП Bin2_10 начинается с подготовительных операций Флаг переноса- заёма С опускается ( бит С регистра STATUS сбрасывается в 0), в счетчик проходов Count записывается константа, числовое значение которой равно общему количеству битов 4- байтного регистра TimerL/TimerM/TimerH/TimerHH (.32), и содержимое всех LED ов сбрасывается в 0. Подготовительные операции закончены Далее , начинается отработка ПП Loop16 В ее начале, происходит циклический сдвиг влево, на одну позицию (через бит С регистра STATUS ), содержимого 8- разрядного регистра (8 команда потом, содержимое счетчика количества проходов ( Count ) декрементируется ( decfsz Count,F , результат декремента сохраняется в нем же. Так как байт- ориентированная команда decfsz является командой ветвления, то возможны два сценария работы программы Предположим , что результат декремента равен 0 отмотаны " все 32 "витка "). В этом случае, начнется отработка группы команд поразрядного распределения содержимого регистров (обеих полубайтов, по младшим полубайтам регистров LED0...7 ( концовка ). Этой группе команд вполне можно было бы "присвоить статус " отдельной подпрограммы, но так как на 1- ю команду этой группы команд, переходов нетто формально, она входит в состав ПП Loop16 Если результат декремента содержимого регистра Count не равен 0, то осуществляется безусловный переход в ПП adjDEC В состав ПП adjDEC входят 4 группы команд, в каждой из которых осуществляется условный переход в ПП adjBCD Возврат происходит наследующую (из этих четырех) группу команд Каждая из этих групп команд работает со "своим " регистром (с нулевого по третий, то есть, соблюдается порядок старшинства (вначале ППbadjDECb, происходит "работа " с содержимым регистра, а в конце, с содержимым регистра. Предположим, что с содержимым регистра LED3 осуществлены необходимые действия и произошел возврат на команду Loop16 251 После исполнения этой команды, начнется " отмотка нового витка " внутреннего цикла ПП Bin2_10 (напоминаю, что таких "витков " 32 штуки. На каждом таком "витке ", происходит сдвиг содержимого 8- байтного регистра TimerL/TimerM/TimerH/TimerHH/LED0/LED1/LED2/LED3 на одну позицию (байт, по направлению от TimerL к LED3 То есть, 4- байтный регистр будет последовательно заполняться результатами числовых преобразований ПП adjDEC никаких числовых преобразований не осуществляет Она исполняет функцию "администратора ", то есть, определяет порядок обработки содержимого регистров LED0...3 Он следующий LED0, LED1, LED2, LED3 учтен порядок старшинства. В состав каждой из этих 4- х групп команд, входят две команды процедуры "разорванной ", косвенной адресации Слово "разорванной " означает то, что в ПП adjDEC , осуществляется только запись, в регистр FSR , адреса регистра, с содержимым которого будут производиться действия, асами эти действия производятся в другой подпрограмме ( в ПП adjBCD ). После исполнения команды LED... ( 0, 1, 2, 3 ), в регистр W , записывается адрес текущего LED а (вспомните про то, о чем говорилось ранее. После исполнения команды FSR , этот адрес, из регистра W, копируется в регистр FSR Далее , осуществляется условный переход в ПП adjBCD ( call adjBCD ). После того, как ПП adjBCD будет отработана, то есть, будет исполнена команда 0 , содержимое регистра W сбрасывается в 0 и происходит возврат на команду записи, в регистр W, адреса следующего LED а Проще говоря, начинается обработка содержимого следующего LED а И так будет происходить до тех пор, пока не будет обработано содержимое регистра LED3 После этого, осуществляется безусловный переход в ПП Loop16 , то есть, на новый "виток " внутреннего цикла ПП Bin2_10 А теперь обратим внимание на стек Ранее рассматривались случаи, когда в стек "закладывался " только один адрес возврата В данном случае, адрес возврата на 1- ю, после команды Bin2_10 , команду программы, будет "лежать " в стеке вплоть до окончания отработки ПП Bin2_10 , но только преимущественно (основную часть времени, не в вершине стека (в 1- й его строке, а во 2- й строке , так как после исполнения команд adjBCD , вершину стека поочередно будут занимать соответствующие адреса возвратов Таким образом, если на момент исполнения текущей команды, в стеке уже находится адрес ( адреса ) возврата , "заложенный" в него ранее, тов таблице стека ( всего в этой таблице 8 строк, он ( они ) сместится на одну позицию вниз, а в вершину стека запишется адрес возврата, соответствующий текущей ( последней ) команде call . После освобождения вершины стека, все "имеющиеся в наличии ", активные адреса возвратов, синхронно сместятся вверх на одну позицию ( строку ) , после чего, в вершине стека будет "лежать" адрес возврата, ранее "дислоцировавшийся" вой строке . Итак , после записи, в регистр FSR, адреса текущего LED а ( в ПП adjDEC ), происходит условный переход в ПП adjBCD ПП adjBCD является как бы "основной кухней " преобразования чисел Она обрабатывает результаты групповых, циклических сдвигов, находящиеся в регистрах LED0...3 В начале ПП adjBCD , с помощью команды 3 , в регистр W, записывается константа 03h ( 00000011 ), которая далее, с помощью команды суммируется с содержимым текущего LED а Этой командой завершается, ранее начатая, процедура косвенной адресации Обращение к регистру INDF происходит не непосредственно (с "пропиской " его названия, а через его адрес (косвенно. В данном случае, происходит обращение к числу 0, то есть, к адресу регистра В области оперативной памяти, по адресу 00h, "дислоцируется " регистр INDF Следовательно , обращение происходит именно к нему 252 А если происходит обращение к регистру INDF (прямое или косвенное, без разницы, то по определению, происходит обращение к содержимому того регистра, адрес которого записан в регистре FSR В регистре FSR, "лежит " адрес текущего LED а , следовательно, произойдет суммирование содержимого текущего LED а c ранее записанной, в регистр W, константой 03h. Результат суммирования сохранится в регистре W Затем , результат суммирования, из регистра W, копируется в регистр оперативной памяти, после чего, состояние бита анализируется ( btfsc Mem,3 ). Если в этом бите 1, то исполняется команда 0 , которая также относится к "разряду хитрых ". В ней также (см выше) происходит обращение не к названию регистра, а к адресу регистра (00h). То есть, происходит обращение к содержимому текущего LED а Таким образом, команда копирует содержимое регистра W, в текущий LED А так как в регистре W находится тоже самое, что ив регистре, то фактически, происходит копирование содержимого регистра, в текущий LED Если бит регистра Mem равен 0, то процедура суммирования повторится снова, но только в регистр W будет записана не константа 03h, а константа 30h ( 00110000 ), и будет произведен анализ состояния не бита, а бита № 7 регистра Mem Напоминаю , что если в тексте программы указано число без атрибутов систем исчисления ( а в данном случае так оно и есть ), то речь идет о 16- ричной системе исчисления, а не о десятичной Вместо movlw 30 , можно написать или Результат будет одними тем же Если бит регистра Mem будет равен 0, то произойдет возврат в ПП adjDEC , после чего произойдет смена текущего LED а , следующий переход в ПП adjBCD , ее отработка, возврат в ПП adjDEC и т д До тех пор, пока не будет закончена обработка содержимого регистра LED3 Далее , исполняется команда Loop16 , после чего начинается " отмотка " следующего витка / кольца ПП Bin2_10 И так 32 раза После того, как содержимое счетчика количества проходов Count станет равным 0, начнется отработка группы команд поразрядного распределения содержимого регистров по младшим полубайтам регистров (" концовочная " процедура. На момент начала ее отработки, в 8- ми полубайтах регистров, в порядке старшинства, будут "лежать " результаты преобразований, в виде восьми 4- битных , двоично- десятичных чисел Направление возрастания старшинства от младшего полубайта регистра LED0, и далее по- порядку Распределение начинается со старшего полубайта регистра (он "уходит " в младший полубайт регистра LED7 В его старший полубайт записывается 0) и далее , по- порядку (в сторону уменьшения разрядности) и аналогично Примечание : если начать это распределение с младшего полубайта регистра LED0 (" с другого конца "), то содержимое некоторых полубайтов будет утеряно То есть, в данном случае (8 знакомест, в наличии должно быть 8 групп команд распределения Причем , при распределении каждого полубайта, должна гарантированно обеспечиваться запись нуля в старший полубайт регистра- получателя (почему См выше. Эти 8 групп команд, по сути, выполняют одну и ту же "работу ", но разными способами - 4 группы команд, работающие с младшими полубайтами регистров, - одним способом, и 4 группы команд, работающие со старшими полубайтами регистров, - другим Это обусловлено положением полубайта в байте Если полубайт старший, то необходимо задействовать команду смены местами старшего и младшего полубайтов ( swapf ), а если полубайт младший, то этого не требуется Рассмотрим работу первых двух групп команд (остальные пары групп команд работают аналогично. Распределение начинается со старшего полубайта регистра 253 С помощью команды старший и младший полубайты регистра LED3 меняются местами Результат этой операции сохраняется в регистре W С помощью команды выполняется логическая операция побитного И содержимого регистра W и константы 0Fh (.15 или. То есть, фактически, выполняется побитное И содержимого регистра (с учетом смены местами его полубайтов) и константы 0Fh, с сохранением результата этой операции в регистре W В результате этого, старший полубайт "встает на место " младшего, ив старшем полубайте устанавливается 0. По логике операции И , результат побитного И с нулем, всегда есть ноль, а результат побитного И с единицей, повторяет состояние второго "участника " этой логической операции Таким образом ( movwf LED7 ), в младший полубайт регистра, записывается старший полубайт регистра, ив старшем полубайте регистра LED7 устанавливается 0. Следующая группа команд работает с младшим полубайтом регистра LED3 В этом случае, менять местами полубайты регистра ненужно Первая команда ( movfw LED3 ) копирует содержимое регистра LED3 в регистр W Примечание : movfw - не опечатка Такой команды в распечатке команд Вы не найдете (есть, но тем не менее, команда movfw работает (можете добавить в список ). Команды название регистра ) и movf название регистра ) ,W производят одно и то же действие Работа второй команды ( andlw 0Fh ) описана выше Работа третьей команды ( movwf LED6 ) описана выше, разница только в том , что содержимое регистра W копируется не в регистр LED7 , а в регистр LED6 Таким образом ( movwf LED6 ), в младший полубайт регистра, записывается младший полубайт регистра, ив старшем полубайте регистра LED6 устанавливается 0. Остальные 3 пары групп команд распределения полубайтов работают аналогично При распределении полубайтов в регистры LED0...3 , содержимое их ранее распределенных полубайтов во внимание не берется (они уже распределены, и с ними можно проводить описанные выше операции, не опасаясь "уничтожить нужный " полубайт На конечной стадии распределения, младший полубайт регистра LED0 копируется в него же В чем смысл Ведь содержимое младшего полубайта регистра, казалось бы, можно вообще "не трогать " (ничего с ним не делать. Нов этом случае, старший полубайт регистра LED0 не будет установлен в ноль Поэтому , последняя группа команд распределения должна быть исполнена в полном объеме После ее исполнения, рабочая точка программы переходит на команду возврата ( ПП Bin2_10 отработана ), и далее , осуществляется возврат наследующую, после команды Bin2_10 , команду ПП START После отработки команд ПП START , начинается исполнение ПП динамической индикации ( данные для ее работы подготовлены, итак далее До следующего " влёта " рабочей точки программы в ПП Bin2_10 " На фоне " сказанного, ПП adjBCD является некой "темной лошадкой ". В том смысле, что формально (без "привязки " ко всему остальному, ее работа понятна, нов комплексе совсем остальным, получается довольно- таки объемная и трудно воспринимаемая "круговерть " чисел В это можно "въехать ", нона данной стадии обучения, какого- то большого, практического смысла в этом нет И выбора у меня тоже нет, так как в дальнейшем , без подпрограммы преобразования двоичных чисел в двоично - десятичные, никак не обойтись Эта подпрограмма работает четко, ив ее "эксплуатации ", никаких сложностей не будет Нужно только научиться "трансформировать " ее текст под то, что Вам нужно (а вот в этом есть "могучий ", практический смысл. Как это делается Пример "Переоборудуем " ПП Bin2_10 под линейку, состоящую из 4- х знакомест В этом случае, необходимо произвести следующие действия В "шапке" программы 254 Убрать регистры, а регистры LED0...3 оставить . Убрать регистры TimerH и TimerHH , а регистры TimerL и TimerM оставить . Таким образом, группа ПП формирования двоичного числа должна быть рассчитана на формирование 2- байтного , двоичного числа, которое должно "лежать" в регистрах TimerL и TimerM . В рабочей части программы 3. Заменить константу хна константу 8 х 2= .16 4. Убрать 4 команды LED4...7 . Убрать 4 команды TimerH,F, rlf TimerHH,F, rlf LED2,F, rlf LED3,F . 6. В группе команд распределения полубайтов, убрать первые 4 (сверху) группы команд распределения. 7. В ПП adjDEC , убрать ю и ю (сверху) группы команд ( movlw, movwf, call ). Таким же образом, можно "переоборудовать " ПП Bin2_10 под любое количество знакомест Если учесть, что такого же рода "переоборудование " можно произвести и в ПП динамической индикации (об этом говорилось ранее, тов комплексе, получается именно то, что нужно А теперь сведем то, с чем мы разбирались по частям, к единому целому Получается некая универсальная заготовка" с названием (находится в папке " Тексты программ. Она выглядит так ;******************************************************************************** |