Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 16.06.2025
Просмотров: 3610
Скачиваний: 3
-а после его очищения (в счетчике - ноль), декрементируется содержимое регистра старшего байта.
Примечание: N-байтный счетчик может называться N-разрядным счетчиком.
Впоследнем случае, имеется ввиду количество байтов. Строго говоря, такое определение удобно, но не вполне корректно. Имейте это ввиду.
Далее, я буду использовать оба этих понятия. Именно так и "закаляется сталь/приобретается иммунитет" ("организмы должны быть стойкими").
Декремент счетчика младшего разряда будет происходить каждый раз после формирования периода тонального сигнала, а декремент счетчика старшего разряда будет происходить через каждые 256 периодов тонального сигнала, в момент смены, в младшем разряде счетчика, числа .255 на число .0 Сигналом окончания формирования трехсекундного интервала времени является очищение
счетчика старшего разряда, после чего рабочая точка программы должна "уйти" в сценарий "программа исполняется далее".
По своей сути, этот "механизм" ничем не отличается от "механизма" работы счетчика, собранного, например, на микросхемах счетчиков (...ИЕ...) и тот, кто с ними работал, без особого труда поймет, о чем идет речь.
Врегистры SecH и SecL, нужно записать какие-то константы.
Нужно определиться с их числовыми значениями.
Для того чтобы "отмерить" 3 сек., 2-хразрядный счетчик должен посчитать 4348 периодов (см. выше).
Счетчик младшего разряда декрементируется каждый период.
Если установить в нем константу, например, .255, то в процессе последовательного декрементирования, после установки числа .0, произойдет один декремент содержимого счетчика старшего разряда.
Затем, в счетчике младшего разряда, происходит переход от .0 к .255 и все повторяется снова. И так происходит много раз (счет "по кольцу"). Пока не обнулится счетчик старшего разряда.
Таким образом, при прохождении 4348 периодов, должно произойти примерно 17 декрементов содержимого счетчика старшего разряда.
Следовательно, для того чтобы очистить счетчик старшего разряда примерно за 3 сек., необходимо записать, в регистр SecH, константу .17
Вданном случае, в счетчик младшего разряда записывается максимально возможное значение константы (.255), которое, по этой причине, условно можно приравнять единице значения константы старшего разряда.
Таким образом, в счетчик старшего разряда необходимо заложить "прикидочную" ("грубую")
константу .17 - .1 = .16
Обращаю Ваше внимание на следующее.
Между первой командой ПП CYCLE и командой decfsz SecL,F располагаются не только отдельные команды, но и целых две циклические подпрограммы.
Подпрограмма CYCLE классифицируется как циклическая подпрограмма задержки, с "массивной врезкой", включающей в себя две циклические ПП задержки PAUSE_1 и PAUSE_2.
Вот Вам и наглядная иллюстрация того, о чем я говорил ранее: в состав "врезки" могут входить не только отдельные команды, но и целые циклические подпрограммы.
Вциклическую ПП задержки, образно выражаясь, можно "врезать все что угодно". Главное при этом то, чтобы после этого, ПП задержки не "потеряла свою жизнеспособность" и обеспечивала нужное время задержки.
Если говорить конкретно о циклической ПП CYCLE, то можно сделать следующий вывод: "врезка" подпрограммы CYCLE работает по заданному разработчиком алгоритму и обеспечивает полный цикл этой подпрограммы, равный периоду сигнала с частотой 1450 Гц. (690 мкс.).
2-хразрядный счетчик отсчитывает число периодов, "помещающихся" в трехсекундном интервале времени, и по его окончании, осуществляется переход в сценарий "программа исполняется далее".
"Для полного счастья", остается только детально разобраться с константами трехсекундного счетчика (таймера).
Чтобы излишне не мудрствовать, "привяжусь" к тем значениям констант, которые были указаны выше.
102
То есть, .255 в младшем разряде счетчика и .16 в старшем.
С учетом того, что "прикидка" производилась "грубо", и в результате этого, реальное время "выхода" в эфир сигнала тонального вызова несколько больше, чем расчетное, я на единицу уменьшил числовое значение константы счетчика старшего разряда и сделал ее равной .15. То есть, в этом случае, сигнал тонального вызова будет "выдаваться" в эфир в течение времени немного меньшего, чем 3 сек.
"На фоне слова приблизительно", это приемлемо.
Лично я, решил так, а другой человек может принять другое решение.
Например, можно уменьшить числовое значение константы счетчика младшего разряда, а числовое значение константы счетчика старшего разряда не менять, или перейти к другому соотношению числовых значений констант, или вообще задать другое значение интервала времени "выхода" в эфир сигнала тонального вызова.
Если, как в данном случае, точной калибровки не требуется, то достаточно и приблизительного расчета, подобного приведенному выше.
То есть, рассчитанные ранее константы, можно "смело закладывать" в программу, и в дальнейшем, не тратить время на проверку истинного значения трехсекундного интервала времени в симуляторе.
Естественно, что в этом случае, нужно быть уверенным, что расчеты произведены правильно.
Если возникают сомнения по поводу правильности выбора числовых значений времязадающих констант, то милости просим в симулятор. Он для этого и существует. Если же речь идет о формировании калиброванных (точных) интервалов времени (в нашем случае, времени полупериодов), то в большинстве случаев, без проверки их значений в симуляторе и соответствующей "рихтовки", не обойтись.
Итак, "окончательно и бесповоротно" назначаю: константа старшего разряда счетчика = .15, константа младшего разряда счетчика = .255 .
Теперь возникает вопрос: "В какое место текста программы нужно врезать группу команд записи констант"?
Ответ на этот вопрос был дан ранее, и поэтому "врезаю" эту группу команд в концовку ПП
START.
Вот Вам и ответ на вопрос: "Откуда взялась, в концовке ПП START, группа команд записи констант и почему она выглядит именно так"?
Если производится последовательная запись констант в несколько регистров, то порядок этой записи не имеет значения.
Применительно к данному случаю, это означает то, что сначала можно записать константу в регистр SecH, а потом, в регистр SecL или наоборот.
Что получается? А получается это:
Декремент содержимого 2-хразрядного счетчика производится при наличии, на НЧ выходе устройства, единичного уровня, так как рабочая точка программы "заходит в этот счетчик" во время формирования положительного полупериода.
Во время формирования 3-хсекундного интервала времени, после перехода рабочей точки программы в ПП CYCLE, установка нулевого уровня, на НЧ выходе устройства, происходит после исполнения команды bcf PortB,2.
Далее, с помощью ПП PAUSE_1, этот уровень фиксируется на время отработки полупериода. Далее, после исполнения команды bsf PortB,2, на НЧ выходе устройства, устанавливается единичный уровень.
Далее, с помощью ПП PAUSE_2, этот уровень фиксируется на время отработки полупериода. Далее, происходит декремент содержимого 2-разрядного счетчика.
Если результат декремента не равен нулю, то происходит переход в ПП CYCLE
(goto CYCLE) и все повторяется снова и снова, до тех пор, пока, с момента включения на передачу, не пройдет примерно 3 сек.
Посмотрите в текст программы cus.
После 4-х команд 2-хразрядного счетчика, Вы видите команду bcf PortB,2
Именно на эту команду переходит рабочая точка программы после того, как счетчик старшего разряда очистится, то есть, завершится формирование 3-хсекундного интервала времени "выхода" тонального сигнала в эфир.
Этой командой осуществляется смена единичного уровня, на НЧ выходе устройства, на нулевой.
103
Это сделано для того, чтобы после очищения счетчика старшего разряда, закончить формирование положительного полупериода.
Собственно говоря, эта команда вставлена в текст программы "для порядка" и без нее вполне можно обойтись (убрать).
Ив самом деле, какая разница, какой уровень "выставлен" на НЧ выходе устройства после формирования 3-хсекундного интервала времени "выхода" тонального сигнала в эфир (см. разделительный конденсатор)?
Эту команду можно оставить, а можно и удалить.
Далее, рабочая точка программы "влетает" в ПП PRD, которую сейчас предстоит создать. Напоминаю, что она должна делать.
В этой ПП, рабочая точка программы должна уйти в "вечное кольцо" и выйти из него в момент переключения с передачи на прием, с последующим переходом на новый цикл программы. "Механизм" функционирования "вечного кольца" рассмотрен ранее (см. "вечное кольцо" ПП
START).
Ив ПП PRD он точно такой же.
Разница только в деталях: так как "закольцовка" происходит внутри ПП PRD, то команда безусловного перехода должна обращаться к ПП PRD, и при опросе состояния вывода RB0, вместо команды btfsc, используется команда btfss (если применить btfsc, то будет "вилка"). Если речь идет о длительной "закольцовке" (что и имеет место быть), то обязательно нужно периодически сбрасывать WDT.
В"вечном кольце" ПП START, это делалось с помощью команды clrwdt, расположенной в группе команд подготовительных операций.
Примерно так же нужно поступить и по отношению к ПП PRD.
То есть, нужно "врезать" команду clrwdt в цикл "вечного кольца" этой подпрограммы.
Вданном случае, команду clrwdt можно "пристроить" единственно разумным способом - сверху от команды ветвления, с переносом названия подпрограммы PRD на команду clrwdt. Посмотрите, как это выглядит в тексте программы cus.
Необходимость применения команды clrwdt обусловлена тем, что время включения на передачу может быть бОльшим, чем 2,3 сек.
Первые 3 команды ПП PRD можно классифицировать так: циклическая ПП задержки, с "врезкой" из одной команды, с "уходом в вечное кольцо" и с выходом из него по внешнему управляющему сигналу.
Для сценария типа "закольцовка", цикл такой подпрограммы равен 3 м.ц.+1 м.ц. команды clrwdt = 4 м.ц. и поэтому срабатывания WDT опасаться не нужно.
Итак, мы дошли до конца полного цикла программы.
Остается только вставить в текст программы команду безусловного перехода на "новый", полный цикл программы (goto START), чем и обеспечивается соблюдение "глобального"
принципа: рабочая точка программы всегда должна находиться в движении.
Текст программы всегда заканчивается директивой end для того, чтобы MPLAB "знал", что ниже этой директивы, текст программы "искать" не нужно.
Замечание по WDT: естественно, что длительность импульса, вырабатываемого WDT (в нашем случае, 2,3 сек.), можно уменьшить за счет уменьшения коэффициента деления предделителя.
Можно отключить предделитель от выхода WDT (18-ти мс. вполне достаточно) и даже вообще отключить WDT (в битах конфигурации).
Если имеется такое учебно-тренировочное желание, то нужно изменить числовое значение константы, записываемой в регистр OptionR или изменить числовое значение слова конфигурации.
Предполагаю, что после прочтения изложенной выше информации, возможно возникновение "неразберихи" в терминологии, связанной с такими понятиями как: подпрограмма задержки, счетчик, "уход в вечное" кольцо и т.д.
Все это, в своей основе, одно и то же, хотя, казалось бы, речь идет о выполнении разных функций.
И в самом деле, что общего между, например, ПП PAUSE_1, ПП PRD и ПП CYCLE, кроме того, что все они - циклические?
Конструкции разные, и выполняемые функции также разные.
Однако, в основе "всего этого великолепия", лежат такие понятия как "задержка" и "счетчик" ("сиамские близнецы").
Например, подпрограмму PRD можно классифицировать как подпрограмму задержки, с
104
выходом из нее по внешнему воздействию, но ее можно считать и счетчиком, который отсчитывает время, от момента очистки старшего разряда трехсекундного счетчика и до момента перехода с передачи на прием. И первое, и второе "имеют право на жизнь". Примерно то же самое (с поправкой на специфику) можно сказать и о любых других циклических подпрограммах.
Такого рода классификация - процесс субъективный, и поэтому одну и ту же подпрограмму можно классифицировать по-разному.
Это зависит от того, какое из двух этих восприятий наиболее удобно (кто-то видит счетчик, а кто-то видит задержку или их "гибрид").
Частенько из-за этого возникают "разнобои", которые не способствуют взаимопониманию. Конечно, если человек "упертый", то он, через "пинки, синяки и шишки", рано или поздно выработает в себе умение смотреть на любую циклическую подпрограмму с обеих точек зрения (счетчик/задержка), но с целью минимизации указанных выше "бяк", выгоднее изначально разобраться с подобного рода "вещами" и не жалеть на это времени.
В качестве тренировки, попробуйте разглядеть в любой из циклических подпрограмм программы cus, одновременно, и устройство типа счетчика, и устройство, осуществляющее задержку.
Дополнение
Какую именно группу команд считать подпрограммой - определяет программист. Программист может видоизменить исходную подпрограмму так, что и "мама родная не узнает", вплоть до того, что вообще лишить ее этого "статуса", и в "статусе" группы команд, включить ее в состав другой подпрограммы.
Короче, "полная демократия".
Однако, существуют определенные правила, которых, с точки зрения "наведения элементарного порядка", нужно придерживаться.
Если имеется группа команд с четко выраженной функциональностью, то прежде чем присваивать ей "статус" подпрограммы, нужно ответить на вопрос: "Имеется ли в тексте программы хотя бы один переход на начало исполнения этой процедуры или таких переходов нет"?.
Если хотя бы один такой переход есть, то этой группе команд присваивается "статус" подпрограммы, а если таких переходов нет, то этого делать не нужно (хотя и можно), так как "захламлять" текст программы неработающими названиями подпрограмм, нет смысла. Например, 2-х разрядный счетчик, реализованный в программе cus, является функционально законченным устройством и ему, формально, вполне можно "присвоить статус" подпрограммы.
В этом случае, в 1-м столбце текста программы, "прописывается" название подпрограммы
(например, XYZ) XYZ decfsz SecL,F.
Но это название не будет работать, так как в программе cus, отсутствует необходимость в безусловном переходе на XYZ.
Получается что-то типа "лишнего балласта".
А раз это так, то и незачем назначать такое неработающее название.
Что касается меток, то они применяются для того чтобы перейти на любую другую команду текста программы, которая не является первой командой подпрограммы.
Пример "манипуляций" с меткой (правда, их результат функционально "забракован", но на "технологию" работы с метками это не влияет), был приведен выше.
Краткий, общий итог
Выше описан процесс конструирования конкретного устройства на основе ПИКа. Надеюсь на то, что после знакомства с этой информацией, Вы поняли, что если заранее определены исходные данные, то процесс составления программы не есть что-то суперсложное.
Изначально, с непривычки, некоторые из Вас могут с этим не согласиться, но после того, как Вы "набьете руку", то сами удивитесь, как это, в сущности, относительно просто.
Добрый совет: на данной стадии обучения, не стОит "стрелять из рогатки по медведю". То есть, вовсе не нужно пытаться сразу же сконструировать что-то свое.
Для этого, как минимум, нужна "рогатина", а еще лучше, "ружье".
105
На первых порах, для приобретения "солидного инструментария" и его "шлифовки", советую Вам обратить самое пристальное внимание на "разбор полетов", а именно, на анализ текстов "чужих" программ.
То есть, программ для устройств с готовыми исходными данными (неопределенности отсутствуют).
Вэтом, я, по мере своих возможностей, постараюсь эффективно Вам помочь.
Втом смысле, что кроме подробного анализа текстов программ, я постараюсь показать, как именно происходит "борьба с неопределенностями", вразумительное описание чего, по совокупности причин, является большой редкостью.
Вконечном итоге, когда Вы "набьете руку" и займетесь практическим конструированием,
"центр сложности" несколько сместится, из "технологического сектора работы", в "сектор работы по борьбе с неопределенностями".
До этого еще далековато.
Сейчас же, главная задача "прочувствовать (в том числе, и на уровне подсознания) правила игры". Пока, в приложении к простым программам.
Ранее, в ходе работы над текстом программы, "механизм" визуального, Образного восприятия работы программы (не все в нашем деле определяется только прямолинейной логикой) был задействован как-то слабовато.
Теперь пора его "включить на полную мощность". Речь идет о работе в симуляторе.
Кроме того, что Вы реально увидите, как рабочая точка программы движется по тексту программы (как исполняется программа и что при этом происходит в "недрах" ПИКа), Вы узнаете и то, что такое отладка программы.
"Самоучитель по программированию PIC контроллеров для начинающих" http://ikarab.narod.ru E-mail: karabea@lipetsk.ru
106
9.Работа в симуляторе. Отладка программы.
Отом, что такое симулятор, говорилось ранее. Подошло время "привести этот мощнейший инструмент в полную боевую готовность".
Введение
Для создания общего представления о том, зачем нужен симулятор, достаточно представить себе разницу, например, между счётами и компьютером.
Естественно, что бухгалтер, работающий на компьютере, сделает одну и ту же работу быстрее и качественнее, чем если бы он работал со счетами.
Не может также вызвать сомнения и то, что прежде чем быстро и качественно сделать работу, необходимо, сначала, хотя бы знать, "с какого бока подойти" к этому самому компьютеру, на что нажимать и что после этого будет происходить.
Первичное представление о работе в симуляторе можно составить, усвоив соответствующую информацию из раздела, посвященного MPLAB.
Вдальнейшем, я исхожу из предположения, что эта информация Вами усвоена. Руководствуясь принципом "от простого к сложному", сначала рассмотрим случай:
программа, с которой работает симулятор, заведомо работоспособна. То есть, заданный разработчиком алгоритм ее работы, безошибочно выполняется.
Обращаю Ваше внимание на то, что безошибочно выполняемый алгоритм работы программы означает только то, что выполнение программы происходит в строгом соответствии с блок - схемой программы, и все ее "квадратики", в тексте программы, реализованы без ошибок функционального характера, но не то, что эта программа, в части касающейся точного соблюдения, заданных разработчиком, временнЫх характеристик устройства, идеальна. Например, имеется работоспособный частотомер, но из-за того, что в тексте программы неверно подобраны числовые значения времязадающих констант или использован кварц с номиналом частоты, отличающимся от рекомендованного, он будет "врать".
Если он "врет не сильно", то можно "превратить" его в "полноценный" измерительный прибор, корректируя значение частоты кварцевого генератора.
А если он "врет сильно" и эта коррекция не эффективна?
А если, при переходе с одного интервала времени измерения на другой, существует большая разница в показаниях одного и того же значения частоты?
Вэтих случаях, нужно "лезть" в текст программы и корректировать значения времязадающих констант или "подгонять" время исполнения одного сценария работы программы под время исполнения другого сценария (я это называю "выравниванием сценариев").
Сделаем это, пока, теоретически и в общем виде, без "привязки" к какой-то конкретной программе.
Итак, "запускаем" MPLAB и открываем проект с программой "врущего" частотомера. Допустим, что перед нами текст программы, созданной под частотомер. Естественно, что сначала, в тексте программы, нужно найти группы команд "закладки" соответствующих времязадающих констант, в регистры общего назначения, созданные и "прописанные" в "шапке" программы под это дело.
Эти группы команд - стандартные (о них говорилось выше: пары команд: movlw и movwf) и поэтому обнаружить их не составляет большого труда.
Если имеются несколько отдельных констант и/или групп констант (такое бывает часто), то необходимо выяснить, в реализации каких именно функциональностей они задействованы, и анализируя текст программы, "отсеять" ненужные.
Кстати, то, что Вы сейчас читаете, это примитивный пример использования приемов программно-аппаратного анализа.
Вчасти касающейся "тренировки мозгов", такая работа не то что полезна, а исключительно полезна.
Естественно, что такого рода "манипуляции" предполагают наличие опыта.
Если он есть, и человек владеет приемами программно-аппаратного анализа, то даже при отсутствии комментариев к тексту "чужой" программы, в ней, по большому счету, можно "вычислить" все что угодно, и что-то целенаправленно изменить.
Вконце концов, "материнскую" программу можно "перекроить так, что мама родная не узнает" или, на ее основе, создать нечто новое.
Именно к этому нужно всячески стремиться, и именно это является одним из главных признаков классного программиста, который, по определению (по умолчанию), является
107