Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
Скачать 3.49 Mb.
|
C и DC , все команды сброса флагов можно смело убрать Вопрос : "Так что же, в конце концов, делать- то, убирать или не убирать "? Ответ : если информация, изложенная выше, Вам предельно ясна и понятна , и Вы имеете хотя бы небольшой опыт составления и отладки программ, то команды предварительных сбросов флагов можно не применять, а если у Вас с этим проблемы, то отказываться от этих сбросов не стОит По причине того, что в последнем случае, процесс отладки программ (в части касающейся отладки подпрограмм, в которых происходят опросы состояний флагов 1- й группы ) становится более наглядным Пример Предварительного сброса флага С нет В результате исполнения предшествующих команд программы, на момент исполнения команды, бит флага С установился в 1. Допустим, суммируем числа .100 и .200. Значит, после исполнения команды, бит флага С должен установиться в 1. Нов нем итак "выставлена " 1. В итоге , после исполнения команды, состояние бита флага С не изменится ( подтверждение ранее установленного состояния. Работа программы не нарушится, нов симуляторе, Вы не увидите изменения состояния бита флага С , что для начинающих, которые недостаточно хорошо ориентируются во " флаговых делах ", совсем не комфортно "На этой почве ", могут возникнуть сомнения, на устранение которых будут потрачены силы и нервы При наличии такого рода затруднений, например, при суммировании, целесообразно предварительно установить бит флага С в ноль ( bcf Status,0 ) так, как это сделано в группе проверочных команд, после чего можно будет с комфортом наблюдать за поднятием флага в окнах RAM или SFR Если нужно проконтролировать случаи сбросов флага, то перед исполнением соответствующей команды, можно либо вообще ничего не "врезать " (если "на влёте ", флаг поднят, либо (если "на влёте ", флаг опущен) предварительно поднять флаг С командой bsf Status,0 (по принципу типа "хуже от этого не будет и изменения увижу "). Подобного рода "манипуляции " есть элемент удобства отслеживания работы программы Можно даже сказать, что "уловка ". Может быть, опытные программисты и посчитают такое внимание к контрольным ( второстепенным ) операциям излишним, ноя так не считаю По той причине, что опытные программисты это знают, а начинающие не знают Именно осмысление подобного рода "деталей " и дает то, что называется профессиональной уверенностью Для Вашего удобства, сведу результаты в таблицу : Таблица состояний битов Z и C . - нулевой результат бит = 1, - ненулевой результат бит = 0, - перенос есть бит С = 1, 195 - переноса нет бит С = 0, - заём есть бит = 0 (заем имеет инверсное значение. - зама нет бит = 1 (заем имеет инверсное значение. Перед тем, как работать с флагом DC , внесу некоторую ясность в вопрос о том , почему арифметические операции сложения и вычитания (в пределах одного байта) выполняются в ПИКах так быстро Или этот вопрос можно сформулировать так "Почему флаги С и DC так быстро "реагируют " на результаты исполнения арифметических операций" Все познается в сравнении и поэтому приведу пример "доисторического " 4- хбитного арифметического устройства на двоичном счетчике с предустановкой 555 ИЕ 7 (полный цикл счета - 16 чисел. Например, нужно сложить числа .02 и .10. Код числа .02 подается на входы предустановки и записывается в триггеры счетчика После этого, на счетный вход счетчика подается 10 тактовых импульсов Счет начинается от числа .02 и прекращается на числе .12. Это - пример арифметического устройства последовательного типа, которое работает "долго и нудно ". Ив самом деле, ждать результата 10 тактов - "радость небольшая ", а если этот "динозавр ", например, многокаскадный и речь идет о больших числах Такие вычисления могут понравиться только любителям перекуров Для того чтобы произвести эти вычисления всего за время одного такта, в микроконтроллерах используются так называемые 8- разрядные полные сумматоры Кто этим интересуется информации о них полным- полно в технической литературе широкого пользования Почему именно "сумматор " - понятно, так как он осуществляет операцию суммирования А как быть с операцией вычитания, ведь сумматор может только складывать Дело в том , что применяя, при выполнении операции вычитания, специальные приемы ( преобразования чисел, можно свести операцию вычитания к операции сложения В этом случае, операция вычитания является специфической разновидностью операции сложения, и с использованием полного сумматора, можно реализовать обе эти операции, что и имеет место быть Как конкретно это происходит, программисту знать вовсе необязательно, но если кто интересуется, то литературы на этот счет много- разрядный полный, универсальный сумматор работает в стандартном , параллельном, весовом (обычном) коде и имеет 2 группы входов, по 8 разрядов каждая, на которые "подаются " слагаемые числа, 8 выходов, на которые выводится результат суммирования и один выход переноса - заёма Для "запуска механизма " суммирования, в этом случае, никаких дополнительных сигналов управления ненужно, так как, образно выражаясь, полный сумматор суммирует, "не спрашивая разрешения ". Какие числа "выставлены " на входах, такие он тут же и суммирует Просто необходимо, в нужный момент, их "выставить ", и сразу же после этого (буквально после паузы в несколько десятков наносекунд, можно считывать результат (он будет зафиксирован в течение всего интервала времени фиксации слагаемых чисел. То есть, арифметические операции можно совершать очень быстро Таким образом, состояния бита флага С ( DC ) есть состояния выхода переноса - зама такого универсального ( задействуется и при сложении, и при вычитании, 8- разрядного полного сумматора Программист может только произвести опрос (программными средствами) состояний выхода переноса- зама такого полного сумматора (что и есть опрос состояний флагов С / DC ) и при необходимости, по результатам этого опроса, направить рабочую точку программы в один из двух сценариев Разрядность полного сумматора программист нарастить не может Он производит операции только в пределах одного байта После завершения операции, байт результата должен быть своевременно скопирован в регистр общего назначения, а иначе , в результате исполнения следующей операции, он будет "потерян " (за что кровь пролита "?). Продолжу тему флагов 196 Пытаю " флаг DC " Орудия пытки " такие же, как и при "пытке " флага С , только контролировать нужно ненулевой бит регистра, а первый его бит В тексте программы Multi, замените проверочную группу команд для флага С на проверочную группу команд для флага DC Специфика работы с флагом DC такова , что лучше сначала прочитать пояснения, а потом начать с ним работать Байт состоит из х полубайтов побита в каждом Они разделяются на младший и старший полубайты Младший полубайт - тот, в состав которого входит нулевой бит байта Так как в каждом полубайте побита, то младший полубайт способен отобразить 16 чисел ( от .00 до .15). Можно провести аналогию между байтом, в случае работы с флагом С , и младшим полубайтом, в случае работы с флагом DC Всё один к одному Разница только в том , что в первом случае, переносы или замы происходят в случаях "выхода " результата арифметической операции, за пределы числового диапазона байта (от .00 до .255), а во втором случае, они происходят в случаях "выхода " результата арифметической операции, за пределы числового диапазона полубайта ( от .00 до .15). При работе с флагом DC , перенос осуществляется в младший разряд старшего полубайта, а не в дополнительно задействованный регистр общего назначения, как в случае наращивания разрядности при работе с флагом С . Если флаг DC работает с младшим полубайтом, то можно сделать следующий вывод : флаги С и DC работают в комплексе . Давайте посмотрим, как это будет выглядеть практически "Привяжемся " к операции суммирования Давайте что- нибудь посчитаем с использованием все той же группы проверочных команд для случая суммирования (см выше. Можете убрать из нее команду по той причине, что при работе этой группы команд в составе программы, перед исполнением команды Y , биты С и DC сброшены ( флаги С и DC опущены ) и эта команда ( bcf Status,0 ) просто ненужна (это как раз то, о чем говорилось выше. Оставшиеся 2 команды "вставьте " в текст программы на свое "проверочное место " так, как это делалось ранее. На место условных чисел X и Y, поставьте нули (начало анализа. Походу работы, можно производить и одновременную смену констант, но для того чтобы не запутаться, изначально, выгоднее зафиксировать одну из этих констант зафиксировать (.00). Например, X , а константу Y постепенно увеличивать, начиная с числа .00. Основное внимание нужно направить на нулевой и первый биты регистра STATUS Откройте окна RAM или SFR Кому какое удобнее А можно и оба Откройте также окно, "заложив " в него регистр в нем Вы будете видеть результат суммирования. Не забывайте, после каждой смены значения константы, производить ассемблирование Напоминаю : используемая нами команда ADDLW воздействует на флаги, C, DC (см распечатку команд. Встаньте " на команду Это означает, что последней была выполнена команда Посмотрите на содержимое регистра STATUS В нем - число 18h ( 00011000 ). Разбираемся биты флагов (3- й бит ) и (4- й бит ) установлены в 1. Причина после ассемблирования (что эквивалентно включению питания, ПИК сбрасывает сторожевой таймер, то есть, автоматически исполняется команда (см распечатку команд. Почему при сбросе 3- й и 4- й биты устанавливаются в 1, а не в 0? Обратите внимание на дефис перед названием этих флагов он означает инверсию Таким образом, флаги -PD и -TO опущены (установлены в 1). Далее, на эти флаги можно не обращать внимания Флаги С и DC также опущены (установлены в 0). Производим суммирование двух нулей, последовательно выполняя команды и 197 addlw После этого, содержимое регистра STATUS изменится сна. Все правильно, 0+0=0. Флаг нулевого результата (2- й бит ) поднялся В команде addlw , меняем .00 на .01. Ассемблируем Сбрасываем программу на начало В пошаговом режиме доходим до команды и исполняем ее Смотрим на содержимое регистра STATUS В нем опять число 18h ( 00011000 ). ??? Вывод : так как результат суммирования неравен, флаг нулевого результата Z сбросился Переносов нет, так как значение суммы не выходит "заграницы (см выше) рабочих зон ". Точно такая же "картина " будет наблюдаться, если Вы будете, в качестве числа, использовать любое число до .15 включительно При этом, значение числа суммы не превысит .15 и переполнения младшего полубайта не будет Суммируем .00 и .16. Сумма равна .16. Это число большее, чем способен отобразить младший полубайт и казалось бы, флаг DC должен подняться. Смотрим на содержимое регистра STATUS В нем 18h ( 00011000 ). Почему флаг DC не поднялся Посмотрите на младший полубайт числа .16. Он равен .00 ( 0000 ), а 0+0=0. То есть, "выхода заграницы" младшего полубайта нет, и флаг DC , по определению, подняться не должен Возникает вопрос "Почему, когда мы раньше суммировали нули, флаг нулевого результата Z поднялся , а теперь он не поднялся "? Ответ : флаг Z работает с байтом , а .00+.16=.16. То есть, результат не является нулевым (в отличие от .00+.00=.00). Точно также флага также флаги C и Z ) не поднимется ив тех случаях, если Вы будете, вместо числа, "подставлять " любые другие числа, большие чем .16 (вплоть до .255). Можете поменять местами числа X и Y , результат будет тот же самый Учитывая то, что флаг DC не поднимался и тогда , когда вместо числа "подставлялись " числа от .00 до .15, можно утверждать следующее если одно из слагаемых (или оба) является нулем, то при любом числовом значении второго слагаемого, флаги C и DC никогда не поднимутся, а флаг Z поднимется только в случае .00+.00=.00 . На основании этого утверждения, можно сделать следующий практический вывод если одно из слагаемых равно нулю, то переносов происходить не будет. В сущности , это объясняется просто в этом случае (одно слагаемое равно 0), из- за того что другое слагаемое, по определению, не может быть больше числа .255 (для байта) и .15 (для полубайта, выхода, отображаемых байтом и полубайтом , чисел, заграницы соответствующих "зон ", не происходит Следовательно , не происходит и переносов Поэтому флаги C и DC будут опущены А теперь замените .00 на .01, а вместо .16 поставьте .15. Сумма - такая же, как ив случае .00+.16=.16. Посмотрим, что изменится После выполнения команды, в регистре STATUS зафиксируется число 1Ah ( 00011010 ). Теперь флаг DC поднялся Он также поднимется ив случаях 2+14, 3+13, 4+12 и т д до 15+1 включительно, а также и при других комбинациях чисел, если ни одно из них не является нулем и их сумма больше 15- ти А если меньше 15- ти (в том числе ив случаях "применения " нулей, то флаг DC будет сброшен А теперь посмотрим, что произойдет, если слагаемые "выходят " из числового диапазона полубайта (.00 … .15) в других случаях Например, просуммируем числа .08 ( 00001000 ) и .150 ( 10010110 ). Флаг DC сбросился Почему ? Еще раз напоминаю, что флаг DC работает только в пределах младшего полубайта 198 Младший полубайт числа .08 равен .08. Младший полубайт числа .150 равен .06. Флаг DC сбросился потому, что .08+.06=.14 (меньше .15- ти ). А теперь просуммируйте числа, например, .08 ( 00001000 ) и .153 ( 10011001 ). Флаг DC поднялся Почему ? Младший полубайт числа .08 равен .08. Младший полубайт числа .153 равен .09. Флаг DC поднялся потому, что .08+.09=.17 (больше .15- ти ). А вот пример, когда оба флага (и) поднимаются Просуммируйте числа, например, .139 ( 10001011 ) и .157 ( 10011101 ). Флаги С и DC поднялись Почему ? Младший полубайт числа .139 равен .11. Младший полубайт числа .157 равен .13. Флаг DC поднялся потому, что .11+.13=.24 (больше .15- ти ). Флаг С поднялся потому, что .139+.157=.296 (больше .255- ти ). После исполнения команды, в регистр W, будет записано число 28h (.40). Разбираемся, откуда оно "взялось ". Из- за того, что число .296 больше числа .255, произошел переход на второй "виток " счета В пределах этого второго "витка ", результат суммирования "займет положение " числа (28h). Количество этих "витков " не может быть более двух (почему Ответьте самостоятельно. Таким образом, вне зависимости от значения суммы двух чисел, отображаемой байтом, флаг "реагирует " только на результаты выполнения операций сложения (вычитания) содержимого младших полубайтов Образно выражаясь, флагу "все- равно, что происходит " в старшем полубайте Он работает на своем "узком участке " вбита и "контролирует " именно этот участок, а не весь байт Весь байт (оба полубайта) "контролируют " флаги Z и C Возникает вопрос "Где может дислоцироваться этот легендарный байт, с которым мы все время работаем" Ответ : там , куда программист посчитает целесообразным его поместить В данном случае, "местом его дислокации " является регистр (см комментарий к команде ADDLW ). Если же применить байт- ориентированную команду, то можно выбрать, куда поместить результат операции или во всё тот же аккумулятор, или в регистр общего назначения, а это уже "выход на широкий, оперативный простор ". А теперь посмотрите в комментарий к флагу DC (см распечатку. В нем флаг DC называется флагом десятичного переноса - заёма Этот комментарий я, в свое время, взял из технической документации, предоставляемой компанией Microchip. Флаг |