Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 16.06.2025

Просмотров: 3627

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

W.

Если есть хотя бы одна такая команда, то строка W equ 0 оставляется в "шапке" программы, а если их вообще нет, то удаляется.

То же самое относится и к строке F equ 1

В тексте программы cus, результаты выполнения команд сохраняются в тех же регистрах, с содержимым которых производятся действия, а регистр W не задействуется.

По этой причине строка F equ 1 оставлена, а строка W equ 0 удалена (хотя, ее можно и оставить. От этого, в работе программы ничего не изменится).

Идем далее.

Строка RP0 equ 5

С учетом сказанного выше, становится понятным, что директива equ дает указание MPLAB: если в тексте программы имеется комбинация символов RP0, то ее нужно воспринять как цифру 5 (в данном случае, 5-й бит регистра Status переключение банков).

Вэтом случае, команда переключения в нулевой банк будет выглядеть не как bcf Status,5, а как bcf Status,RP0 (установить в 0 пятый бит регистра Status), а команда переключения в первый банк будет выглядеть не как bsf Status,5 , а как bsf Status,RP0 (установить в 1 пятый бит регистра Status).

Таким же образом, при помощи директивы equ, можно "подменить" номера любых битов регистров специального назначения на стандартные названия этих битов (можно даже придумать свои названия, но зачем это нужно?).

Названия битов запоминаются гораздо легче, чем номера битов, которые, к тому же, и дублируются (регистров много, а битов всего 8), поэтому рекомендую Вам оперировать не номерами битов, а их названиями.

К таким "вещам" нужно привыкать с самого начала.

Естественно, что имеет смысл присваивать названия только тем битам, которые задействованы в программе.

Впрограмме cus, задействован только один такой бит (RP0). Он и "прописан".

Если возникнет такая необходимость, то ходу написания программы, можно заменять номера битов на их названия (естественно, с "пропиской").

Аможно изначально прикинуть, какие биты могут потребоваться, "оптом прописать" их, а затем, по окончании работы над текстом программы, убрать те названия битов, обращений к которым нет.

Из сказанного можно сделать вывод: ничего плохого не произойдет, если в "шапке" программы будет "прописано" то, что в программе не используется (ошибки нет).

Авот об обратном такого сказать нельзя: если в рабочей части программы будет использовано то, что в "шапке" программы не "прописано", MPLAB обязательно "заругается" и укажет Вам на это.

То есть, после ассемблирования, Вы получите сообщение об ошибке, и MPLAB "откажется" создавать HEX-файл.

И еще один вывод, директива equ ставит в соответствие одно другому: - название регистра его адресу, - название бита его номеру,

- название константы (константе тоже можно присвоить название) ее значению. Применение этой директивы позволяет составить удобный, для работы и восприятия, текст программы.

И в самом деле, зачем каждый раз, при обращении, например, к регистру, указывать его адрес в области оперативной памяти (можно сделать и так), когда этот регистр можно один раз "прописать", а затем указывать только его название.

Этому названию MPLAB автоматически поставит в соответствие адрес того регистра, которому оно присвоено (найдет его в области оперативной памяти).

И последнее, что нужно указать в "шапке": "точку входа" в программу и "точку входа" в подпрограмму прерывания.

О последнем будет отдельный разговор.

Так как в программе cus прерывания не используются, то и "точку входа" в подпрограмму прерывания указывать не нужно.

Для того чтобы задать "точку входа" в программу, необходимо, при помощи директивы org, указать, с какого адреса (в счетчике команд PC) нужно начать исполнение программы

(org 0 - начать с нулевого адреса).

В подавляющем большинстве случаев, указывается нулевой адрес, но можно указать и

88


другой.

В последнем случае, в памяти программ, все команды программы смещаются вниз на количество ячеек PC, указанное в рабочей части директивы org (применяется редко и в специфических случаях).

Директива org подобна стартовому пистолету: после того, как она "сделает свое дело" можно начинать исполнение рабочей части программы.

Если рабочая часть программы начинается с ПП START, то никаких дополнительных "пинков" не нужно: программа начнет исполняться с ПП START, как говорится, "своим ходом".

А если ПП START находится где-то в "дебрях" текста программы (например, в середине текста), то нужен "пинок", в качестве которого используется команда goto START.

В соответствии со сказанным, в программе cus, после директивы org 0, команда goto START не нужна, но в обучающих целях, я ее убирать не стал, так как во многих случаях, эта команда нужна.

Пусть она Вам немного "глаза помозолит". Хуже от этого не будет. Теперь о синтаксисе.

В"шапке" программы, названия "того-сего" могут быть указаны в удобной для программиста форме.

Например, в "шапке" программы, указано название регистра IntCon. Это означает то, что в рабочей части программы, при обращении к этому регистру, обязательно должны буквально соблюдаться правила написания этого слова.

