Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
![]()
|
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. Флаг |