Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 16.06.2025
Просмотров: 3639
Скачиваний: 3
Выполняем команду nop.
Вокне RAM опять ничего не меняется (кроме PCL), так как эта команда не производит никаких действий.
Итак, рабочая точка программы "вышла на оперативный простор" и "стоит" на команде bcf PortB,2.
Исполняем эту команду.
Вокне RAM опять ничего не изменилось (кроме PCL).
Почему, ведь команда bcf PortB,2 является командой, влияющей на содержимое регистра? Объяснение: по умолчанию, 2-й бит регистра PortB установлен в 0.
То есть, имеет место быть подтверждение ранее установленного состояния ("краснеть" не от чего).
Напоминаю, что проверку состояний битов регистров, лучше производить в окне SFR, так как в нем, содержимое регистров представлено в удобной для восприятия форме (бинарной). Выполняем следующие 3 команды nop.
Вокне RAM, по указанной выше причине, опять не произойдет никаких изменений (кроме
PCL).
Рабочая точка программы "встала" на команду movlw .85.
"По образу и подобию", приведенного выше, отслеживания аналогичных команд (команд записи константы в регистр), отследите самостоятельно выполнение этой команды и следующей за ней, команды movwf Sec.
Убедитесь, что из регистра W, в регистр Sec, скопировалось число .85 (55h).
Итак, рабочая точка программы установилась на первой команде (clrwdt) ПП задержки
PAUSE_1.
Ранее, мы уже отслеживали выполнение этой команды, так что сделайте это самостоятельно.
Рабочая точка "встала" на команду decfsz Sec,F.
На момент ее исполнения, в регистре Sec (адрес 0Ch) находится число .85 (55h). Посмотрите в окно RAM и убедитесь в этом.
Выполняем команду decfsz Sec,F. Смотрим в окно RAM.
Изменение имеется: содержимое регистра Sec, в полном соответствии с алгоритмом выполненной команды, уменьшилось с 55h до 54h, то есть, на единицу (произошел декремент).
Так как число 54h (результат операции, сохраненный в том же регистре Sec) отлично от нуля, то следующей исполняемой командой должна быть команда goto PAUSE_1.
Проверяем. И в самом деле, рабочая точка программы "стоИт" именно на этой команде. Выполняем команду goto PAUSE_1.
Вокне RAM никаких изменений (кроме PCL) не происходит (аналогично выполнению команды goto START).
Смотрим в текстовый редактор. Произошел безусловный переход рабочей точки программы на первую команду ПП PAUSE_1 (clrwdt).
Снова выполняем команду clrwdt. Снова выполняем команду decfsz Sec,F.
Смотрим в окно RAM. Содержимое регистра Sec еще раз уменьшилось на 1 (с 54h до 53h). Число 53h не равно 0, значит далее, снова будет осуществлен безусловный переход в ПП PAUSE_1 и так далее.
До тех пор, пока регистр Sec не очистится (00h).
Таким образом, рабочая точка программы "закольцевалась" в ПП PAUSE_1.
Если пытаться "добраться" до конца этой "закольцовки" (00h по адресу 0Ch) пошагово, то это займет достаточно много времени (особенно, если счетчик - многобайтный).
Есть 2 способа уменьшения этого времени: либо назначить точкой остановки команду bsf PortB,2 и "дойти" до нее в "автомате", либо поступить следующим образом: нажать на кнопку F7 и не отпускать ее, одновременно контролируя содержимое регистра Sec в окне
RAM.
Вы увидите, что содержимое этого регистра достаточно быстро начнет уменьшаться.
При приближении к нулю (например, где-то в районе чисел 01h - 04h), нужно остановить счет, отжав кнопку F7, и "добраться" до состояния 00h, пошагово исполняя программу (с помощью всё той же кнопки F7).
128
Всоответствии с алгоритмом работы команды decfsz, после исполнения команды последнего декремента (переход от 01h к 00h), рабочая точка программы перейдет на команду
bsf PortB,2
При отслеживании работы программы, не нужно проверять соответствие фактических и требуемых значений временных параметров программы, так как оно проверяется при отладке программы.
При отслеживании работы программы, главное "протащить" рабочую точку программы по выбранному сценарию работы программы (а в идеале, поочередно, по всем сценариям) до конца полного цикла программы, с одновременным контролем соответствия фактического и задуманного алгоритмов исполнения программы.
Обнаружение такого несоответствия, почти всегда, свидетельствует о наличии ошибки функционального характера, которую нужно исправить.
Для различных сценариев исполнения программы, полные циклы программы будут функционально различны (со всеми вытекающими последствиями).
Итак, рабочая точка программы находится на команде bsf PortB,2.
Так как группы команд формирования отрицательного и положительного полупериодов идентичны, то не буду повторять практически одно и то же.
С учетом сказанного выше, Вы вполне сможете самостоятельно отследить исполнение группы команд формирования положительного полупериода.
После формирования интервала времени положительного полупериода, рабочая точка программы установится на команде decfsz SecL,F.
Посмотрите в окно RAM.
На момент исполнения этой команды, регистр Sec очищен (в нем "лежит" 00h), а в регистры SecH (адрес 0Dh) и SecL (адрес 0Eh) ранее записаны константы .15 (0Fh) и .255 (FFh) соответственно.
Выполняем команду decfsz SecL,F. Смотрим в окно RAM.
Содержимое регистра младшего разряда SecL уменьшилось с FFh (.255) до FEh (.254), то есть на 1, что соответствует алгоритму работы команды decfsz (что при условии сохранения результата операции в этом же регистре).
Результат выполнения операции (FEh) не равен нулю, следовательно, следующей исполняемой командой будет команда goto CYCLE.
Выполняем команду goto CYCLE.
После этого, рабочая точка программы "встаёт" на первую команду ПП CYCLE (btfsc PortB,0), что соответствует задуманному.
И в самом деле, после того как сформируется период сигнала тонального вызова, должно начаться формирование следующего периода, и т.д.
Вплоть до обнуления двухбайтного счетчика (то есть, до окончания трехсекундного интервала времени).
Таким образом, речь идет о длительной "закольцовке" рабочей точки программы. Вопрос: "Как отследить такую протяженную по времени закольцовку"?
Ответ: в этом случае, проверка правильности исполнения алгоритма работы программы сводится к обнаружению факта очищения регистра старшего разряда счетчика, ведь именно после его очищения, имеет место быть сценарий типа "программа исполняется далее".
Вданном случае, это единственный способ "выхода из закольцовки".
Так как речь идет о достаточно значительном интервале времени, то лучше всего произвести отслеживание факта "выхода из закольцовки" в "автомате".
Во всех остальных случаях (при пошаговом исполнении программы с кратковременными нажатиями F7 и при пошаговом исполнении программы с долговременным нажатием на F7), такого рода отслеживание займет много времени.
Итак, убеждаемся, что декремент старшего разряда счетчика происходит (ранее мы убедились, что происходит декремент младшего разряда счетчика).
Для этого необходимо назначить точку остановки на следующей, после decfsz SecH,F, команде, то есть, на команде goto CYCLE.
Итак, назначаем точкой остановки команду goto CYCLE. Сбрасываем программу на начало.
Для наблюдения за процессом счета, можно вызвать секундомер.
Щелкаем по кнопке с зеленым светофором ("автомат") и дожидаемся конца процесса счета
129
(придется подождать достаточно продолжительное время).
Через 175,71 мс. счет закончится и рабочая точка программы установится на команде goto CYCLE, следовательно, команда decfsz SecH,F "штатно" исполнена.
Смотрим в окно RAM.
Содержимое регистра SecL (младший разряд счетчика, адрес 0Eh) очистилось (00h), а содержимое регистра SecH (старший разряд счетчика, адрес 0Dh) уменьшилось на 1, с 0Fh (.15) до 0Eh (.14), в чем и требовалось убедиться.
После этого, можно еще раз "запустить автомат": содержимое старшего разряда счетчика еще раз уменьшится на 1 (с 0Eh до 0Dh), а потом еще и еще..., пока счетчик старшего разряда не очистится.
Но эта очистка займет много времени, да и особой надобности в ней нет, так как для того чтобы убедиться, что 2-хразрядный счетчик работает "штатно", достаточно и пары декрементов содержимого счетчика старшего разряда.
Вопрос: "Каким образом "выйти" на сценарий "программа исполняется далее", не тратя массу времени на очистку содержимого регистра старшего разряда SecH"?
Ответ: нужно сделать то, что мы уже делали ранее заменить следующую, после decfsz SecH,F, команду (goto CYCLE), на команду nop.
Делаем это.
Втекст программы внесены изменения, следовательно, производим ассемблирование. Теперь нужно удалить "старую" точку остановки и назначить "новую".
Но удалять старую точку остановки не нужно, так как она уже удалена при ассемблировании
(при ассемблировании, все точки остановки удаляются), значит нужно только назначить новую точку остановки на команде bcf PortB,2.
Делаем это.
Запускаем "автомат" и дожидаемся его отработки.
После этого, рабочая точка программы установится на команде bcf PortB,2.
Таким образом, мы "коварно проскочили" 2-хразрядный счетчик и перешли в сценарий "программа исполняется далее", что и требовалось.
Если после этого, Вы посмотрите на показания секундомера и в окно RAM, то увидите ту же самую "картину", что и в случае одного декремента содержимого SecH : 175,71 мс. и число 0Eh по адресу 0Dh.
То есть, в случае использования "уловки", SecH не очищается, и это естественно, так как при помощи одного декремента, SecH очистить нельзя.
Хотя и программа и не исполнена в полном объеме (00h в SecH нет), но тем не менее, мы можем, как говориться, с чистой совестью двигаться дальше, так как убедились, что счетчик работает по задуманному алгоритму, и получили гарантию "нормальной" его работы после замены "подставы" (NOPа) на "штатную" команду goto CYCLE.
Если у Вас есть время и терпение, то в познавательных целях, Вы можете добиться исполнения программы в полном объеме, многократно декрементируя содержимое регистра SecH, указанным выше способом.
Вэтом случае, goto CYCLE на nop менять не нужно.
Итак, мы находимся на команде bcf PortB,2. Выполняем ее.
Смотрим в окно RAM.
2-й бит регистра PortB изменил свое состояние с 1 на 0 (содержимое PortB изменилось с 04h
на 00h).
С учетом того, что перед исполнением команды bcf PortB,2, на выводе RB2 присутствует единичный уровень, это соответствует задуманному.
Рабочая точка программы перешла на первую команду ("врезку") ПП PRD (clrwdt). Выполняем команду clrwdt.
Рабочая точка программы установилась на команде ветвления btfss PortB,0 Следовательно, необходимо определиться, по какому из двух сценариев ее направить. Предположим, необходимо отследить исполнение сценария "программа исполняется далее". Смотрим в окно RAM (или в окно SFR).
В регистре PortB все биты установлены в 0 (в том числе и интересующий нас нулевой бит). Следовательно, по логике команды btfss, следующей должна выполниться команда
goto PRD, после чего рабочая точка программы "закольцуется" в ПП PRD, а это нас не устраивает (это не сценарий "программа исполняется далее").
130
Что делать?
Правильно, меняем goto PRD на все тот же "легендарный" nop. В ПП PRD имеется две проверки.
Если отслеживается первая проверка, то со второй проверкой "возиться" нет смысла, так как она в точности такая же.
Следовательно, вторую проверку можно просто заблокировать (исключить из отслеживания), поставив перед обеими ее командами точки с запятой.
В тексте программы произошли изменения, значит производим ассемблирование (при этом, все точки остановки снимаются).
Устанавливаем программу на начало.
Назначаем точку остановки на команде btfss PortB,0, "запускаем автомат" и ждем окончания процесса.
После его окончания, рабочая точка программы установилась на команде btfss PortB,0. Выполняем ее.
Выполняем следующую команду (nop).
Рабочая точка программы установилась на команде goto START, минуя команды второй проверки (они заблокированы).
Итак, мы "протащили" рабочую точку программы по выбранному сценарию ее работы (самому "протяженному". По количества команд).
Если выполнить команду goto START, то рабочая точка программы "улетит" на начало полного цикла программы.
Из рассмотренного выше, можно сделать следующие выводы:
Понятие "полный цикл программы" есть общее понятие. Его можно/нужно рассматривать как совокупность нескольких вариантов полных циклов программы (по количеству возможных сценариев ее исполнения).
По этой причине, не вполне корректный вопрос: "Каков полный цикл программы"?, нужно задавать иначе: "Каков полный цикл программы для конкретного сценария ее исполнения"? Такая постановка вопроса корректна, ведь различные сценарии исполнения программы будут отличаться как по количеству команд, так и по своей функциональности.
Отслеживание выполнения программы (для выбранного ее сценария) можно производить не детально (а можно и детально, но это более трудоемко), а в "формализованном" виде.
Это означает то, что если имеются несколько одинаковых групп команд, то достаточно отследить выполнение одной из них, а другие проигнорировать Конечно, все это достаточно условно и зависит от квалификации программиста.
И в самом деле, если программист "врезал" в текст программы подпрограмму (группу команд), с которой он много раз работал и которую знает "как облупленную", то какой смысл заниматься бестолковкой?
Например, в программе cus, группы команд формирования отрицательного и положительного полупериодов идентичны, и в принципе, можно отследить только выполнение одной из этих групп команд, а другую проигнорировать, но для этого нужно быть полностью уверенным в том, что в этой проигнорированной группе команд, нет ошибок.
То есть, опять же, такого рода упрощение работы "упирается" в квалификацию и опыт программиста.
Именно по этой причине, опытный программист может отследить выполнение различных сценариев работы программы "с реактивным свистом", а не имеющий такого опыта, может потратить на это дело уйму времени.
Все это - "дело наживное", и по мере "набора ума-разума", процесс отслеживания будет занимать все меньше и меньше времени.
Побольше "разборов полетов / тренировки", и все будет полном порядке.
Обращаю Ваше внимание на разницу между отслеживанием и отладкой программы.
Отслеживание выполнения программы первично.
Оно необходимо для проверки соответствия фактических алгоритмов ее исполнения задуманным, что автоматически означает проверку программы на предмет наличия ошибок функционального характера, которые, естественно, нужно устранить.
Отладка программы вторична.
Она производится после отслеживания ее выполнения (а какой смысл производить отладку, если есть вероятность того, что в тексте программы имеются функциональные ошибки?). Проще говоря, слову "отслеживание" можно поставить в соответствие слово "грубо", а слову "отладка", слово "точно".
131