Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008). Самоучитель по программированию PIC контроллеров для начинающих. Система команд pic16F84A 26 Что такое программа иправила ее составленияПример создания программы автоколебательного мультивибратораДирективы.
![]()
|
; Если результат декремента не =0, ; то переход в ПП PAUSE_D. incfsz SecH_1,F ; Если результат декремента =0, то инкремент ; старшего разряда счетчика SecH_1. goto PAUSE_D ; Если результат инкремента не, ; то переход в ПП PAUSE_D. ; Если результат инкремента =0, то программа ; исполняется далее. ;================================================================================ ; Формирование интервала времени сканирования. ;================================================================================ movlw .245 ; Закладка константы .245 в регистр W. movwf SecH ; Копирование .245 из регистра W 143 ; в регистр SecH. movlw .255 ; Закладка константы .255 в регистр W. movwf SecL ; Копирование .255 из регистра W ; в регистр SecL. ;-------------------------------------------------------------------------------- ; Разрешение прерываний INT. ;-------------------------------------------------------------------------------- movlw .144 ; Закладка константы .144 в регистр W. movwf IntCon ; Копирование .144 (1001 0000) из регистра W ; в регистр IntCon ; (разрешение прерываний по входу INT). ;-------------------------------------------------------------------------------- PAUSE clrwdt ; Сброс WDT. decfsz SecL,F ; Декремент содержимого младшего разряда ; счетчика SecL. goto PAUSE ; Если результат декремента не, ; то переход в ПП PAUSE. incfsz SecH,F ; Если результат декремента =0, то инкремент ; старшего разряда счетчика SecH. goto PAUSE ; Если результат инкремента не, ; то переход в ПП PAUSE. ; Если результат инкремента =0, ; то программа исполняется далее. ;-------------------------------------------------------------------------------- ; Изменение направления ретрансляции. ;-------------------------------------------------------------------------------- clrf IntCon ; Запрет всех прерываний. incf Trigg,F ; Увеличение на 1 (инкремент) содержимого ; переключателя направления ретрансляции. goto START ; Переход на новый цикл сканирования. ;******************************************************************************** end ; Конец программы . Создайте проект с названием Retr_1 , загрузите в него файл, проассемблируйте текст программы и убедитесь в отсутствии ошибок Обращаю Ваше внимание на то, что при использовании прерываний, директива назначения вектора прерываний 4 эту директиву просто нужно принять как данность) должна находиться, в "шапке " программы, сразу же за командой То есть, после возникновения факта прерывания, рабочая точка программы автоматически "улетит " в ячейку PC с адресом 04h (это определено разработчиками ПИКов ). Откройте окно ROM и убедитесь в этом Если после директивы 4 , нет команды перехода в ПП прерывания , то рабочая часть программы должна начинаться с ПП прерывания , а "основное тело " программы должно быть расположено сразу же после команды retfie Если ПП прерывания "врезана " в "основное тело " программы (располагается, например, в середине текста программы Условно ), то такой переход должен быть То есть, в ячейке PC с адресом 04h, должна находиться - либо первая команда ПП прерывания , либо команда перехода в ПП прерывания . В данном случае, речь пойдет о первом варианте Вопросы может также вызвать и ПП INT Вопрос : " В тексте программы, команд переходов, в эту ПП (или на эту метку, нет (они и не нужны, так как переход происходит по вектору прерываний, которому "по барабану " все названия. Для чего нужно это название "? Ответ : для удобства отслеживания и отладки Пояснение В ходе работ по отслеживанию и отладке программы, с переходом в "основное тело " программы, проблем не возникает сбрасываем программу на начало, нажимаем F7 и попадаем на первую команду ПП START А как попасть на первую команду ПП прерываний ? Без "уловок " здесь не обойтись 144 Самая простая из них для обеспечения перехода на первую команду ПП прерывания (то есть, в ПП прерывания ), на этой команде выставляется метка (в нашем случае. А можно сказать и то , что подпрограмме присваивается название Можно итак, и эдак На смысл не влияет В "шапку " программы, сразу же после команды START , "врезается " команда в тексте программы ее нет, но при отслеживании и отладке программы ее нужно вставить. А теперь все очень просто если ставим точку с запятой (блокируем команду) перед командой INT (перед командой точки с запятой нетто попадаем на первую команду ПП START , а если снимаем точку с запятой с команды goto и ставим точку с запятой перед командой START , то попадаем на начало ПП прерывания Вот для этого и нужна метка с названием INT (или с другим названием. В текст программы, я ее ввел для того чтобы обозначить начало ПП прерывания Команду goto можете прямо сейчас "врезать " в "шапку " программы, только заблокируйте ее точкой с запятой В дальнейшем , при отслеживании и отладке , она потребуется Перед "прошивкой ", то есть, после того, как программа полностью отработана, эту метку (а также и команду goto INT ), из текста программы можно удалить Это никак не повлияет на работу устройства Разбираем текст программы Эту "разборку " я буду проводить не так детально, как ранее С учетом того, что предыдущая информация Вами усвоена Принцип "конструкции шапки " программы – стандартный Повторяться не буду Остановлюсь только на особенностях Три пары регистров с названием Sec... - элементы трех двухразрядных счетчиков Регистры со стандартными (рекомендовано разработчиками) названиями W_Temp и Stat_Temp, это регистры оперативной памяти, использующиеся для сохранения содержимого регистров W и Status, в интервале времени исполнения ПП прерывания На регистре с названием Trigg "собран " триггер со счетным входом Так как используются команды, результат исполнения которых необходимо сохранить в регистре W, то в Определении места размещения результатов операций дополнительно "прописан " регистр W В соответствии со сказанным выше, в конце "шапки " программы, располагается директива Выполнение программы начинается с запрета всех прерываний ( clrf IntCon ). Команду сброса (в программе он задействован См биты конфигурации) можно вставить в любое место подготовительных операций Причина такой "демократии " заключается в том , что интервал времени срабатывания значителен, ион с запасом "перекрывает " интервал времени исполнения команд подготовительных операций (и не только их. Если последующие команды clrwdt обеспечивают перезапуск RC- одновибратора сторожевого таймера до окончания формирования его импульса, то команда, расположенная вначале исполнения программы, в принципе , ненужна, но "пусть живет " кашу маслом не испортишь "). Далее, также как ив программе, "настраиваются " направления работы выводов порта В : RB0/INT - "на вход ", остальные (в том числе и интересующий нас вывод) - "на выход " ( 00000001 ). Подтягивающие резисторы порта В включены Собственно говоря, нужно подключить только один подтягивающий резистор К выводу RB0/INT Но так как они могут быть включены или отключены только "оптом "значит подключаем их все В этом же регистре 6- й бит (выбор активного фронта прерывания) устанавливается в ноль То есть, в соответствии с задуманным (см задание на разработку, прерывание будет осуществляться по перепаду от 1 к 0. Все остальные биты регистра, кроме 6- го иго, нас не интересуют В них можно выставить любой уровень Для удобства, "привяжемся " к нулевым уровням 6- го иго битов 145 Поэтому, во всех битах регистра OptionR, выставляем нули, что соответствует числовому значению байта = 0. Смотрим в блок - схему программы Теперь нужно опросить состояние переключателя направлений ретрансляции типа "триггер со счетным входом ". Создаем этот триггер (или переключатель Кому как нравится. Процесс конструирования подобного рода устройств (всего- навсего 2 состояния 0 или 1) выглядит так Под это дело, назначается (прописывается ") регистр общего назначения В нашем случае, это регистр (см. "шапку " программы. Можно назвать и по - другому Все регистры общего назначения являются 8- битными Поэтому , диапазон чисел, который они способны отобразить от .0 до .255. В данном случае, такое большое количество состояний нам ник чему, ведь нужно только два из них Какие именно Любой из 8- ми двоичных разрядов может находиться водном из двух состояний (0 или 1), но чаще всего эти состояния будут меняться (в результате инкремента или декремента) в младшем , двоичном разряде То есть, в этом случае, они будут меняться после каждого инкремента или декремента, а не "через рази болееПоследовательно инкрементируя или декрементируя содержимое регистра, значение бита его младшего разряда будет меняться сна или наоборот Вот Вам и триггер со счетным входом При этом, значения битов оставшихся 7- ми разрядов нас не интересуют Вообще Таким образом, опрос состояния регистра Trigg можно производить "по принципу четности / нечетности ": если в нем четное число (бит, то программа исполняется по одному сценарию, а если нечетное (бит, то программа исполняется по другому сценарию Применительно к нашему случаю, это означает то, что при равенстве нулевого бита регистра Trigg нулю , ретрансляция будет происходить в одну сторону, а при его равенстве единице, в другую сторону Разбираем ПП TRIGGER Первая ее команда проверяет состояние нулевого бита регистра ( btfsc Trigg,0 ). btfsc - команда ветвления, следовательно, имеются 2 сценария дальнейшей работы программы 1. В случае исполнения одного сценария, в регистр PortB записывается константа .251 ( 11111 0 11 ), то есть, на выводе RB2 устанавливается 0 (одно направление ретрансляции. 2. В случае исполнения другого сценария, в регистр PortB записывается константа .255 ( 11111 1 11 ), то есть, на выводе RB2 устанавливается 1 (другое направление ретрансляции) Это связано со спецификой управления конкретным типом ретранслятора Так как на "линейном участке " программы (а мы сейчас как раз с таким и работаем ) рабочая точка программы движется только сверху вниз (по тексту программы) и последовательной записи обеих констант в регистр PortB допустить нельзя (должна записаться либо одна, либо другая, то для того чтобы это обеспечить, необходимо команду пометить меткой, ив одном из двух случаев, осуществить безусловный переход на эту метку При такой "конструкции " проверки, на команду никаким иным образом, кроме как с использованием команды перехода, перейти нельзя Кроме того, необходимо, чтобы после исполнения любого из этих сценариев, рабочая точка программы попала на одну и ту же команду продолжения программы в нашем случае это команда Это можно условно назвать "разветвлением на сценарии, с последующим их слиянием ". Обязательно обратите на это внимание, так как в дальнейшем , входе "въезда в выравнивание сценариев ", это пригодится Если после исполнения команд записи константы .255, в регистр PortB , рабочая точка программы, "естественным образом попадает " на команду .197 , то после исполнения команд записи константы .251, в регистр PortB , она может "попасть " на команду только после того, как произойдет запись константы .255, в регистр PortB Этого допустить нельзя 146 Какой смысл записывать .251, если в конечном итоге, все равно запишется .255 ? Значит, если в регистр PortB, записывается константа .251, то последующие команды записи, в него , константы .255, нужно обойти (перепрыгнуть " через них. То есть, нужно пометить команду еще одной меткой ( Metka_1 ), и после исполнения команд записи константы .251, в регистр PortB, нужно на нее перейти ( goto Metka_1 ). Посмотрите, как это сделано в программе Retr_1 После того, как направление ретрансляции выбрано (произошло переключение "раскладок " частот, необходимо сформировать защитный интервал времени продолжительностью примерно 50 … 150 мс (что это такое см выше. Для Vertex-7000VXR, хватит и 60 мс На эту цифру я и буду ориентироваться при отладке программы Таким образом, речь идет о банальной (без "выкрутасов ") ПП задержки Следовательно , предварительно (то есть, до начала ее исполнения, нужно записать, в задействованные под нее регистры общего назначения (и) соответствующие константы Калиброванную задержку величиной порядка 60 мс можно сформировать и одним разрядом счетчика, нос точки зрения универсальности устройства (оно может быть подключено и к аппаратуре с бОльшей инерционностью синтезатора частот, лучше сделать его двухразрядным Для разнообразия, в обучающих целях, младший разряд счетчика я сделаю вычитающим, а старший разряд - суммирующим Собственно говоря, добавить что- ток тому, что было сказано ранее (при "разборках " с двухразрядным , вычитающим счетчиком Программа cus ), нечего, за исключением напоминания о том , что в разряде суммирующего счетчика, направление "приближения " к нулю противоположно направлению "приближения " к нулю , в разряде вычитающего счетчика Если , например, нужно увеличить время задержки, то числовое значение константы вычитающего разряда счетчика необходимо увеличить, а числовое значение константы суммирующего разряда счетчика необходимо уменьшить Что касается конкретных, числовых значений констант, то они подобраны из расчета формирования защитного интервала времени величиной, примерно, 60 мс. Попробуйте, для тренировки, "грубо " рассчитать числовые значения констант, для защитного интервала времени = 60 мс. (с учетом "конструкции " счетчика, и сравните результат этого расчета стем, что "имеется в наличии ". В итоге , Вы должны получить числовые значения констант, близкие к тем , которые указаны в тексте программы Теперь , в соответствии с блок - схемой программы, необходимо сформировать интервал времени сканирования В принципе , это делается точно также, как ив случае формирования защитного интервала времени С целью недопущения "черепно- мозгового бардака ", в счетчике интервала времени сканирования, я задействовал отдельную пару регистров общего назначения, с названиями SecH и SecL Таким образом, в "основном телепрограммы, с которым мы сейчас работаем, задействованы две пары регистров общего назначения - при формировании защитного интервала времени SecH_1 и SecL_1 , - при формировании интервала времени сканирования SecH и SecL. А теперь посмотрим на содержимое регистров и на момент начала формирования интервала времени сканирования Оба они очищены (в них записаны нули, и далее , походу исполнения программы (в том числе и в ПП прерывания ), они не используются Вывод : их можно использовать повторно При формировании интервала времени сканирования То есть, можно обойтись без регистров и SecL , заменив их, соответственно, на и Верно также и обратное утверждение можно оставить только и SecL , аи убрать (вычеркнуть " из "шапки " программы. В данном случаев пределах одного полного цикла программы, работа этой пары регистров, будет выглядеть так после записи, в них , констант защитного интервала времени вначале формирования этого интервала) и очистки этих регистров (в конце формирования этого интервала, в них снова будут записаны константы, но только не защитного интервала времени, а интервала времени сканирования, после чего, в конце формирования интервала времени сканирования, эти регистры снова очистятся И это должно быть понятным, так как программа исполняется последовательно (сразу две задержки формироваться не могут. С учетом сказанного, конечно же, в текст программы (если эту программу предполагается использовать не как учебную) можно внести изменения, нос точки зрения обеспечения минимальной путаницы, при "въезде " в программу , я посчитал целесообразным "расписать " именно этот (4 регистра вместо 2- хне очень- то и рациональный вариант ее построения Практический вывод, из этих рассуждений, следующий если в программе задействованы однотипные счетчики, то во многих случаях, в них можно использовать одну и ту же группу регистров общего назначения. Забегая вперед, расскажу про случай, когда одну и ту же группу регистров общего назначения нельзя использовать в двух счетчиках В ПП прерывания имеется, аналогичный описанным выше, двухразрядный счетчик на регистрах и Пары регистров, и, можно объединить в одну пару, так как на момент начала работы одного счетчика, содержимое другого счетчика очищено (не значимо. А вот регистры, и, SecL объединить нельзя, так как содержимое счетчика, SecL значимо Если его уничтожить "записью поверху, то нормальная работа устройства будет нарушена Детали этого утверждения будут понятны после "въезда " в работу ПП прерывания На первых порах, рекомендую Вам , под каждый счетчик, назначать отдельную группу регистров общего назначения (так, как это сделано в программе |