Если Вы укажете его название как INTCON или Intcon, то после ассемблирования получите сообщение об ошибке.

Если бит "прописан" как RP0, то именно в таком виде название этого бита должно "фигурировать" в рабочей части программы.

Если Вы там укажете его название как rP0 или Rp0, то опять же, получите сообщение об ошибке.

Сказанное относится как к названиям рабочих битов, так и к названиям битов флагов. Примечание: в тексте программы cus, биты флагов не используются (операций с флагами нет).

Названия регистров W и F можно указывать и с большой, и с маленькой буквы.

Например, если в "шапке" указана буква F, то в рабочей части программы можно писать f или F. Ошибки не будет.

То же самое распространяется на адреса и директивы.

Например, можно написать адрес регистра как 0CH, 0cH, 0ch, 0Ch, а директиву как equ, Equ,

EQu, EQU ...

Врабочей части программы, названия подпрограмм (и меток) должны буквально совпадать с названиями этих же подпрограмм (меток), которые указываются в командах переходов. Например, имеется подпрограмма START.

Если, при переходе в эту подпрограмму, в команде перехода, указано Start (goto Start, а не goto START), то MPLAB выдаст сообщение об ошибке.

Названия подпрограмм (меток) придумывает программист. Он может придумать, например, название Start_1.

Главное, чтобы в командах переходов, это название было бы точно таким же.

Рабочая часть программы.

Рабочая часть программы начинается с подпрограммы START, которая, в свою очередь, начинается с подготовительных операций и заканчивается записью, в регистры общего назначения, констант, задающих время работы таймера.

Так как запись этих констант не требует никаких предварительных установок, то эту группу команд можно разместить, например, в начале ПП START или "врезать" ее между командами подготовительных операций (то, о чем говорилось ранее). Результат будет одним и тем же. В данном случае, я разместил эти группы команд так, как указано в тексте программы.

ПП START начинается с команды clrf IntCon.

Смысл этой команды заключается в следующем: вывод RB0 порта В задействован как вход. Одновременно, вывод PB0 является входом внешнего прерывания (INT).

К тому же, вывод RB6, по которому организуется прерывание по изменению уровня сигнала на выводах RB4...RB7, также задействован как вход.

О прерываниях разговор будет позже, а пока просто примите это к сведению.

89


Хотя в программе cus и не предусмотрен уход в прерывания, специалисты фирмы Microchip рекомендуют, в этом случае (и вообще, в случаях, когда задействованы выводы ПИКа, участвующие в организации прерываний, и когда хотя бы один из них, работает на вход) глобально запретить прерывания.

Для этого достаточно установить в 0 седьмой бит регистра IntCon (глобальный запрет прерываний), но чаще всего, сбрасывается в 0 весь байт регистра IntCon, что Вы и видите в тексте программы (это, как бы, "двойной запрет" прерываний, см. распечатку регистра

IntCon).

На первых порах, команду clrf IntCon можно всегда вставлять в начало программы, в которой не предусмотрен уход в прерывания (или предусмотрен, но позднее), особо не задумываясь, нужна она или нет.

Хуже от этого не будет, а "перестраховочка" не помешает. Следующая команда: clrwdt (сброс сторожевого таймера WDT).

Так как сторожевой таймер включен (см. биты конфигурации), то его, по ходу исполнения программы, нужно периодически сбрасывать.

Напоминаю, что сторожевой таймер представляет собой "немудреный" RC - одновибратор (ждущий мультивибратор) с перезапуском.

Если его периодически не перезапускать (не сбрасывать), то он закончит формирование импульса, и по заднему его фронту, произойдет сброс программы на начало, то есть, переход на первую команду ПП START.

Таким образом, если программа, по каким-то причинам, "зависнет", то WDT выведет ее из этого состояния.

В этом и заключается основной смысл его применения.

Так вот, рассматриваемая сейчас команда является первой из нескольких таких же команд, "разбросанных" по тексту программы, что вполне объяснимо, так как WDT нужно периодически сбрасывать, чтобы он не закончил формирование импульса.

Если программа работает нормально (не "зависает"), то WDT никогда не закончит формирование своего импульса, так как он будет периодически перезапускаться. Ниже по тексту программы, располагается группа из шести команд.

Это и есть основные команды подготовительных операций.

1.Выводы RB0 и RB6 должны работать на вход, а вывод RB2 должен работать на выход. Следовательно, речь идет о регистре TrisB.

Регистр TrisA "со счетов сбрасываем", так как выводы порта А не задействованы, и как именно они будут работать "по барабану".

2.Необходимо определиться с подтягивающими резисторами, предделителем, активными фронтами и тактовыми сигналами, то есть c содержимым регистра OptionR.

Оба этих регистра (TrisB и OptionR) расположены в 1-м банке (см. область оперативной памяти).

По умолчанию, программа (начиная с первой команды ПП START) начинает исполняться в 0-м банке, следовательно, прежде чем работать с содержимым регистров TrisB и OptionR, необходимо перейти в 1-й банк, что и делается при помощи первой команды из этой группы команд: bsf Status,RP0 (установка 1-го банка).

Напоминаю, что 5-му биту этого регистра, в "шапке" программы, присвоено название RP0 (то, о чем говорилось ранее), и поэтому в команде можно указать не номер бита, а более удобное для восприятия текста программы, его название.

Итак, переход в 1-й банк осуществлен.

Далее все очень просто: устанавливаем 0-й и 6-й биты этого регистра в 1 (работа "на вход"), а остальные в 0 ("работа на выход").

Собственно говоря, в ноль нужно установить только 2-й бит, но так как выводы RB1,3,4,5,7 не задействованы, и по этой причине, не имеет значения, как именно они будут работать, то установим их "всем скопом" в 0, и дело с концом.

Бинарное число, которое соответствует такой установке (0100 0001) переводим в более компактную форму.

В данном случае, число переведено из бинарной системы исчисления в десятичную (см. имеющуюся у Вас таблицу).

Получилось .65 (вспоминайте: точка перед числом признак десятичного числа). А можно оставить его в бинарной форме или перевести в 16-ричную.

90


Это "дело вкуса" программиста.

Данное число определяется (назначается) программистом, следовательно оно будет называться константой.

Запись, в регистр TrisB, числа .65 происходит в 2 приема, так как за один прием записать в него константу нельзя.

Сначала константа .65 записывается в аккумулятор (регистр W): movlw .65 (запись константы

.65 в регистр W), а затем копируется (после копирования, число .65 из регистра W не удаляется, а остается в нем), из регистра W, в регистр TrisB (movwf TrisB).

Итак, задействованные, в принципиальной схеме, выводы порта В, работают в соответствии с ранее сформулированным требованием.

Переходим к содержимому регистра OptionR. Сразу "выбраковываем" то, что не нужно.

Так как внешние тактовые сигналы в работе устройства не используются (внешние сигналы управления не являются тактовыми) и уходов в прерывания нет, то значения 4-го, 5-го и 6-го битов регистра OptionR могут быть любыми.

То есть, они не влияют на работу устройства и поэтому установим их, например, в 0 (а можно и в 1 или в любой комбинации).

Теперь работаем с битами, которые на что-то влияют.

Сначала нужно определиться: задействовать или нет предварительный делитель? Предделитель может быть включен либо перед таймером TMR0, либо после сторожевого таймера WDT.

Внешних тактовых сигналов у нас нет, значит и незачем включать предделитель перед TMR0. Остается WDT.

Давайте поподробнее с ним разберемся.

WDT (сторожевой таймер) сбрасывается командой clrwdt.

Строго говоря, вместо слова "сбрасывается", нужно применять слово "перезапускается", но так как по отношению к WDT, слово "сбрасывается" является стандартным, то его и буду применять.

Имейте это ввиду.

После инициализации ПИКа, по умолчанию (аппаратно), начинается формирование импульса

WDT.

Такой аппаратный запуск происходит только один раз (за одно включение питания), а далее, по ходу отработки программы, WDT (если он включен) нужно программно перезапускать. При каждом перезапуске, к сформированному ранее импульсу, проще говоря, добавляется "довесок/хвостик" продолжительностью 18 мс., и поэтому формирование импульса продолжается (не завершается).

"Примерно" потому, что стабильность временных характеристик управляемого RC-одновибратора с перезапуском (это основа WDT) оставляет желать лучшего. Разработчики ПИКов предлагают ориентироваться на 18 мс.

Если WDT работает без предделителя, то сбрасывать (перезапускать) его необходимо через промежутки времени менее чем 18 мс., то есть, достаточно часто.

Это не всегда бывает удобным из-за необходимости применения относительно большого количество команд clrwdt.

Если после WDT включить предделитель, то максимальный интервал времени перезапуска увеличится. Он будет кратен коэффициенту деления предделителя.

Например, если предделитель с максимальным коэффициентом деления (128) подключен к WDT, то команды clrwdt нужно располагать в тексте программы через промежутки времени меньшие чем 18х128=2304 мс. (2,3 сек.).

То есть, потребуется меньшее количество команд clrwdt, нежели в случае, когда предделитель не подключен к WDT.

Если программа "зависнет" (перезапуски WDT прекращаются), то в данном случае, примерно через 2,3 сек. после начала "зависания", произойдет аппаратный сброс программы на ее начало (исполнение программа начнется с ПП START).

"Не мудрствуя лукаво", применяю это на практике (можно задать и меньший Кдел. предделителя).

Итак, определились: подключаем предделитель, с коэффициентом деления 128, к WDT.

Для этого необходимо установить в 1 первые 4 бита (начиная с младшего) регистра

OptionR.

Остался один 7-й бит: включение/выключение подтягивающих резисторов порта В.

91