Ошибка

Средства разработки для PICMICRO

Категория: Электроприводы
Опубликовано 13.07.2011 07:52
Автор: Super User
Просмотров: 5399

Глава 27. Средства разработки для PICMICRO 101

При запуске симулятор MPSIM начинает искать файл «MPSIM.INI». Этот текстовый файл создается пользователем, и я использую его, чтобы задать все используемые в программе параметры. Ниже приведен пример созданного мной файла MPSIM.INI.

MPSIM File for PROG2 - Включение светодиода

Myke predko - 96.05.02

P 84 ; Использование микроконтроллера типа 16С84

SR X ; Представление данных 16-разрядном формате

ZR ; Установка регистров в нуль

RE ; Сброс времени выполнения программы и

; счетчика циклов

DWD ; Запрет использования сторожевого таймера wdt

V W,X,2 ; Вывести регистр W

AD F3,B,8 ; Вывести на экран содержимое регистра STATUS


AD F4,X,2 ; Вывести на экран содержимое регистра FSR

AD OPT.X.2 ; Вывести на экран содержимое регистра Option

AD FB,B,8 ; Вывести на экран содержимое регистра Intcon

AD F2,X,3 ; Вывести на экран содержимое регистра PCL

AD FA,X,3 ; Вывести на экран содержимое регистра PCLATH

AD F1,X,2 ; Вывести на экран содержимое регистра TMRO

AD ЮА,Х,2 ; Вывести на экран содержимое регистра TrisA

AD F5,X,2 ; Вывести на экран содержимое регистра Порта А

AD ЮВ,Х,2 ; Вывести на экран содержимое регистра TrisB

AD F6,X,2 ; Вывести на экран содержимое регистра Порта В
rs

sc 1 ; Установка тактовой частоты 1 Мгц
lo prog2
di О, О


В представленном файле указаны: тип микроконтроллера, система счисления данных по умолчанию, регистры, содержимое которых выводится на экран, рабочие параметры. Любая команда, которая вводится в программу MPSIM, может быть задана в файле MPSIM.INI, который определяет начальное состояние программы. При работе MPSIM создает файл MPSIM.JRN, в котором сохраняются все нажатия клавиш, введенные в процессе моделирования. Это может быть полезно при анализе того, что было сделано, и для устранения проблем. Более детально эти вопросы будут рассмотрены ниже.

В программе поддерживаются комментарии, которые даются после знака «;», но не допускается использование пустых строк. Если в файл MPSIM вводится пустая строка, то повторяется выполнение предыдущей команды. Это происходит из-за специфики пользовательского интерфейса в MPSIM, который повторяет последнюю команду при нажатии клавиши «Enter», посылающей символ «возврат каретки». Эта особенность очень полезна при по-шаговой отладке программы, но она вызывает сложности, когда вы определяете регистры, содержимое которых должно быть выведено на экран.

Еще несколько слов о настройке файла MPSIM.INI. Я стараюсь использовать один и тот же заголовок для всех файлов. Заголовок содержит спецификацию основных регистров, которые постоянно используются симулятором MPSIM. В их число входят регистры W, STATUS, OPTION, INTCON и TMRO. Я рассматриваю эти регистры как панель управления самолетом, на котором есть шесть основных приборов. При определении вида экрана для MPSIM я всегда вывожу одни и те же основные регистры в одном и том же формате.


В MPSIM используются следующие команд

АВ AD

Команда Параметры Комментарии

Прерывание текущей сессии. Список файлов не изменяется

Выводит содержимое регистра в окне «View» в указанном формате и заданной системе счисления: (radix):

X — Шестнадцатиричная В — Двоичная D - Десятичная

Установка точки останова по текущему или указанному адресу.

Установка точки останова, когда условие выполняется.

Операция Ор:

= Равно

> Больше чем

< Меньше чем

>= Больше или равно

<= Меньше или равно

!= Не равно

Удаление всех или указанной точки останова.

Продолжение выполнения программы с пропуском указанного количества следующих точек останова.

Задание частоты сигналов на определенном выводе с указанием количества циклов для состояния I и 0 (hi, low). Параметр «-» задает момент прекращения импульсов.

Вывод на экран всех активных точек останова. Очистка фрагмента памяти программ


Reg[, radix[, digits]]

B

[addr] Reg Op Value

ВС С

СkК

[addrjReg] [#break]

pin, {hi, low} |-

DB DE

addrl,addr2

Команда Параметры Комментарии

DI [addrl[,addr2j] Вывод на экран фрагмента памяти программ

DK #,{Pin,State} |- Определение комбинации клавиш «Alt-F#»

для подачи на соответствующий вывод состояния 1 («Н»), О («L»), перепада («Т») или импульса («Р»). Параметр «-» —запрещает все функции «Alt-F#».


DL Symbol Удаление символа.

DM [addr,addr2] Вывод фрагмента памяти программ в числен-

ном виде (не в виде команд)

DP Вывод всех исправлений программы

DR Вывод содержимого всех регистров.

DS Вывод таблицы символов

DV Reg Удаление из окна просмотра соответствую-

щего регистра

DW [E|D] Разрешение/запрещение функционирования

сторожевого таймера.

DX Вывод на экран текущих параметров трасси-

ровки. В режиме трассировки «Trace Mode» на экран выводится текущее состояние выполнения программы

Е [addr] Выполнение программы с текущего или ука-


занного адреса.

ЕЕ addr Модификация содержимого памяти EEPROM.

Реализуется только для микроконтроллеров,

содержащих память EEPROM

EL 0|1|2 Определяет, какие сообщения/предупрежде-

ния/ошибки будут выводится на экран при выполнении программы.

F Reg Вывод на экран содержимого регистра и воз-

можность его редактирования пользователем

FI fn,addr, Reg[,n] |- Ввод следующего или n-го значения величи-

ны из файла в регистр

FM addrl,addr2,value Заполнение неиспользуемого фрагмента про-

граммной памяти указанным значением.

RV MC|EM|MP|RC256| Определение рабочего режима

RC64|RC|OSC для микроконтроллеров семейства 17Схх.


GE fn Получение и выполнение командного файла.

Это способ загрузки командного файла .INI

Команда Параметры Комментарии

GO Запуск микроконтроллера и начало выпол-

нения программы.

GS Symbol, value, type Создание символа с соответствующим типом:

«F» —файл, «В» — битовое поле, «L» — метка, «К» — литерал.

Н Вывод окна помощи (Help).

IA addr Вставка ассемблерного кода, начиная с адреса

«add г»

IN addr,instruction Вставка ассемблерной инструкции по указан-

ному адресу.

IP [time | step] Ввод входных воздействий в соответствии со

значением параметра «step» в файле Stimulus.


IR ALL) RAM | SFR Рандомизация содержимого всех регистров

(ALL), файла регистров (RAM) или специальных регистров (SFR)

LJ Загрузка и выполнение текущего файла

«JRN». Является способом повторения команд, предварительно записанных в файл MPSIM.JRN

LO fn Загрузка в MPSIM файлов «.HEX» и «.COD»

LR fn Загрузка содержимого регистра

LS fn Загрузка внешнего символьного файла

М addr Вывод на экран содержимого памяти про-

грамм, начиная с адреса «addr», и возможность его редактирования. Ввод «Q» завершает команду, ввод «-» вызывает повторение предыдущей команды

NV Окно просмотра очищается.

О fn Вывод исправленного файла «.HEX» . (Хотя

я указываю эту команду, но не рекомендую ее использовать. Я не советую создавать объектные файлы, которые не сопровождаются исходным текстом).


Р device Выбор типа моделируемого микроконтроллера

Q Выход из MPSIM и запись команд в файл «JRN»

RA Восстановление таблицы исправлений, таб-

лицы символов и удаление точек останова.

RE Сброс времени выполнения и счетчика цик-

лов.

Команда Параметры Комментарии

RP Восстановление первоначального содержимого

памяти программ (до введения исправлений)

RS Сброс типа моделируемого микроконтроллера

SC length Определение времени цикла в микросекундах.

SE pin | port Вывод на экран состояния указанного вывода

или порта и возможность его изменения пользователем

SF addrl, addr2, reg Поиск первого использования указанного


регистра в заданном диапазоне памяти.

SI addrl,addr2,ins Поиск первого использования указанной ко-

манды в заданном диапазоне памяти.

SM addrl,addr2,ins Поиск первого использования команды в за-

данном диапазоне памяти и вывод сообщения на дисплей без символьной информации.

Как показано в приведенном выше примере файла MPSIM.INI, после определения содержимого экрана и установки рабочих параметров я загружаю специальный hex-файл и вывожу на экран первую команду.

Когда эти команды вводятся в сеансе работы с MPS1M, они заносятся в файл с именем MPSIM.JRN, который используется для создания расширенного файла MPSIM.INI. Данный файл можно использовать, чтобы помочь выявить определенные ошибки или обеспечить нормальное выполнение программы после исправления кода. Например, если в процессе отладки программы вы определили, ч го неправильный код начинается через пять команд после метки «Some_Label», то файл MPSIM.INI может быть скорректирован путем вырезания соответствующих строк из файла MPSIM.JRN и вставки их в конец файла MPSIM.INI. Данная процедура выполняется следующим образом.


В "Some_Label" ; Установка точки останова.

Е ; Выполнение программы до точки останова.

SS ; Выполнение пяти команд до проблемного участка.

SS

SS

SS

SS

Я пока не касался использования файлов внешних тестовых воздействий. Эти файлы используются MPSIM и симулятором, входящим в состав MPLAB, чтобы обеспечить подачу повторяющихся входных сигналов в процессе выполнения программы. При этом можно наблюдать, как микроконтроллер будет реагировать на эти сигналы. В качестве примера рассмотрим файл для тестирования программы, выполняющий опрос состояния клавиши

Файл воздействий состоит из множества состояний, для которых задается параметр STEP, определяющий число циклов, в течение которых поддерживается указанное состояние. Для расчета числа циклов, соответствующего определенному промежутку времени, я использую формулу:


Step (Количество циклов) = (Время Задержки) * (Тактовая Частота)/ 4.

В файле воздействий можно указать любой вывод микроконтроллера PICMicro, например, RAO задает вывод 0 порта А. Для обозначения вывода запуска(сброса) микроконтроллера используется символ «_MCLR». Для обозначения комментариев используется символ «!» (восклицательный знак). В файле воздействий могут использоваться пустые строки.

Хотя MPSIM является неплохим средством моделирования, он имеет, по моему мнению, один важный недостаток — отсутствие возможности представлять на экране все команды ассемблера в hex-файле. По этой причине я предпочитаю использовать симулятор, который содержится в среде MPLAB.

Среда MPLAB

MPLAB является одной из наилучших интегрированных сред разработки, имеющихся для любых микроконтроллеров. Эта среда, которая содержит редактор, ассемблер и симулятор, может работать совместно с программатором PICStart Plus и схемным эмулятором PICMaster, поставляемыми фирмой Microchip. Для разработки прикладных программ данная среда может также использовать языки высокого уровня. Среда MPLAB способна выполнять разработку, симуляцию, эмуляцию приложений и программирование любых микроконтроллеров семейства PICMicro, а это означает, что требуется только одна версия MPLAB для разработки всех приложений. Наиболее привлекательной особенностью среды MPLAB является то, что она свободно распространяется фирмой Microchip на ее Web-сайте.Копия MPLAB, которая была доступна на время написания книги, содержится на прилагаемом к ней CD-ROM.


Когда вы в первый раз увидите рабочий экран MPLAB (рис. 27.4), она, возможно, покажется вам слишком сложной. Однако после освоения работы со средой вы сможете задавать тот вид экрана, который вам нравится, и получите достаточный опыт для разработки приложений с ее помощью.

Рис. 27.4. Функциональные области на рабочем экране среды MPLAB

MPLAB предназначена для работы с операционными системами Windows 3.1 или Windows/95 фирмы Microsoft. Программное обеспечение — редактор, ассемблер, компилятор и симулятор, будут работать также с другими операционными системами, эмулирующими Windows, например, Windows/NT или SoftWin для компьютеров Macintosh. Однако периферийные аппаратные средства, например, программатор PICStart Plus и эмулятор PICMaster, не будут функционировать с этими системами.

Экран среды MPLAB делится на четыре части. Верхняя строка (1 на рис.27.4) содержит последовательность меню, используемых для задания рабочих параметров MPLAB. Область под этой строкой (2 на рис.27.4) - «панель инструментов», которая содержит кнопки, используемые для быстрого управления режимом работы MPLAB. Имеется три или четыре группы кнопок, которые могут быть выбраны, чтобы реализовать различные функции. Я обычно произвожу установку MPLAB с кнопками симулятора, которые идентифицируются красным и зеленым фонариками в левом углу полосы выбора.


Чтобы выбрать соответствующую группу кнопок, щелкайте самую левую кнопку на экране, пока не появится требуемый набор кнопок.

Центральная часть экрана (3 на рис. 27.4) содержит область, в которой располагаются рабочие окна, например окно редактирования, окно содержимого памяти, окно контроля останова или окно просмотра. Эта область может быть конфигурирована таким образом, чтобы обеспечить удобство работы пользователя. Как можно видеть на рис. 27.4, я предпочитаю полностью выводить на экран различные окна.

В нижней части экрана размещается строка (4 на рис. 27.4), которая показывает текущее состояние MPLAB. Информация о состоянии содержит номера строки и колонки, определяющие положение курсора в окне редактирования, тип микроконтроллера PICMicro, текущее содержимое (симулируемое или эмулируемое) программного счетчика, регистров W и STATUS.

Приложения, разрабатываемые с помощью MPLAB, называются «проектами». Для каждого проекта сохраняются исходные файлы, используемые приложением, и набор текущих состояний окон MPLAB. Создание проекта инициируется щелчком мыши на меню «Project» и последующим щелчком на команде «New Project» (эта последовательность действий обычно обозначается символической записью «Project» -> «New Project»). После этого появится окно ввода для задания имени проекта, с последующим указанием имен исходных файлов, связанных с данным проектом, которые должны быть ассемблированы или скомпилированы. Исходные файлы могут быть выведены в окно редактирования с помощью последовательных щелчков «File» -> «Source».


После загрузки исходный файл может редактироваться с помощью стандартных операций Windows. Например, для вырезания выделенной части текста используется комбинация клавиш «Ctrl-X». Можно использовать несколько окон редактирования одновременно. Редактор использует буфер обмена Windows и позволяет перемещать данные между файлами и приложениями.

Когда исходные файлы приложения созданы и отредактированы, вы можете произвести симуляцию (функциональное моделирование), после того как проведено их компилирование и ассемблирование. Процедуры компиляции и ассемблирования определены в меню «Project». Перед симуляцией следует обязательно убедиться, что тип используемого микроконтроллера задан правильно. Для этого производится последовательность щелчков «Options» -> «Development Mode», после чего выбирается необходимый тип микроконтроллера для режима «Simulator Mode». Вид окна для выбора режима симуляции «Simulator Mode» или режима редактирования «Editor Mode» показан на рис. 27.5.

С помощью этого окна вы можете выбрать, оставить ли симулятор активным или перейти в другой режим с помощью команды «Editor Mode». Я всегда оставляю симулятор активным за исключением случаев, когда требуется выполнить прямую модификацию содержимого памяти программ (это требуется при использовании микроконтроллеров семейства 12С5ххдля введения параметра калибровки) или произвести запись в память EEPROM для микроконтроллеров семейства F.


Рис. 27.5. Выбор типа микроконтроллера для симуляции в среде MPLAB

Хотя режим редактирования «Editor Mode» может быть использован для корректировки содержимого памяти программ микроконтроллера, я не советую делать это таким способом. Вместо этого для внесения исправлений в код программы я рекомендую создать копию текущего исходного файла, произвести его изменение и затем выполнить репрограммирование микроконтроллера. Я не люблю производить прямое исправление программного кода. Я встречался со многими случаями, когда пользователь производил корректировку программ с целью наладить работу устройства и после этого не мог вспомнить и восстановить те изменения, которые он внес в исходную программу для решения возникшей проблемы.

Имеется два вида экранных окон, используемых при отладке с помощью симулятора или эмулятора PICMaster. Первым является окно контроля останова «Stopwatch», которое используется для индикации текущего количества выполненных командных циклов (рис. 27.6). Критичные ко времени фрагменты прикладных программ могут контролироваться путем установки значения рабочей частоты «Target Frequency» и установки в нуль счетчика циклов в начале выполнения контролируемого программного кода.

Рис. 27.6. Окно контроля останова в среде MPLAB.


Другое окно, используемое при отладке приложений — это окно просмотра «Watch». Это специальный вид окна, в котором выводится текущее содержимое всех регистров, как аппаратных, так и файловых. Когда окно просмотра

создается с помощью последовательности щелчков «Windows» -> «New Watch Windows», вы получаете подсказку для выбора метки файловых регистров или указания адресов, которые должны контролироваться при выполнении симуляции. Вид окна просмотра выделен в правом нижнем углу на рис. 27.7.

Добавление переменных в конец списка, данного в окне просмотра, производится путем щелчка мыши на квадратике в верхнем левом углу окна или нажатием клавиши «Insert». Удаление переменных в окне просмотра осуществляется помещением курсора на требуемой строке и нажатием клавиши «Delete». Если требуется вывести на экран 16-битную переменную, то следует ввести символы «%%» после имени переменной. В противном случае, переменные или адреса представляются как 8-битные.

Среда MPLAB использует такой же формат представления файла воздействий, как и симулятор MPSIM. Этот файл определяет время подачи воздействий по количеству выполненных команд, которое выводится на экран в окне «Stopwatch». Установка этого окна в нуль приведет к тому, что подача воздействий, определенных в данном файле, начнется сначала.


При использовании симулятора или эмулятора PICMaster и выполнении пошаговой отладки текущая строка программного кода будет выделена. Если вы используете скомпилированную программу, то с помощью последовательности щелчков «Windows» -> «Program Memory» можно вывести на экран содержимое памяти программ, чтобы посмотреть, какой код сформирован компилятором в различных позициях, или получить файл листинга. Подсве-

ченная полоса появится на экране и позволит вам проследить, что происходит в программе.

Когда программирование производится на ассемблере, я очень редко вывожу на экран листинг файла или содержимое памяти программ. Действительно, нет каких-либо причин делать это, так как в файл листинга добавляются номера строк, адреса и коды операций, занимающие на экране место, которое можно использовать для размещения команд или комментариев. Память программ также содержит эту информацию, но она не выдает информацию в символической форме. Сказанное не значит, что не следует выводить эти файлы на экран при отладке прикладных программ, написанных на языках высокого уровня. В этом случае вы можете использовать данные файлы, чтобы посмотреть результат работы компилятора.

Точки останова и места прекращения выполнения программы («Run to Here») могут быть легко введены с помощью мыши. Сначала передвиньте курсор на строку, где вы хотите остановить выполнение программы. Это производится перемещением мыши на требуемую строку и нажатием на ее левую клавишу. Затем нажмите правую клавишу мыши и выберите тип останова. Варианты команд «Trigger» (Запуск) и «Trace» (Трассировка), которые вы увидите, используются при работе с эмулятором PICMaster, чтобы указать, какая операция будет производиться (например, трассировка исполняемого кода).


Отрицательной чертой симулятора MPLAB является низкая скорость работы. На моем компьютере с процессором Pentium — 133 МГц симулятор выполняет 300 команд в секунду. Это означает, что для моделирования задержки в 0,1 с на микроконтроллере PICMicro, работающем с тактовой частотой 4 МГц, симулятору потребуется пять с половиной минут. Чтобы избежать нежелательных затрат времени при моделировании задержек, я написал условный программный код, который включается по присутствию-отсутствию псевдо-метки, в качестве которой обычно используется слово «Debug». Например, если реализуется задержка, задаваемая 16-битным счетчиком, то я записываю ее в следующем виде:

goto $-1 decfsz

Counthi goto $-3

return

Когда это код скомпилирован, и присутствует псевдо-метка «Debug», то в счетчик в качестве переменных «Count» и «Counthi» загружается 1, что позволяет выполнить программу очень быстро (короткая задержка). В противном случае в качестве этих переменных загружаются их значения, задающие требуемую длительность задержки.


Рассматривая этот код, вы, возможно, удивитесь, почему я не исключаю фрагмент кода после директивы «if», а прогоняю программу с минимальным числом циклов задержки. Причина состоит в том, что я хочу иметь одинаковое число команд в отлаживаемом коде и получаемой прикладной программе. Различие в размерах программ может вызвать проблемы, если я захочу изменить работу программы.

Когда программа промоделирована симулятором и кажется работоспособной, я загружаю ее в микроконтроллер PICMicro с помощью программатора PICStart Plus (рис. 27.8). Этот прибор работает только под управлением среды MPLAB.

Рис.27.8. Система разработки с программатором PICStart Plus

Вид окна управления программатором PICStart Plus показан на рис. 27.9. Это окно используется для управления битами конфигурации в микроконтроллере PICMicro. Как было сказано выше, я настоятельно рекомендую выполнять установку битов конфигурации в вашей программе, используя директиву «_CONFIG», а не производить их ручную установку с помощью этого окна.

Рис. 27.9. Окно управления программатором PICStart Plus

Маленький совет: когда у вас все готово, чтобы запрограммировать PICMicro, запустите PICStart Plus, а затем выполняйте ассемблирование или компиляцию вашей программы. Когда ассемблирование-компиляция будет закончена, вы увидите, что конфигурационные флаги в окне программирования мерцают и принимают правильные значения. Таким образом, вы исключите возможность ошибки при программировании вашего устройства. Основная ошибка при освоении работы с PICMicro состоит в неправильной установке значений битов конфигурации. В этом случае микроконтроллер не выполняет прикладную программу, потому что сторожевой таймер постоянно производит перезапуск программы или неправильно выбран способ генерации тактовых сигналов.


Когда эмулятор PICMaster подключается к PICMicro с помощью интерфейсной платы, вставляемой в ISA-слот, он использует во многом такой же интерфейс, как симулятор MPLAB. Выбор эмулятора производится последовательностью щелчков мышью «Options» -> «Development Mode». Наряду со стандартными опциями эмулятор может быть использован для трассировки выполнения программы в соответствии с определенными условиями, которые задаются выбором команд «Trigger» (Запуск) или «Trace» (Трассировка).

Эмулятор PICMaster может использоваться для запуска внешних приборов, например, осциллографов или логических анализаторов, или для трассировки процесса выполнения команд. Это производится путем установки указания «Trace» на соответствующей точке программы. После окончания ее выполнения можно просмотреть память трассы («Trace Memory»), чтобы проанализировать ход реального выполнения программы.

В этом разделе я дал очень краткое объяснение основных возможностей MPLAB, а также PICStart Plus и PICMaster. Как и большинство хорошо написанных программ, MPLAB лучше изучать в процессе его практического освоения. При этом вы можете найти свои собственные приемы работы и наиболее удобные методы разработки и отладки программ. Используя данные здесь указания, вы сможете начать работу с MPLAB, с PICStart Plus и PICMaster. Я рекомендую вам распечатать pdf-файлы, которые содержат описание MPLAB и аппаратных средств разработки, и внимательно ознакомиться с ними перед началом использования этих средств.


Система KEELOQ

Система разработки KeeLoq фирмы Mirochip реализует алгоритм обеспечения безопасности, позволяющий аппаратно управлять микроконтроллером. Эта система служит надстройкой над остальными программными средствами, которые могут предоставляться другими фирмами. В системе защиты от угона моего автомобиля используются микроконтроллеры PICMicro с системой KeeLoq в карманном пульте отпирания-запирания и самом автомобиле. Пульт передает расположенному в автомобиле приемнику число, которое кажется случайным, а затем переходит к следующему псевдослучайному числу, которое будет послано в качестве сигнала отпирания-запирания в следующий раз.

Каждая комбинация пульт-приемник содержит уникальный кольцевой регистр сдвига, который формирует псевдослучайное число на основе специально заданного начального значения. Мне кажется удобным представить генератор псевдослучайных чисел в виде колеса с большим количеством точек, расположенных по окружности (рис. 27.10). Когда вы находитесь в любой точке окружности, то можете определить, какое число будет следующем при повороте колеса. Когда передатчик пульта посылает сигнал, приемник проверяет его значение в соответствии с положением своего «колеса» и обеспечивает срабатывание замка, если полученное число равно значению, указанному в следующей позиции «колеса». Если числа не совпадают, то приемник отмечает это место и переходит к следующей точке на «колесе». Если в следующий раз пульт пошлет число, которое совпадает со следующим числом на «колесе» приемника, то он выдаст сигнал срабатывания. Причина, по которой приемник снова проверяет поступающий сигнал, состоит в том, что сигнал передатчика может быть потерян или искажен приемником.


Данное описание системы KeeLoq является сильно упрощенным, и в нем, возможно, пропущены некоторые важные особенности ее работы. Но это не столь важно, потому что если вы хотите использовать технологию KeeLoq, то должны подписать соответствующее соглашение о конфиденциальности сведений с фирмой Microchip. Система KeeLoq достаточно сложна и способна обеспечить реализацию ряда дополнительных возможностей, например, посылку приемнику различных команд, которые не рассмотрены в этом раздел

Рис. 27.10. «Колесо» псевдослучайных чисел в системе KeeLoq

Набор FUZZY TECH

Чтобы помочь пользователям разрабатывать собственные прикладные программы на базе нечеткой логики, фирма Microchip создала набор средств Fuzzy Tech. Эти средства позволяют легко создавать в графическом виде различные приложения, использующие нечеткую логику. В набор входит простая демонстрационная плата, которая содержит резистивный нагреватель и датчик температуры (термистор). Эта плата может быть использована, чтобы разработать с применением нечеткой логики первую прикладную программу, обеспечивающую управление устройством, которое содержит потенциометр для установки требуемой температуры, датчик температуры и микроконтроллер, выдающий ШИМ-сигналы для нагревателя.


Fuzzy Tech создает выходной файл, совместимый с ассемблером MPASM, который может быть интегрирован в код прикладной программы. Возможность применения нечеткой логики ограничивается только доступными ресурсами микроконтроллера PICMicro.

Если вы ознакомитесь с описанием Fuzzy Tech, то увидите, что формирование правил должно производиться вручную, хотя их ввод в систему осуществляется с помощью графического интерфейса Fuzzy Tech, после чего система создает выходной программный код. Разработчик прикладной программы должен обеспечить интерфейс с внешними устройствами, а также выполнение любых других функций, которые должны быть реализованы микроконтроллером PICMicro.

Fuzzy Tech не превращает микроконтроллер PICMicro в устройство с нечеткой логикой, предназначенное для специальных приложений. Вместо этого данное средство обеспечивает создание программного кода, использующего принципы нечеткого логического управления для заданных входных воздействий, что расширяет возможности приложения.

глава

28


Система команд

микроконтроллеров

PICMicro

Краткое содержание

Команды арифметических операций с регистровой адресацией

Команды арифметических операций с непосредственной адресацией

Команды изменения последовательности выполнения программы

Команды управления микроконтроллером

Команды битовых операций

Команды старших моделей PIC (17C4X)

Расширение набора команд в ассемблере MPASM

Система команд ассемблера Parallax для PICMicro

В данной главе представлена, главным образом, система команд микроконтроллеров среднего уровня. Большинство из этих команд являются общими для различных семейств PICMicro, однако, существуют несколько команд, реализуемых только в архитектуре старших моделей серии 17С4Х. Описание этих команд, а также системы команд для ассемблера Parallax PICMicro, дано в конце главы. Приведенные здесь коды команд справедливы для микроконтроллеров среднего уровня. Если вы используете микроконтроллеры младших или старших моделей, то следует уточнить битовое представление команд, используя справочные данные фирмы Microchip для соответствующего микроконтроллера, хотя формат команд остается одинаковым для различных серий.


Команды арифметических операций с регистровой адресацией

Команды арифметических операций с регистровой адресацией, которые называются фирмой Microchip «байт-ориентированными операциями с регистрами файлов», используются в PICMicro мя пересылки данных между ре-гистрами и выполнения математических операций над их содержимым. Иначе говоря, эти команды осуществляют как пересылку данных внутри P/CMicro, так и арифметические операции над ними.

На первый взгляд набор команд PICMicro может показаться ограниченным — для микроконтроллеров младших и средних моделей их число составляет немного более 30. Однако, получив определенный опыт работы с ними, вы убедитесь, что он является достаточно мощным, и позволяет реализовать широкий набор операций. Частично такая гибкость достигается возможностью указания адреса размещения результата операции. Многие операции, реализация которых в других процессорах требует двух или более команд, выполняются в PICMicro одной командой.

В качестве еще одного преимущества системы команд можно отметить существование различных способов обращения к регистрам. Команды, описанные в данной главе, обеспечивают запись и считывание содержимого любого из регистров PICMicro. Адрес регистра указывается непосредственно в команде и содержит 7 битов. Поэтому доступ возможен только к данным, расположенным в пределах текущего банка, выбор которого осуществляется с помощью параметров RPO и RP1. Адресация данных также может также осуществляться с помощью индексного регистра FSR, посредством обращения к псевдорегистру INDF, расположенному по нулевому адресу. Особенностью микроконтроллеров PICMicro является использование при индексной адресации такого же формата, что и при прямой адресации.


Команда «movf» используется для установки флага нуля в зависимости от содержимого определенного регистра и может быть использована для его загрузки в регистр W (команда 28. 1 ). Данное описание команды может показаться несколько странным, однако в действительности оно точно соответствует выполняемой операции. Как и для других арифметических команд с регистровой адресацией, результат выполнения команды «movf» может сохраняться в регистре W.

Возникает вопрос, каким будет результат выполнения команды «movf» при записи результата операции в регистр, являющийся источником данных, то есть при выполнении команды «movf reg f». В данном случае производится загрузка содержимого регистра в АЛУ и сравнение его с нулем, после чего это содержимое помещается обратно в регистр. Таким образом, основной функцией команды «movf» является установка флага признака нуля. Второй (дополнительной) функцией этой команды является загрузка содержимого регистра-источника в регистр W.

Команда «movwf» используется для записи содержимого регистра W в указанный файловый регистр. Если в качестве этого регистра указывается INDF,то адрес регистра выбирается из регистра FSR. При выполнении данной команды флаги состояния не изменяются (команда 28.2).


Процессоры PICMicro имеют специальные команды для очистки регистров. Команда «clrf reg» записывает ноль в указанный регистр, a «clrw» - в регистр W.

При выполнении команд очистки регистров и команды «movf» необходимо помнить, что они также устанавливают соответствующее значение флага нуля. Это обстоятельство может вызвать проблемы, если вы хотите сохранить текущее состояние процессора для последующего выполнения программы. Поэтому рекомендуется использовать только флаг переноса для сохранения состояния процессора при переходе к другим программам, так как его изменение производится меньшим числом команд, чем изменение флага нуля (команды 28.3 и 28.4).

Наиболее часто используемой арифметической операцией является сложение. В микроконтроллерах PICMicro сложение производится обычным способом (команда 28.5). Эта операция может изменять все биты состояния. Флаг нуля устанавливается в I, если при выполнении логической операции «И» над полученным результатом и числом OxOFF получается ноль. Флаг переноса устанавливается в I, если результат превышает число OxOFF (255). Флаг переноса из младшей тетрады («ниббла») устанавливается в I, если сумма четырех младших битов превышает OxOF (15). Например, рассмотрим выполнение фрагмента кода:


movlw 10 ; Сложить ОхООА и ОхООА

movwf Reg

addwfReg ; Поместить результат в регистр W

В результате регистр W будет содержать число 20, в заданном регистре Reg сохранится число 10, флаги нуля и переноса будут сброшены в 0, а флаг межтетрадного переноса установится в 1..

Вычитание в PICMicro является операцией, с которой необходимо более подробно ознакомиться, прежде чем ее использовать (команда 28.6). При знакомстве с описанием команд вас, возможно, удивит операция «subwf». Следует отметить, что вместо вычитания PICMicro выполняет операцию сложения с отрмштелънъш числом. То есть вместо операции D = S - \V в действительности выполняется: D - S + (- W), где D (Destination) и S (Source) - содержимое регистра-приемника и регистра-источника, соответственно.

Отрицательное значение содержимого W в приведенном примере вычисляется по следующей формуле:

Negative = (Positive л OxOFF) + 1.

Таким образом, вычитание с учетом вышесказанного, выполняется по формуле:

D = S + (W Л OxOFF) + 1.


Эта формула помогает понять, что происходит при выполнении команды «subwf». С ее помощью можно также объяснить, как устанавливаются флаги переноса. При этом флаги переноса и межтетрадного переноса цифры могут изменяться не так, как вы ожидаете. Рассмотрим, например, что произойдет, если из 1 вычесть 2:

Source = 1

W = 2

Команда = subwf Source, w

Для объяснения этого примера используем приведенную выше формулу, в которую подставим заданные значения:

w = 1 + ( 2 Л OxOFF) + 1 Произведя вычисления, получим:

w = 1 + ( OxOFD ) + 1 w = 1 + OxOFE w = OxOFF

Это результат, который ожидался. Однако отметим, что при этом флаг переноса не устанавливается в 1, что можно было бы ожидать для обычных процессоров. При выполнении обычной команды вычитания флаг переноса для данного примера был бы установлен в 1 (обычно «перенос» в других процессорах является «заемом»).


Теперь для того же примера положим, что:

Source = 2 W = 1

Подставляя эти значения в формулу, получаем:

w = 2 + ( 1 Л OxOFF ) + 1 w = 2 + ( OxOFE ) + 1 w = 2 + OxOFF w = 0x0101

В регистр W реально будет записано число 0x001 (OxOlOl&OxOFF). Но отметим, что в этом случае при вычитании меньшего числа из большего флаг переноса (а, возможно, и флаг межтетрадного переноса) действительно устанавливается в 1! По этой причине после выполнения команд «subwf», «sublw» или прибавления отрицательного числа я рассматриваю флаг переноса как флаг положительного результата, а не флаг заема. Если вы просмотрите пояснения к командам, такое определение флага покажется вам более правильным.

Команды логических операций «andvf», «iorwf» и «xorwf» позволяют выполнять основные логические операции над соответствующими битами содержимого регистров (команды 28.7, 28.8, 28.9). Вероятно, с операциями «and» и «хог» читатель уже встречался, но фирма Microchip решила называть операцию «or» как «Включающее ИЛИ» («inclusive or»), обозначая ее «ior». Эта команда выполняется как обычная команда «or». Логическая операция производится над содержимым указанного регистра и регистра W. Флаг нуля в регистре STATUS устанавливается в I или сбрасывается в 0 в зависимости от значения полученного результата.


Для проверки содержимого некоторого регистра можно загрузить заданное число в регистр W, а затем выполнить операцию XOR («Исключающее ИЛИ») над содержимым проверяемого регистра и W. Если содержимое регистра равно числу, записанному в регистр W, то результат операции будет равен нулю, и флаг нуля установится в I. Например, переход к определенной точке программы при равенстве содержимого регистра PORTB числу ОхОА5 будет происходить при выполнении следующего фрагмента:

movlw OxOAS ; Получение проверяемого значения

xorwf PORTB, w ; Операция XOR с ожидаемым значением

btfsc STATUS, Z ; Получено совпадение?
goto PORTB_A5 ; Да, переход к выполнению определенного кода

Команда «comf» используется для инвертирования значения всех битов в регистре источника (команда 28.10). Следует заметить, что это команда не делает число отрицательным, то есть, не переводит его в дополнительный код. Отрицательное число N может быть получено из положительного Р следующим образом:

N = ( Р л OxOFF ) + 1


Выполнение команды «comf» аналогично логической операции XOR с числом OxOFF. Таким образом, для получения отрицательного значения содержимого регистра с помощью команды «comf», необходимо выполнить следующие операции:

comf Reg incf Reg

Если результат должен быть сохранен в регистре W без изменения содержимого регистра-источника, то выполняется следующий код:

comf Reg, w addlw 1

Эта последовательность команд может выполняться только микроконтроллерами PICMicro, реализующими команду «addlw», то есть средними и старшими моделями семейства.

Команда «swapf» меняет местами тетрады в регистре (команда 28.11). Как и в остальных командах, описанных в этом разделе, результат выполнения этой команды может быть сохранен как в регистре W, так и в регистре-источнике. Данная команда не меняет значения какого либо из из флагов состояния (переноса, межтетрадного переноса или нуля). Это свойство бывает полезно во многих случаях.

С точки зрения пересылки данных команда «swapf» может использоваться для достижения двух целей. Во-первых, она позволяет прикладной программе хранить две цифры в одном регистре, переставляя их в зависимости от того, какую из них вы хотите использовать. Во-вторых, эта команда реализует быстрый сдвиг содержимого регистра на четыре разряда. Сдвиг производится вправо или влево в зависимости от того, над какой из тетрад результата будет выполнена последующая логическая операция AND с числом OxOF.


Я часто использую команду «swapf», чтобы разделить байт на две тетрады для их последующего отображения на дисплее. Например, для вывода на печать байта в шестнадцатиричном формате можно использовать следующий код:

swapf Byte, w ; Получение старшей тетрады

addlw OxOOF

call PrintHex ; Печать старшей тетрады

movf Byte, w

andlw OxOOF

call PrintHex ; Печать младшей тетрады

Одной из наиболее полезных особенностей команды «swapf» является то, что содержимое регистра STATUS не изменяется при загрузке результата в регистр W. Это свойство обычно используется для восстановления содержимого контекстных регистров перед возвратом из прерывания.

Команды циклического сдвига полезны по ряду причин. Основной функцией этих команд является сдвиг содержимого регистра влево или вправо на один бит с записью на место младшего значащего бита значения флага переноса или, соответственно, установлением флага переноса в соответствии со значением старшего значащего бита (команды 28.12 и 28.13).


Команды циклического сдвига могут быть использованы для умножения и деления на число 2 в степени п. Это может быть проделано с 16-битными числами. Следующий пример демонстрирует, как умножить 16-битное число на 4.

bcf STATUS, С ; Сброс флага переноса перед сдвигом

rlf Reg, f ; Сдвиг переменной влево (умножение на 2)

rlf Reg + 1, f

bcf STATUS, С ; Повторение умножения на 2

rlf Reg, f

rlf Reg, f

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

Команды инкремента «incf» и декремента «decf» используются для изменения содержимого регистра на I (команды 28.14 и 28.15). После выполнения команд инкремента/декремента может измениться только флаг нуля. Вы можете предположить, что будет изменяться также флаг переноса, если результат превысит значение OxOFF при инкременте или окажется меньше 0 при декременте, однако этого не происходит. Поэтому инкремент/декремент 16-


битного числа не может быть выполнен обычным способом. Инкремент 16-битного числа может быть реализован следующим образом.

incf Reg, f ; Инкремент младшего байта

btfsc STATUS, z ; В результате получен 0? (Младший байт=256) incf Reg + 1, f ; Да, производим инкремент старшего байта

Так как флаг нуля устанавливается, если младший байт равен 0 (или 256), то мы можем определить, когда надо выполнить инкремент старшего байта в 16-битном числе.

Операция декремента несколько сложнее. Если вследствие декремента значение достигает нуля, то это не означает, что надо уменьшать старший байт. Следовательно, необходимо использовать команду, которая изменяла бы флаг переноса после декремента младшего байта, чтобы убедиться в необходимости декремента старшего байта. Поэтому лучше вычесть 1 из младшего байта, чем выполнять операцию декремента.

movlw 1 ; Загрузить 1 в регистр W

subwf Reg, f ; Вычесть 1 из младшего байта


btfss STATUS, С ; Флаг переноса установлен в 1?

decf Reg + 1 , f ; Нет - производим декремент старшего байта

Наряду с командами тестирования битов, которые описаны ниже, имеются две другие команды, осуществляющие переход к заданной команде. Это инкремент/декремент с пропуском команды при нулевом результате (команды 28.16 и 28.17). Эти две команды работают аналогично командам «incf» и «decf» в смысле обработки данных. Единица вычитается из содержимого регистра-источника или прибавляется к нему. Затем полученное значение может быть сохранено в регистре W или в регистре-источнике. Важное отличие от тех команд заключается в том, что при нулевом результате выполнения этих команд пропускается следующая за ней команда. Это означает, что команды «decfsz» и «incfsz» могут использоваться для организации программных циклов. Действительно, я могу сказать, что команда «decfsz» обычно служит для управления циклами. Ниже приведен пример кода, который показывает, как можно осуществить цикл из 37 повторений с очень малым увеличением объема программы.

movlw 37 ; Загрузить регистр-счетчик циклов

movwf LoopCounter
Loop ; Повторение каждой итерации в цикле


decfsz LoopCounter, f ; Декремент счетчика циклов
goto Loop ; Если результат не равен нулю, то повторить

; цикл ; Продолжение программы

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

Хотя команда «incfsz» используется не так часто, как «decfsz», она может служить для создания очень компактных временных циклов, чтобы получить 16-битные значения задержки.

Count Counthi

Loop incfsz incf

btfsc PORTn, Bitn

goto Loop movf Counthi, w subwf Count, w movwf Counthi

Возврат к временному циклу Инкремент младшего байта счетчика Инкремент старшего байта, если младший


не равен О Выход из цикла, если условие выполнено

Установка правильного значения старшего байта

При реализации петли («loop») содержимое младшего байта в счетчике циклов инкрементируется при каждом ее прохождении. Содержимое старшего байта инкрементируется, если результат инкремента младшего байта не равен нулю. Это означает, что содержимое старшего байта счетчика равно значению младшего байта минус значение старшего байта.

Этот маленький отрезок кода использует всего лишь 5 командных циклов (или 20 тактов синхронизации) для каждого прохождения петли и является минимальным программным фрагментом для формирования 16-битных временных задержек. Серьезным недостатком этого фрагмента является невозможность выхода из цикла при переполнении счетчика, то есть в случае, если условие выхода не выполняется в течение 64К. х 5 командных циклов. Несмотря на это данный фрагмент остается очень эффективным методом таймирования 16-битных событий с помощью всего лишь пяти команд.

Пара замечаний по поводу этих двух команд. Если вы используете при их выполнении регистры процессора, то предварительно следует убедиться, что их содержимое может принимать нулевое значение. В базовой серии Р1С16С5х регистр FSR содержит биты, которые никогда не обращаются в ноль (всегда равны 1). Эти регистры никогда не примут нулевого значения, то есть никогда не произойдет пропуск следующей команды. Кроме того, эти команды не влияют на значение флагов состояния (можно было бы ожидать изменения флага признака нуля). Это означает, что вы можете поставить команду «bsf STATUS, Z» после команды, следующей за incfsz/decfsz, как сделано в следующем примере:


decfz Count goto Loop

bsf

STATUS, Z

Декремент содержимого счетчика Возвращение в цикл, если содержимое

счетчика не равно О Установить флаг нуля для индикации конца

цикла

Команда: decfsz Register, [wlf]

Код команды:

00

1011

dfff

ffff

Выполнение: d <— f - 1

PC <(PC+1)&(dI0)

Пример:


37 Counter

movlw movwf Loop

Counter Loop

decfsz goto

«f» - Номер регистра «d» - Размещение результата: регистр W при d=0 регистр f при d=1

^ Входные данные и результат при d=0

Результат при d=1 •|» PC Inc

Число командных
циклов:
1/2

Тип микроконтроллеров:

средние модели

Loop 37x

Команды арифметических операций с непосредственной адресацией

Арифметические команды с непосредственной адресацией используют при выполнении операции явно заданные операнды. Эти операнды являются частью команд.


Команда «movlw» используется для записи константы в регистр W (команда 28.18). При выполнении этой команды содержимое регистра STATUS не изменяется.

Команда «addlw» прибавляет непосредственную заданную величину к содержимому регистра W (команда 28.19). Эта команда изменяет значение флагов нуля, переноса и межтетрадного переноса таким же образом, как команда «addwf».

Команда «sublw» вычитает содержимое регистра W из заданного значения константы Literal (команда 28.20). Это выглядит несколько странно. По моему мнению, выполнение данной команды, похожей на команду «subwf», имело бы больший смысл, если бы значение константы Literal вычитаюсь из содержимого регистра W. Однако архитектура PICMicro не поддерживает этого. Лучший способ пояснить эту команду — визуально представить ее выполнение. Выполняемая командой «sublw» операция имеет вид:

W = Literal - W,

вместо интуитивно более понятной операции W = W - Literal.

В отличие от «subwf», результат выполнения команды «sublw» можно представить в следующем виде:


W = Literal + (W * OxOFF) + 1.

Данная команда изменяет значения тех же флагов, что и команда «subwf». Так как я считаю, что операция, выполняемая командой «sublw», не соответствует интуитивным представлениям, то я пытаюсь избежать ее использования, за исключением случаев, когда производится изменение знака содержимого регистра W с помощью команды «sublw О»:

Sublw О ; Изменить знак содержимого регистра W

Существует один маленький трюк, который вы можете использовать, если вам необходимо вычесть явно заданное число. Он заключается в том, что производится сложение с числом, имеющим противоположный знак. Например, вы хотите написать код, реализующий следующую операцию:

W = W - 47. Это может быть сделано следующим образом:

movf Temp

movlw 47 subwf Temp, w

Сохранить содержимое W в промежуточном

регистре Temp


Загрузить в регистр W вычитаемое Вычесть его из первоначального содержимого W

Если вы используете микроконтроллеры серии Р1С16С5х, а не младшие модели PICMicro, то данную операцию можно реализовать с помощью команды «addlw»:

addlw 0-47 ; Прибавить отрицательное число

Если вы используете младшие модели микроконтроллеров из серии Р1С16Схх, которые не выполняют эту команду, то изменить знак содержимого регистра W можно с помощью интересного небольшого отрезка кода, представленного недавно в информационных материалах PICLIST:

addwf Reg, w ; W = W + Reg

subwf Reg, w ; W = Reg - W

; W = Reg - (W + Reg) (результат команды

; «addwf Reg, w»)

; W = Reg - W - Reg

; W = - W

Результатом выполнения этою кода будет изменение знака содержимого регистра W. Содержимое регистра Reg останется без изменения.


Команды addlw и sublw не реализуются в младших моделях микроконтроллеров (серия I6C5.X).

Команды логических операций «andlw», «iorlw», «xorlw» выполняют no-битно соответствующие операции над содержимым регистра W и непосредственно заданной константой Literal (команды 28.21, 28.22 и 28.23). Эти операции, как и логические операции с регистровой адресацией, устанавливают только флаг нуля в регистре STATUS к соответствии с результатом операции. Полученный результат сохраняется в регистре W. При выполнении этих команд запись результата в другой регистр не реализуется. Выполнение команды «iorlw 0» является хорошим способом определения равенства нулю содержимого регистра W. В зависимости от результата этой операции флаг нуля будет установлен в I или сброшен в 0.

Команда «retlw» используется для возврата из подпрограммы с установкой начальных условий в регистр W, а также для реализации таблиц, что описывается в другом месте. Перед возвращением из подпрограммы эта команда осуществляет загрузку непосредственно заданной величины в регистр W (команда 28.24). Данная команда может заменить две команды:

movlw return

Value


; Загрузить значение Value в регистр W

Команда «retlw» является единственным способом возврата из полпрограммы, возможным для младших моделей микроконтроллеров PICMicro (серия I6C5.X).

Команда: movlw Literal

Код команды:

11

0000

LLLL

LLLL

«L» - Константа

Путь данных

Число командных
циклов: 1

Тип микроконтроллеров:

средние модели


77 ; w = 77 в десятичной системе

Команда 28.18. Команда movlw

Выполнение: w <- Lit

w,

Пример:

movwf

literal в P/CMicro.

Команда: addlw Literal

Код команды:

11

111x

LLLL

LLLL

L» - Константа

Путь данных


Число командных
циклов: 1

Выполнение: w <-

Z <-С <-

DC Пример:

movf Reg, w addlw 7 addlw -13

w + Lit

(w + Lit) & OxOFF (w + Lit) > OxOFF <- ((w & OxOF) (Lit & OxOF)) > OxOF

w = Reg + 7

w = (Reg + 7) -13

Команда 28.19. Команда addlw literal в PICMicro. Команда: sublw Literal

Код команды:

Пример:

movf Reg, w sublw 0


; w = -Reg

11  110x LLLL LLLL

<L» - Константа

Путь данных

Число командных
циклов: 1

Тип микроконтроллеров:

средние модели

Примечание: Следует использовать команду «addlw -Lit» вместо «sublw» для вычитания отрицательной константы из содержимого регистра W

Команда 28.20. Команда sublw literal в PICMicro.

Команды управления программой

Перед использованием таких команд, как «goto» или «call», очень важно понять, как они работают. Если вы еще не сделали этого, то я советую вам вернуться назад и прочитать раздел о программном счетчике в главе «Архитектура процессора PICMicro». Команды «goto» и «call» при некоторых обстоятельствах могут выполняться необычным образом, в результате чего программный счетчик не будет давать правильное указание адреса. Причина необычных эффектов при выполнении команд «goto» и «call» состоит том, что все команды PICMicro имеют одинаковую длину, а разрядность адреса может превышать число битов, которое выделено для него в коде команды.


Обе инструкции, «goto» и «call», могут явно задавать адрес перехода в пределах определенной страницы, размер которой зависит от типа микроконтроллера: 256/512 адресов для младших моделей семейства, 2К адресов для микроконтроллеров среднего уровня и 8К адресов для старших моделей. Если адрес перехода выходит за границы страницы, то регистр PCLATH (или соответствующие биты регистра STATUS для младших моделей) должен содержать правильную информацию о новой странице.

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

movlw high Label

movwf PCLATH

goto Label Реализация межстраничного перехода

В данном отрезке кода в регистр PCLATH заносится номер новой страницы перед выполнением команды goto. Это приводит к загрузке в программный счетчик правильного полного значения адреса, когда выполняется команда «goto» (команда 28.25).

Команда «call» выполняется почти так же, как и «goto», за исключением того, что указатель на следующую команду сохраняется в стеке программного счетчика (команда 28.26).


В серии микроконтроллеров Р1С16С5х могут вызываться только подпрограммы, начало которых располагается в младших 256 адресах каждой 512-адресной страницы. Это является следствием того, что код команды не поддерживает полного 9-разрядного адреса страницы.

Существуют три различных способа возврата из подпрограммы для средних и старших моделей микроконтроллеров (как отмечалось выше, младшие модели серии 16С5х имеют только одну инструкцию возврата retlw). При каждом из этих способов значение адреса извлекается из вершины стека и загружается в программный счетчик. Эти адреса используются для возврата из подпрограмм или прерываний.

Следует отметить, что если в исходном тексте MPASM, написанном для младших моделей микроконтроллеров, присутствует команда «return», то реально будет использоваться команда «retlw 0», которая осуществляет загрузку нуля в аккумулятор (регистр W). При этом не выдается ошибка о неправиль-

ном использовании команды «return», которая отсутствует в архитектуре младших моделей PICMicro.

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


Команда «retfie» используется для возврата из прерывания (команда 28.28). Она реализуется аналогично команде «return» за исключением того, что при ее выполнении производится установка в I бита GIE в регистре управления прерываниями. Это позволяет после выполнения данной команды немедленно перейти к обработке прерываний, ожидающих своей очереди, что упрощает реализацию последовательной обработки различных запросов прерывания. В противном случае перед окончанием обработки потребовалась бы проверка наличия других запросов прерывания, и, в случае их поступления, переход к их обработке.

Label

Команда 28.25. Команда goto label в PICMicro.

Команда «sleep» служит для двух целей (команда 28.30). Первой из них является отключение микроконтроллера PICMicro после того, как он закончил выполнение программы. Микроконтроллер прекращает дальнейшую работу и перестает управлять другими устройствами в данной системе. Такое использование микроконтроллера предполагает, что он необходим только для решения определенной задачи в приложении, например, инициализация других устройств, а затем его работа в системе больше не потребуется.


Второй целью введения команды «sleep» является реализация в PICMicro режима ожидания какого-либо события. Известить микроконтроллер о таком событии можно одним из трех способов. Первым из них является подача сигнала запуска на вход _MCLR, что приведет к перезапуску процессора и началу выполнения программы с нулевого адреса. Вторым способом является поступление сигнала «пробуждения» микроконтроллера от сторожевого таймера. Третьим способом «пробуждения» является реализация некоторого внешнего события, например, прерывания. При любом способе «пробуждения» использование команды «sleep» для перевода микроконтроллера в режим ожидания позволяет избежать необходимости организации циклов ожидания и может упростить разработку программного обеспечения.

Выход микроконтроллера из режима ожидания («пробуждение») занимает, по меньшей мере, 1024 такта, прежде чем PICMicro возобновит выполнение программы. Это означает, что команду «sleep» нельзя использовать в тех случаях, когда требуется быстрая реакция микроконтроллера на внешнее событие.

Микроконтроллеры серии PICl6C5x имеют только одну страницу в регистровой памяти и поэтому не имеют возможности прямого доступа к регистрам, которые обычно расположены на странице I, например, к регистрам OPTION и TRIS. Чтобы обеспечить доступ к этим регистрам, в набор команд PICMicro включены команды «option» и «tris». Обе команды производит прямую запись содержимого регистра W в соответствующий регистр. Однако при этом вы не имеете возможность считывать обратно содержимое данных регистров.


Команда «option» выполняется достаточно просто (команда 28.31), однако команда «tris» требует некоторого обсуждения. Почти во всех микроконтроллерах PICMicro имеется более одного порта ввода-вывода, и вас, вероятно, интересует, как осуществляется доступ к их регистрам TRIS с помощью команды «tris» (команда 28.32). В команде «tris» используемый порт определяется путем указания численного значения от 5 до 7 или имени порта, например, PORTA. Чтобы записать содержимое регистра W в регистр TR1SB, следует вставить в программу следующую команду:

tris PORT В

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

Команда «пор» означает отсутствие операции (команда 28.33). Когда она выбирается процессором, он просто пропускает ее, не производя каких-либо изменений. Традиционно команда «пор» используется для двух целей. Первой является обеспечение синхронизации программного кода с временными характеристиками различных устройств системы.


Второй целью является резервирование свободного пространства для дальнейшей коррекции кода. Это обычно достигается путем замены команд «пор» необходимыми командами. Однако в микроконтроллерах PICMicro использовать команду «пор» таким образом нельзя. Это является следствием способа программирования памяти в PICMicro. В технологии EPROM и EEPROM, когда память готова для программирования, то есть является чистой, все ее биты установлены в I. В процессе программирования производится сброс определенных битов в 0 для создания необходимого программного кода. Проблема использования команды «пор» в данном случае заключается в том, что ее код состоит из одних нулей. Это означает, что ячейки памяти, занятые командой «пор» нельзя перепрограммировать, заменив ее другой командой. Однако существует способ резервирования памяти с целью добавления программного кода. Это означает, что код, загруженный в PICMicro, может быть модифицирован без необходимости стирания ранее записанного кода, что займет определенное время для микроконтроллеров с памятью EPROM, и последующей его перезаписи. Для этих целей применяется процедура, обратная получению необходимых команд из «пор». Например, вы можете поместить следующий код в вашу программу для микроконтроллера типа 16С84, чтобы обеспечить место для вставки нужного кода:


; Оставить место для введения четырех команд ; Команда, все биты равны 1

goto $ + 5

addlw OxOFF

addlw OxOFF

addlw OxOFF

addlw OxOFF

Чтобы ввести некоторый дополнительный программный код, необходимо все I в первой команде «goto» заменить на 0, превратив ее в команду «пор». Команда «addlw OxOFF» используется потому, что ее код состоит из одних единиц. Приведенная конструкция позволяет добавить в код четыре новых команды вместо «addlw OxOFF», не выполняя повторное ассемблирование вашей программы.

Как и в приведенном примере, все микроконтроллеры PICMicro среднего уровня используют команду «addlw OxOFF» для того, чтобы оставить биты по соответствующему адресу памяти программ установленными в I. В младших моделях PICMicro для достижения такого эффекта используется команда «xorlw OxOFF», а в старших моделях — команда «call OxlFFF».


Вследствие того, что код команды «пор» в PICMicro состоит из одних нулей, ее легко ввести в память программ вместо любой другой команды. Это позволяет удалять отдельные части программного кода, не прибегая к стиранию и репрог-раммированию всей памяти программ, что невозможно реализовать в случае использования однократно программируемых микроконтроллеров.

Выполнение: Число командных циклов: 1

Тип микроконтроллеров:
Пример:
средние модели

пор ; Пропустить один цикл

Команда 28.33. Команда пор в PICMicro.

Команды битовых операций

Установка и сброс отдельных битов производится командами «bsf» и «bcf», соответственно (команды 28.34 и 28.35). Их выполнение можно представить двумя способами.

При традиционном программировании имеются примеры выполнения операций AND или OR над некоторой величиной и константой, при которых изменяется значение только одного бита. Такие операции могут быть легко реализованы с помощью команд «bsf» и «bcf». Например, если вы xo^i-те произвести операцию AND над некоторой величиной и константой Ox07F, то обычно это делается следующим способом:


movlw Ox07F ; Загрузить значение константы для операции AND andwf Reg, f ; Выполнить AND

Однако в PICMicro это можно реализовать с помощью одной команды:

Реализация операции OR с помощью команды «bsf» («установить бит в 1») происходит аналогично. Любой доступный для записи бит в регистровой памяти может быть модифицирован таким способом. Использование этих команд может дать большое преимущество в ситуациях, когда вы хотите изменить только один бит в регистре, например, бит в регистре STATUS. Данные команды позволяют не только выполнить операцию за один цикл вместо двух, но и гарантируют, что ни один из остальных битов регистра не будет изменен.

Однако последнее утверждение не всегда справедливо. Как уже говорилось в главе «Архитектура процессора PICMicro», команды «bsf» или «bcf» могут давать неправильный результат при работе с портами ввода-вывода. Это проявляется в виде непредусмотренных изменений состояния выходных триггеров-защелок в регистре порта, которые могут иметь место после выполнения команды. (Напомним, что значение числа, считываемого из регистра порта, зависит от конфигурации его выводов в качестве входов или выходов данных).


В архитектуре PICMicro не используются команды условного перехода. Вместо этого имеются команды, позволяющие пропустить выполнение следующей команды программы (команды 28.36 и 28.37). Как было сказано выше, команды «decfsz» и «incfsz» могут использоваться для организации циклов. Здесь я хочу рассказать, как осуществляется управление выполнением программы.

Такое управление реализуется с помощью команд «btfsc» и «btfss», позволяющих пропустить выполнение следующей команды программы в зависимости от состояния определенного бита в заданном регистре. В традиционной архитектуре условиями для выполнения переходов и ветвлений являются значения битов (флагов) в регистре состояния. Такая возможность существует и в микроконтроллерах PICMicro. Для этого используются указанные выше команды пропуска по значению бита, которые выбирают соответствующий бит (флаг) из регистра STATUS. Например, если вы хотите выполнить переход по условию установки флага нуля в I (в микропроцессорах семейства Intel 80x86 данной операции соответствует команда «jz»), то можно использовать следующий код:

btfsc STATUS, z ; Пропустить следующую команду, если флаг

; нуля равен О


goto Label ; Флаг нуля установлен в 1 - перейти к

; заданному адресу

Подобный код можно привести для различных условных переходов: JC -переход, если флаг переноса установлен в I, JNZ — переход, если флаг нуля сброшен в 0, и других. Данные команды полезны во MHOIHX случаях: от проверки активности битов, используемых в качестве флагов прерываний, до определения знака числа путем проверки значения его старшего бита или проверки значения флагов в регистре STATUS. В конце этой главы приведен список расширений набора команд, которые введены в ассемблер MPASM, и даны соответствующие им эквиватенты команд PICMicro.

Команды старших моделей PICMicro (серия 17С4х)

Если вы применяете в своих разработках старшие модели PICMicro (серия 17Схх), то, вероятно, заметили, что несколько команд, используемых в этих микроконтроллерах, не были описаны выше. Набор команд для серии 17Схх насчитывает свыше 55 команд, в то время как младшие и средние модели PICMicro реализуют немногим более 30 команд.

Дополнительные команды серии 17Схх можно разбить на три типа: дополнительные арифметические команды, команды пересылки данных и команды чтения и записи табличных элементов. Я не хочу останавливаться на дополнительных арифметических командах, так как они выполняются аналогично командам, описанным выше. Они просто обеспечивают расширение функций (например, реализацию умножения 8x8 бит) для старших моделей PICMicro по сравнению с младшими и средними моделями этого семейства.


Команды пересылки данных заменяют команду «movf», используемую в других моделях PICMicro. Для пересылки данных между основными регистрами и банками регистровых файлов применяются команды «movfp» и «movpf» (команда 23.38.)

Описание команд, используемых в старших моделях для работы с таблицами, выходит за рамки этой книги. Если сказать кратко, то применение этих команд позволяет осуществлять доступ к большим таблицам, расположенным в памяти программ, устраняя, таким образом, барьер между пространством команд и пространством данных. Эта память программ обычно состоит из внешних микросхем памяти RAM, подключаемых к микроконтроллеру PICMicro, но это также могут быть устройства ввода-вывода, которые входят в общее адресное пространство памяти и реализуют передачу 8-разрядных данных. Во время выполнения такой передачи остальные 8 разрядов 16-разрядной шины не должны быть активными, чтобы избежать возникновения конфликтов на шине.

Чтобы произвести чтение или запись таблицы, необходимо сначала установить указатель на адрес таблицы. После этого производится передача 16-разрядных данных между микроконтроллером PICMicro, который использует специальные регистры-защелки для табличного обмена, и внешним устройством (команда 28.39).


В большинстве приложений микроконтроллеры серии 17С4х работают так же, как другие модели PICMicro, но их характеристики расширяют возможности применения и позволяют реализовать более сложные функции.

Расширения MPASM

Поддерживаемый фирмой Microchip ассемблер MPASM реализует ряд специальных команд, которые позволяют упростить написание программ для микроконтроллеров PICMicro. Ниже приведен список команд для младших и средних микроконтроллеров этого семейства.

Команда Описание команды Число Влияние Действительный код

циклов на флаги PICMicro

skpz

Пропуск команды, I если флаг Z=l

Нет

btfss STATUS, Z

subcf Reg, d

Декремент Reg, 2 если флаг C=l

Z

btfsc STATUS, С decf Reg, d

subdcf Reg, d

Декремент Reg, 2 если флаг DC=l

Z

btfsc STATUS, DC decf Reg, d

tstf Reg

Установка флага I Z=l, если содержимое Reg =0

Z

movf Reg


Набор команд Parallax PICMicro

Фирмой Parallax Inc. написан для микроконтроллеров PICMicro очень популярный ассемблер, который называется PASM. В нем используется язык ассемблера, команды которого очень похожи на команды микроконтроллера 18051. Данный ассемблер поддерживает также стандартный формат команд MPASM фирмы Microchip.

Часть команд этого ассемблера разработана специально для младших моделей PICMicro. Поэтому, если вы работаете с микроконтроллерами среднего уровня, то эти команды не должны использоваться.

Необходимо отметить, что многие из используемых в PASM мнемонических команд заменяются несколькими командами PICMicro и могут привести к неожиданным изменениям содержимого регистров STATUS и W. Например, для меня стало большой проблемой выяснить, какие операции выполняет расширенная команда MOV, которая позволяет выбирать многие из команд PICMicro (смотрите ниже).

Существенным преимуществом PASM является то, что многие его команды являются более ортогональными, то есть, предоставляют больше различных способов доступа к регистрам. Другое преимущество PASM состоит в том, что микроконтроллеры PICMicro становится более доступными для пользователей, которые освоили 18051. Некоторым пользователям команды PASM нравятся потому, что в них более ясно определяется размещение результата операции - обратно в файловый регистр или в регистр W. Набор команд для PICMicro, предлагаемый фирмой Parallax, во многом подобен расширенному набору команд фирмы Microchip, которая представлена выше. Как и расширенный набор команд Microchip, команды Parallax могут эффективно использоваться только в том случае, если пользователь их хорошо понимает и правильно применяет.


Ассемблер PASM доступен пользователям на Web-сайте фирмы Parallax. В приведенной ниже таблице команд PASM используются следующие обозначения:

# - непосредственно заданная константа; fr - файловый регистр; Farm — поле параметров, варианты которого приведены для данной команды в следующих строках таблицы.

Символом * в таблице отмечены команды, которые используются только

при работе с

младшими моделями

PICMicro

Команда

Описание команды

Число

Влияние на

Действительный

PASM

циклов

контекст

код PICMicro

CLR Parm

Установка парамет-

ра в 0

"W

W=0

I

Z

clrw

fr

fr=0

I

Z

clr fr

WDT

WDT=0

I

_TO,_PD

clrwdt

MOV Parm

Пересылка данных

"W, #"

W= #

I

Нет

movlw #

"W, fr'

W = fr

I

Z

movf fr, w

"W, /fr"

W = fr Л OxOFF

I

Z

comf fr, w

"W, fr-W"

W=fr+(W-OxOFF)+l

I

Z, C, DC

subwf fr, w

"W, ++fr"

W = fr + I

I

Z

incf fr, w

"W, — fr"

W = fr - I

I

Z

decf fr, w

"W, »fr"

W = fr » I

I

С

rrf fr, w

"W, «fr"

W = fr « I

I

С

rlf fr, w

"W, <>fr"

W = NibSwap fr

I

Нет

swapf fr, w

"fr, W"

fr = W

I

Нет

movwf fr, w

"IPort, W"

TRIS = W

I

Нет

tris Port

"IPort, #"

TRIS = #

2

W

movlw #

tris Port

"IPort, #"

TRIS = fr

2

W, Z

movf fr, w -Э

tris Port

"OPTION, W"

OPTION = W

I

Нет

option

"OPTION, #"

OPTION = #

2

W

movlw #

option

"OPTION, fr"

OPTION = fr

2

W, Z

movf fr, w

option

"fr, #"

fr = #

2

Нет

movlw #

movwf fr

"fr, fr2"

fr = fr2

2

Z

movf fr2, w

movwf fr


Команда PASM

Описание команды

Число Влияние на циклов контекст

Действительный код PICMicro

ADD Farm

Сложение двух чисел

"W, fr"

W = W + fr

I Z, С, DC

addwf

fr, w

"fr, W"

f г = W + fr

I Z, С, DC

addwf

fr, f

"fr, #"

fr = fr + #

2 W, Z, С, DC

movlw

#

addwf

fr, f

"fr, fr2"

fr = fr + fr2

2 W, Z, С, DC

movf

fr2, w

addwf

fr, f

SUB Parm "fr, VV"

Вычитание fr=fr+(WAOxOFF)+l

I Z, C, DC

subwf

fr, f

"fr, #"

fr=fr+(#AOxOFF)+l

2 W, Z, C, DC

movlw

n

subwf

fr, f

"fr, fr2"

fr=fr+(fr2AOxOFF)+l

2 W, Z, C, DC

movf

fr2, w

subwf

fr, f

AND Parm

Операция AND

"W, #"

W = W& #

I Z

andlw

#

"W, fr"

W = W & f r

1 Z

andwf

fr, w

"fr, W"

fr = W & fr

1 Z

andwf

fr, f

"fr, #"

fr = fr & #

2 W, Z

movlw

#

andwf

fr, f

"fr, fr2"

fr = fr & fr2

2 W, Z

movf

fr2, w

andwf

fr, f

OR Parm

Операция OR

"W, #"

W = W| #

1 Z

iorlw

#

"W, fr"

W = W | f r

1 Z

iorwf

fr, w

"fr, W

fr = W | f r

1 Z

iorwf

fr.f

"fr, #"

fr = fr | #

2 W, Z

movlw

»

iorwf

fr, f

"fr, fr2'

fr = fr | fr2

2 W, Z

movf

fr2, w

iorwf

fr, f

XOR Parm

Операция XOR

"W, #"

W = W Л #

I Z

xorlw

#

"W, fr'

W = W л fr

1 Z

xorwf

fr, w

"fr, W"

fr = W л fr

1 Z

xorwf

fr, f

"fr, #"

fr = fr л #

2 W, Z

movlw

n

xorwf

fr, f


Команда PASM

Описание команды

Число Влияние на циклов контекст

Действительный код PICMicro

"fr, fr2'

fr - fr л fr2

2 W, Z

movf fr2, w

xorwf fr, f

DEC Parm

Декремент содержи-

мого регистра

"fr"

fr = fr - 1

1 Z

decf fr, f

INC Parm

Инкремент содер-

жимого регистра

"fr"

fr = fr + i

1 Z

incf fr, f

NEG Parm

Изменение знака

(перевод в дополнит.

код)

"fr"

fr = 0 - fr

2 Z

comf fr, f

incf fr, f

NOT Parm

Инверсия битов

"W"

W = W Л OxOFF

1 Z

xorlw OxOFF

"r"

fr = fr Л OxOFF

1 Z

comf fr

TEST Parm

Тестирование пара-

метра на равенство

нулю

"W

Z = ( W == 0)

1 Z

iorlw OxOFF

"fr"

Z = ( fr == 0)

1 Z

movf fr

RR Parm

Сдвиг содержимого

регистра вправо

Т

fr = fr » 1

1 С

rrf *fr, f

RL Parm

Сдвиг содержимого

регистра влево

"fr"

fr = fr « 1

1 С

rif fr, f

SWAP Parm

Поменять местами

тетрады регистра

"fr"

fr = fr <> fr

1 Нет

swapf fr, f

CLRB fr, bit

fr.bit = 0

1 Нет

bcf fr, bit

SETB fr, bit

fr.bit = 1

1 Нет

bsf fr, bit

CLC

С = 0

1 Нет

bcf STATUS, С

STC

С = 1

1 Нет

bsf STATUS, С

CLZ

Z = 0

1 Нет

bcf STATUS, Z

STZ

Z = 1

1 Нет

bsf STATUS, Z


Команда PASM

Описание команды

Число циклов

Влияние на контекст

Действительный код PICMicro

ADDB fr, bit

fr = fr + bit

2

Z

btfsc fr, bit

incf fr, f

SUBB fr, bit

fr = fr - bit

2

Z

btfss fr, bit

decf fr, f

MOVB fr.b,

Переслать бит

4

Нет

btfss fr2, b2

fr2.b2

bcf fr, b

btfsc fr2, b2

bsf fr, b

MOVB ffb, /

Переслать инвер-

4

Нет

btfsc fr2, b2

fr2.b2

тированный бит

bcf fr, b

btfss fr2, b2

bsf fr, b

NOP

Отсутствие опера-

1

Нет

пор

ции

SLEEP

Переход в режим

N/A

_ТО, _PD

sleep

sleep

*LSET Addr

Установка номера

0-2

РАО, РА1

bcf/bsf STATUS,

страницы перед

РАО (установка но-

переходом

мера страницы в

регистре STATUS)

MOVSZ

Пропустить, если

Parm

результат равен 0

"W, ++fr"

W = f г + I

1/2

W

incfsz fr,w

"W, — fr"

W = f r - I

1/2

W

decfsz fr, b

INCSZ fr

w = f r + l; если

1/2

w

incfsz fr,f

Z=l, то пропуск

команды

DECSZ fr

W = fr - l; если

1/2

w

decfsz fr,f

Z=l, то пропуск

команды

SB fr, bit

Пропуск команды,

1/2

Нет

btfss fr, bit

если бит = 1

SNB fr, bit

Пропуск команды,

1/2

Нет

btfsc fr, bit

если бит = 0

SC

Пропуск команды,

1/2

Нет

btfss STATUS, С

если С = 1


Команда PASM

Описание команды

Число Влияние на Действительный циклов контекст PICMicro

код

CSNE fr, #

Пропуск команды,

3/4 W, С, DC, Z movlw

#

если fr != #

subwf

fr, w

btfsc

STATUS, Z

CSNE fr,fr2

Пропуск команды,

3/4 W, C, DC, Z movf

fr2, w

если fr != fr2

subwf

fr, w


jfe

btfsc

STATUS, Z

JMP Farm

Переход по адресу

* "addr9"

PC = 9-разрядный

2 Нет goto

addr9

адрес

"PC+W"

PC = PC + смеще-

2 Z, C, DC addwf

PCL, f

ние из W

«w

PC = W

2 Нет movwf

PCL

*CALL

Вызов подпрограм-

2 Нет call

addrS

addrS

мы

RET

Возврат из подпрог-

2 W retlw

0

раммы и W = 0

•SKIP

Пропуск следую-

2 Нет btfss

FSR, 7


щей команды

(бит 7 в регистре

FSR

всегда

равен О)

*LJMP addr

Выполнить LSET

2-5 РАО-РА2 bcf/bsf

STATUS,

PAx

перед JMP

goto

addr

*LCALL addr

Выполнить LSET

2-5 PAO-PA2 bcf/bsf

STATUS,

PAx

перед CALL

goto

addr

RETW

Возврат таблицы

2 w retlw

'S'

'String'

retlw

4'

retlw

'r'

retlw

'i'

retlw

'n'

retlw

'g'

IJNZ fr,

Инкремент/ переход

2/3 Нет incfsz

fr, f

addrQ

goto

addr9

DJNZ fr,

Декремент/ переход

2/3 Нет decfsz

fr,f

addr9

goto

addr9


Команда PASM

Описание команды

Число Влияние на Действительный код циклов контекст PICMicro

JB fr, bit,

Переход, если бит

2/3 Нет btfsc

fr, f

addr9

установлен в I

goto

addr9

JNB fr, bit,

Переход, если бит

2/3 Нет btfss

fr, f

addr9

сброшен в 0

goto

addr9

JC addr9

Переход, если С = I

2/3 Нет btfsc

STATUS, С

goto

addr9

JNC addr9

Переход, если С = 0

2/3 Нет btfss

STATUS, С

goto

addr9

JZ addr9

Переход, если Z =1

2/3 Нет btfsc

STATUS, Z

goto

addr9

JNZ addr9

Переход, если Z = 0

2/3 Нет btfss

STATUS, Z

CJA fr, #,

Переход по адресу

goto 4/5 W, C, DC, Z movlw

addr9

#

addr9

addr9, если fr > #

subwf

fr, w

btfss

STATUS, С

CJA fr, fr2,

Переход по адресу

goto 4/5 W, C, DC, Z movf

addr9

fr, w

addr9

addr9, если fr > fr2

subwf

fr2, w

btfss

STATUS, С

CJAE fr,

Переход по адресу

goto 4/5 W, C, DC, Z movlw

addr9

#

#, addr9

addr9, если fr >= #

subwf

fr, w

btfss

STATUS, С

CJAE fr,fr2, addr9

Переход по адресу addr9, если fr >=fr2

goto 4/5 W, C, DC, Z movf subwf

addr9

fr2, w fr, w*

btfsc

STATUS, С

CJB fr, #,

Переход по адресу

goto 4/5 W, C, DC, Z movlw

addr9

#

addr9

addr9, если fr < #

subwf

fr, w

btfss

STATUS, С

CJB fr, fr2, addr9

Переход по адресу addr9, если fr < fr2

goto 4/5 W, C, DC, Z movf subwf

addr9 fr2, w fr, w

btfss

STAT!' ,, С


Команда PASM

Описание команды Число Влияние на Действительный код циклов контекст PICMicro

goto

addr9

CJBE fr, #,

Переход по адресу 4/5

W, С, DC, Z movlw

#

addr9

addr9, если fr <= #

addwf

fr, w

btfss

STATUS,

С

goto

addr9

CJBE fr,fr2,

Переход по адресу 4/5

W, C, DC, Z movf

fr, w

addrQ

addr9, если fr <=f r2

subwf

fr2,w

btfsc

STATUS,

С

goto

addr9

CJE fr, #,

Переход по адресу 4/5

W, C, DC, Z movlw

#

addr9

addr9, если fr == #

subwf

fr, w

btfsc

STATUS,

Z

goto

addr9

CJE fr, fr2,

Переход по адресу 4/5

W, C, DC, Z movf

fr2, w

addr9

addr9, если fr== fr2

subwf

fr, w

btfsc

STATUS,

Z

goto

addr9

CJNE fr, #,

Переход по адресу 4/5

W, C, DC, Z movlw

#

addr9

addr9, если fr != #

subwf

fr, w

btfss

STATUS,

Z

goto

addr9

CJNE fr,fr2,

Переход по адресу 4/5

W, C, DC, Z movf

fr2, w

addr9

addr9, если fr != fr2

subwf

fr, w

btfss

STATUS,

Z

goto

addr9


глава

29

ПРИМЕРЫ ПРИМЕНЕНИЯ PICMICRO

Краткое содержание

Создание первого приложения на базе PICMicro

Цифровые часы/Термометр

Язык PICLite и приложение «Цифровые часы/Термометр»

Определение языка PICLITE

Начинающие разработчики чаше всего используют в своих устройствах микроконтроллеры PIC16F84, потому что они содержат память программ на основе EEPROM, которая позволяет быстро изменять программный код, не производя стирание памяти ультрафиолетовым светом. Этот микроконтроллер поставляется в 18-выводном DIP-корпусе и может быть запрограммирован с помощью множества различных программаторов. В PIC16F84 используется процессор, работающий с 14-разрядными командами и обеспечивающий поддержку прерываний. Этот микроконтроллер относится к разряду моделей PICMicro среднего уровня. Данная глава специально написана для того, чтобы показать, как функционируют PICMicro в различных приложениях.


Большая часть документации, содержащейся в книгах и имеющейся в сети Internet, представляет микроконтроллер PIC16C84, как наиболее доступный для начинающих разработчиков. Однако в 1997 году этот микроконтроллер был объявлен морально устаревшим, и его место занял 16F84. Эти два микроконтроллера практически идентичны, за исключением некоторых отличий в регистре конфигурации. Кроме того, 16F84 имеет больше файловых регистров. Программирование 16F84 и 16С84 производится идентичным образом.

Первое приложение PICMicro

Чтобы создать программный код, показывающий как PICMicro включается и выполняет и выполняет программу, была разработана схема, реализованная на базе прототипной системы (рис.29.1).

При разработке первой программы я хотел обеспечить мерцание одного из светодиодов с частотой, позволяющей наблюдать ее визуально. В этом случае для наблюдения за выходным сигналом не требуется осциллограф. Я хотел также, чтобы это мерцание производилось с помощью прерываний, инициируемых таймером. В конечной версии была реализована процедура опроса состояния кнопочного переключателя, которая выполнялась основной программой и не оказывала влияния на мерцание светодиода.


Частота тактового сигнала составляла I МГц, а это означает, что реальная частота выполнения команд равна 250 КГц. Максимально возможная задержка таймера TMRO с учетом того, что на его входе используется предделитель с коэффициентом деления 256, составляет 65536 командных циклов. Таким образом, светодиод должен мерцать с частотой порядка двух раз в секунду. С учетом вышесказанного была написана программа «Progl»:

title "PROG1 - Flash an LED." Первая программа для PIC контроллера. Предназначена для управления светодиодом.

myke predko 95.05.17

Примечания к аппаратной реализации: Контроллер PIC работает на частоте 1 МГц, которая задается с

помощью кристалла кварца и двух конденсаторов емкостью по 33 пФ. Вход запуска подключен к напряжению питания через резистор

номиналом 10К.

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


LIST P=16C84, R=DEC

errorlevel 0.-305

INCLUDE "c:\mplab\p16c84.inc"

; Общие определения

; Используемые регистры

CBLOCK ОхООС

_w, _status ; Сохраняемые контекстные регистры

Count

ENDC

PAGE

„CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON & _WDT_OFF

; Сторожевой таймер отключен ; Код для Progl

org 0 goto org 4

Mainline


Пропустить обработчик прерываний

Int

movwf _w

movf STATUS, w

movwf _status

bcf INTCON, TOIF

movlw 1

xorwf PORTB

movf _status, w

movwf STATUS

swapf _w

swapf _w, w
retfie

Обработчик прерываний Сохранить контекстные регистры


Сбросить флаг прерывания

Изменить состояние сигнала на выходе RBO

Восстановить содержимое контекстных регистров

Mainline

bsf

STATUS, RPO

bcf

TRISB & Ox07F, 0 ;

Инициализировать RBO

movlw

OxOD7 ;

Разрешить работу таймера

movwf

OPTIONLREG & Ox07F

bcf

STATUS, RPO

bcf

PORTB, 0

clrf

TMRO ;

Сбросить таймер

movlw

OxOAO ;

Разрешить обработку

;

прерываний таймера

movwf

INTCON

goto

$ ;

Бесконечный цикл


Если эту программу представить с помощью псевдокода, то она будет выглядеть следующим образом:

RBO = Output

Prescaler = TMRO Prescaler = 256 TMRO = 0

; Сконфигурировать RBO в ; качестве выхода

; Инициализировать таймер

TMRInterrupt = Enabled

While 1 == 1 ; Вечный цикл в основной программе

TMRInt

TMRInterrupt = Reset RBO = RBO Л 1

Return from Interrupt

; Прерывание таймера

; Изменить состояние сигнала ; на выходе

RBO = Output *RB4 = Output

Конечная версия первого приложения Prog2 построена на базе этого псевдокода, в котором была немного модифицирована основная программа Mainline. Псевдокод основной программы изменился следующим образом (символом * отмечены добавленные строки кода):


; Сконфигурировать RBO и RB4 в ; качестве выходов

Prescaler = TMRO ; Выполнить инициализацию таймера

Prescaler = 256 TMRO = О

TMRInterrupt = Enabled

While 1 == 1 if RB5 == 0 RB4 = 0 else RB4 = 1

; Вечный цикл в основной программе ; Кнопка нажата

Как вы можете видеть, единственная разница между Progl и Prog2 заключается в дополнительном коде, который используется для опроса состояния кнопочного переключателя (SW на рис.29.1) и управления светодиодом LED2 в зависимости от результата опроса.

title "PROG2 - Flash an LED and Show Button Input." Это модификация первой программы для PIC. Она предназначена для реализации мигания первого светодиода и опроса состояния кнопочного переключателя, если на вход поступает низкий уровень сигнала, то загорается второй светодиод.

myke predko 95.05.17

Примечания к аппаратной реализации: Контроллер PIC работает на частоте 1 МГц, которая задается с


помощью кристалла кварца и двух конденсаторов емкостью

по 33 пФ. Вход запуска подключен к напряжению питания через резистор

номиналом 10К. Вывод RBO является выходом и соединен со светодиодом через

резистор номиналом 220 Ом, другой вывод светодиода

подключен к шине питания. Вывод RB4 является выходом и соединен со светодиодом через

резистор номиналом 220 Ом, другой вывод светодиода

подключен к шине питания. Вывод RB5 соединен с резистором номиналом 10К, подключенным

к шине питания, и кнопочным переключателем, подключенным

к "земле".

LIST P=16C84, R=DEC

errorlevel 0.-305

INCLUDE "c:\mplab\p16c84.inc"

; Общие определения

; Используемые регистры CBLOCK ОхООС


_w, ^status ; Сохраняемые контекстные регистры

Count ENDC

PAGE

_CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON & _WDT_OFF

; Сторожевой таймер отключен ; Код для Prog2

org 0 goto Mainline org 4

Int movwf _w movf STATUS, w movwf _status

bcf INTCON, TOIF movlw 1 xorwf PORTB movf _status, w

movwf STATUS swapf _w swapf _ w, w retfie

Пропустить обработчик прерываний


Обработчик прерываний Сохранить контекстные регистры

; Сбросить флаг прерывания

; Изменить состояние сигнала на ; выходе ПВО

Восстановить содержимое контекстных регистров

Mainline

bsf STATUS, RPO

Инициализировать RBO и RB4

movlw OxOEE

movwf TRISB & Ox07F

movlw OxOD7

Разрешить работу таймера

movwf OPTION_REG & Ox07F
bcf STATUS, RPO

bcf PORTB, 0


TMRO

OxOAO INTCON

clrf

movlw movwf

Loop

btfsc PORTB, 5

goto SetBit

bcf PORTB, 4

goto Loop
SetBit

bsf PORTB, 4

; Сбросить таймер

; Разрешить обработку прерываний таймера

; Цикл опроса входного сигнала


; Проверить состояние входного сигнала ; Бит установлен

; Переключатель активен, включить LED ; Установить бит

goto

Loop

end

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

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

it ( ( PORTB & 0x010 ) == 0 ) PORTB = PORTB & OxODF; else " PORTB = PORTB I 0x020;

Однако этот код можно написать по-другому, без использования оператора IF, и он будет иметь вид:

PORTB = ( PORTB & OxCF ) I ( ( PORTB < < 1 ) & OxODF );


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

rlf PORTB, w ; Сдвинуть содержимое PORTB на 1

; и поместить в W

andlw 0x020 ; Выделить бит состояния переключателя SW

bcf PORTB, 5 ; Выключить светодиод

ния точности установки задержки таймера в 50000 циклов. В их реализации используется стандартная процедура вызова вложенных подпрограмм, обеспечивающая определенное число временных задержек. Программа, реализующая задержку, приведена ниже:

Dlay64

call Dlay32 Dlay32

DlayS Dlay4

call Dlay16 Dlay16

call DlayS


call Dlay4

return

Задержка в 64 командных цикла

Dlay4 является базовой процедурой, а ее выполнение занимает 4 цикла — два для выполнения команды «call» и два для выполнения команды «return». Эта задержка в четыре цикла используется подпрограммой DlayS при вызове Dlay4. Более длительные задержки получаются путем дальнейшего увеличения числа вызовов. Этот метод формирования ряда временных задержек длительностью в несколько командных циклов является достаточно эффективным и гарантирует, что таймер и предделитель будут сброшены в нужное время.

Если учесть, что стек имеет глубину, позволяющую выполнить только 8 вложенных подпрограмм, то существует опасность заполнения стека при вызове слишком большого количества вложенных процедур. Например, используя вышеприведенный метод, максимальная задержка, которая может быть получена в основной программе, составляет 512 циклов. Хотя этот метод выглядит довольно простым, необходимо все-таки убедиться в точности формируемых задержек, что может быть легко сделано с помощью симулятора MPLAB.


Так как я уже немного работал с PICMicro, но еще не работал с термометром фирмы Dallas Semiconductor, взаимодействие с которым осуществляется по однопроводному интерфейсу, я главным образом сосредоточил внимание на организации интерфейса с ЖК.И и с DS1820. В ходе их реализации возникли лишь небольшие проблемы. Исходный текст, который был написан при создании интерфейса с DSI820, находится в файле "ТНеппоЗ". Разработка программного интерфейса с этим устройством прошла довольно гладко.

После того, как реализация интерфейса с ЖКИ и термометром была завершена, я приступил к написанию программы для выполнения функций часов реального времени, используя прерывания таймера PICMicro, генерация которых осуществлялась через каждые 50000 циклов, как было показано выше. После запуска прикладной программы я сразу же заметил, что возникла проблема — часы довольно заметно отставали. Реально отставание составляло около 30 — 40 секунд в час. Анализируя эту проблему, я нашел, что ошибка часов может достигать 1,25%.

Причина ошибки заключалась в использованном способе реализации таймера и особенностях функционирования PICMicro. Разработанные часы реального времени и PICMicro оказались несовместимыми по трем причинам.


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

Вторая причина того, что разработанное приложение не обеспечивает абсолютной точности, возникает из-за поступления команд, выполняющихся за два цикла (например, «goto» или «call»). Если в процессе выполнения такой команды возникает запрос на прерывание, то появляется задержка длительностью в один цикл, чтобы завершить выполнение команды. Это увеличивает максимальную длительность отклика на прерывание еще на один цикл.

Последняя причина несовместимости заключается в том, что во время обмена PICMicro с DS1820 (при чтении или записи), обслуживание прерываний запрещено в целях обеспечения необходимых временных характеристик обмена. Если прерывание возникает в течение цикла чтения или записи информации в DS1820, то обработка запроса откладывается на некоторое время. Пытаясь устранить эту проблему, я поместил процедуру считывания температуры из DS1820 сразу же после процедуры перезапуска таймера. Это позволило несколько уменьшить ошибку, но ее величина по-прежнему составила несколько десятых долей процента. При этом величина ошибки будет различной в зависимости от времени поступления запроса прерывания.


Новая идея возникла, когда я начал разработки на базе микроконтроллеров семейства 68НС05. В некоторых моделях 68НС05 имеется 16-разрядный счетчик, функционирующий без какого-либо предделителя (его описание дается в главе, посвященной 68НС05). Взглянув на возникшую проблему после изучения 68НС05, я переделал программный код таким образом, чтобы таймер был похож на таймер 68НС05, и никогда не требовал перезагрузки. Этого удалось достичь путем установки предделителя в 256, в результате чего прерывания должны возникать через каждые 65536 командных циклов. При этом обработчик прерываний стал иметь следующий вид:

Int

movwf _w

movf STATUS, w

movwf „status

; Сохранить контекстные регистры

bcf INTCON, TOIF ; Сбросить флаг прерывания

incf FracS ; Добавить 64К к содержимому счетчика


movf „status, w ; Восстановить контекстные регистры

movwf STATUS

swapf _w

swapf _w, w

retfie

При переполнении таймера данный программный код осуществляет сброс флага прерывания и увеличивает на 64К содержимое 24-разрядного счетчика (регистры FracI - РгасЗ). Когда пройдет по меньшей мере секунда (то есть установится в I бит 2 в регистре РгасЗ, показывая, что обработчик прерывания был выполнен около четырех раз, и в 24-разрядном счетчике содержится, по меньшей мере, число 250000, что соответствует ЮОО тактов или одной секунде), в основном коде программы будет произведено вычитание 250000 из содержимого 24-разрядного счетчика и модифицировано состояние секундного счетчика.

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


После отладки вышеприведенного кода (тексты от «2Thermol» до «2Thermo4») я пришел к выводу, что все проблемы полностью решены, а ошибка теперь составила порядка 0,01%, чего и следовало ожидать с учетом погрешности кристалла, используемого в данной аппаратной реализации. Более того, новый код, выполняющий функции часов реального времени получился проще первоначального и не требовал того количества усилий для определения временных характеристик, которые были затрачены при реализации первого варианта.

Если вы посмотрите на исходный текст приложения, то заметите, что серия программ «Thermo» была написана на пару месяцев раньше серии «2Thermo». В реальной жизни очень редко дается возможность вернуться к старому приложению и взглянуть на него с другой стороны, как это было сделано здесь. Но данный опыт показывает, что изучение других микроконтроллеров может дать полезные идеи, которые в будущем могут быть использованы при разработке новых приложений.

Язык PICLite и приложение «Цифровые часыЯермометр»

Разработка компиляторов для PICMicro стала для меня настоящим хобби. Этот микроконтроллер является довольно интересным устройством с точки зрения написания компиляторов из-за характерных особенностей в архитектуре процессора. Я заинтересовался разработкой наилучшего языка для PICMicro, так как не считаю, что ассемблер является лучшим способом разработки приложений. Однако большинство языков высокого уровня не позволяют использо-


вать все преимущества этого микроконтроллера. Моей основной целью стало создание языка высокого уровня, который можно было бы использовать при написании программ для всех 8-разрядных микроконтроллеров.

При разработке компилятора для PICMicro следует обратить внимание на следующие моменты:

1. Возможность сохранения результата операции либо в регистре W, либо в

регистре-источнике.

2. Ограниченный объем памяти RAM (в каждом банке только по 100 байтов).

3. Ограниченные возможности индексирования.

4. Наличие регистра PCLATH и реализация переходов в пределах страницы,

а также возможность организации таблиц данных в памяти программ.

Прочитав это, вы, наверное, решили, что разработка компилятора для PICMicro более сложна, чем для других микроконтроллеров. Но точнее будет сказать, что она несколько отличается от разработки компиляторов для других устройств. Каждый микроконтроллер, представленный в данной книге, имеет свои особенности, которые делают написание компилятора для него сложным делом.


Первым написанным мной компилятором стал компилятор языка С для 16С84. После его создания, я пришел к выводу, что язык С не очень хорошо подходит для микроконтроллерных приложений. Этот язык оперирует большими значениями целых чисел, указателями и структурами данных, которые довольно сложно реализовать на базе скудных ресурсов микроконтроллера. Язык С также плохо подходит для реализации регистров, расположенных в памяти по определенным адресам, и обработчиков прерываний, начинающихся с определенного адреса. Позднее я пришел к выводу, что в общем случае к коду приложений, написанных на С, приходится добавлять большое количество ассемблерного кода, что не соответствует поставленной цели.

Моей следующей разработкой стал структурированный язык, обладающий возможностью включения в текст ассемблерного кода и назначения определенных адресов переменным и функциям. Он представлял собой улучшенный С-подобный язык, но по-прежнему сохранились проблемы с индексным указателем, особенно при работе с массивами переменных. Реально я имел сложности только с реализацией таблиц. Вышло так, что таблица переменных могла содержать только до 251 элемента одного типа. Мне очень понравился этот язык, но он мог работать только с микроконтроллерами 16С84. К тому времени мой опыт работы с PICMicro значительно вырос, и я начал использовать такие микроконтроллеры, как 16С73А, где имеются более одной страницы памяти программ и более одного банка файловых регистров.


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

PICLite является очень простым языком, предназначенным для программирования микроконтроллеров PICMicro среднего уровня, которые имеют 14-разрядное процессорное ядро с двумя банками регистров 0 и 1. На сегодняшний день выходным файлом является файл на языке ассемблера, компиляция которого может быть выполнена из командной строки PC-DOS. Если ассемблер сделан хорошо, то его запуск на выполнение может быть произведен из среды MPASM (версии 1.40 или выше). Команды ассемблера могут быть непосредственно включены в текст программы без использования специальных операторов или заголовков.

Этот язык проще, чем BASIC, но, как я считаю, он хорошо организован и оптимизирован. Исходные тексты могут быть любого размера и ограничены только наличием свободного пространства на вашем жестком диске. Реализована поддержка как 8-разрядных (байт) так и 16-разрядных (слово) переменных и массивов переменных, однако регистры, размещаемые по определенным адресам, могут быть только 8-разрядными. Для выражений присваивания я, по возможности, постарался сохранить соглашения языка С.


Осуществляется также поддержка прерываний PICMicro, а их реализация довольно проста. Если в конце основного кода поместить метку «int:», то это вызовет автоматическую вставку заголовка обработчика прерываний, а последующий код будет интерпретироваться как тело обработчика прерываний. В конце программы помещается оператор возврата из прерывания.

Этот язык был разработан в результате дискуссии, проводившейся на страницах PICLIST. Если вы имеете какие-либо соображения по поводу языка, пожалуйста, сообщите мне об этом тем же способом.

ОПРЕДЕЛЕНИЯ ЯЗЫКА PICLITE

Опции командной строки:

[D:] [Path] FileName[.Ext]

! /С

- Диск/Путь Ввод исходного файла

- Разрешение отладки (Не удалять файл .~tm)

- Отсутствие отклика (Не печатать результаты)

- Генерировать файлы MPLAB


Вызов осуществляется следующим образом: PICLite [D:] [Path] FileName[.Ext] [.][!] Выходными файлами являются:

FileName.lst

FileName.asm

FileName.~tm

Определения языка:

- Файл листинга

- Файл с ассемблерным текстом в формате MPASM

- Временный файл, необходимый для отладки

Адресные метки ( Упитывается верхний/нижний регистр клавиатуры):

Label {:} - Метка должна начинаться с первого столбца

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

- Использование знака ":" в конце метки необязатель

но, если в строке присутствует только метка, но


если в той же строке есть выражение, например,

"А = В + С", то знак ставить необходимо.

Объявление переменных/констант/регистров:

Label { [Array] } DalaType {= InitValue}

- Элементами массивов могут быть только байты или слова.

- InitValue может быть только байтом или словом, но не

массивом.

- Выражение должно начинаться с первого столбца.

Типы данных (Учитывается верхний/нижний регистр клавиатуры):

= value - Постоянная величина.

byte - Файловый регистр.

word - Два файловых регистра в формате Intel

@ addr @ addr - Заранее определенный аппаратный регистр.

- Для адресации к теневым регистрам Addr необходи


мо умножить на 2.

- Адреса большие или равные 0x02000 будут иметь

длину 14 бит.

- Адреса, большие или равные 0x02000 будут вычис

ляться в процессе компиляции и не могут быть

содержимым регистров или переменными.

Объявление меток:

Label { [Array] } DataType {= InitValue}

- Элементами массивов могут быть только байты или слова.

- InitValue может быть только байтом или словом.

- InitValue в массиве может быть строкой или одиночным

значением.

- Если это одиночное значение, то каждому элементу

массива будет присвоено это значение.


- Выражение должно начинаться с первого столбца.

Указание аппаратной спецификации PICMicro:

type PIC_Type - Спецификация PIC (например, "PICJType" = "16F84")

{s}memory Start:End - "s" ("shadow") означает сохранение содержимого

банка 0 в банке 1.

size - Число команд в памяти программ.

Наряду с возможностью помещения этих определений в исходном тексте, предусмотрена возможность использования файлов с расширением «.def>>, которые содержат необходимую информацию о применяемом микроконтроллере PICMicro.

В настоящее время поддерживаются следующие типы микроконтроллеров:

• 16F84

• 16С71

Форматы констант:

ОхО#### - Число в шестнадцатеричном формате.


ОЬО######## - Число в двоичном формате.

### - Число в десятичном формате.

'с' - Символ.

V - Символ возврата каретки (имеется поддержка стан-

дартных для языка С типов данных, вводимых символом Т).

"St", "ring" - Строки данных, конкатенация которых производится

символом «,»

Имеется возможность включения в текст программы ассемблерных команд в формате Microchip с учетом следующих особенностей:

- Поддерживаются все команды серии 16Схх, включая

"option" и "tris".

- "retfie" является допустимой командой, однако ее

использование не рекомендуется за исключением

случаев, когда надо правильно восстановить контек


стные регистры перед использованием "retfie".

- Если командам "goto" или "call" предшествуют выра

жения на языке PICLite, то перед их использованием

следует правильно установить регистр PCLATH.

- Если командам "goto" или "call" предшествуют выра

жения на языке ассемблера 16Схх, то производить

установку PCLATH не следует.

- Доступ к регистрам W и STATUS осуществляется

также, как и к другим регистрам.

- Команды языка могут изменять содержимое регист

ров STATUS, FSR и PCLATH, поэтому запись в эти

регистры следует производить осторожно.

- Примечание: Если в программе используется индекс

для работы с массивами, то содержимое FSR будет


изменяться.

- В командах ассемблера, которые реализуют доступ

к массивам переменных, могут использоваться

только постоянные указатели на элементы массива.

Допустимые операции языка: Выражения присваивания:

Label = Label I Constant { Operator Label I Constant ... } = Expression

Операторы (расположены в порядке уменьшения приоритета):

+ - сложение

- вычитание (либо унарный минус)

- умножение

/ - деление

// - возведение в степень

« - сдвиг влево

» - сдвиг вправо


& - поразрядная конъюнкция (AND)

I - поразрядная дизъюнкция (OR)

- поразрядное исключающее или (XOR)

= = - сравнить значения и вернуть 1, если они равны != - сравнить значения и вернуть 1, если они не равны

- сравнить значения и вернуть 1, если левое значение больше

>= - сравнить значения и вернуть 1, если левое значение больше

или равно

< - сравнить значения и вернуть 1, если левое значение меньше <= - сравнить значения и вернуть 1, если левое значение меньше

или равно

&& - конъюнкция (логическое AND) I I - дизъюнкция (логическое OR)

Реализация операций деления и возведения в степень взяты из руководства AN617 фирмы Microchip.

Использование скобок:

"(", ")" - Используются для определения порядка выполнения операторов. "[", "]" - Используются для обозначения индекса элемента массива.


Ключевые слова языка:

if Expression then Label - Если выражение !=0 то перейти к метке

Label.

; - Комментарий, все, что расположено

справа игнорируется, file [D:] [path]FileName.ext - Загрузить файл и вставить его в исходный

текст,

int: - Начало кода обработчика прерываний

- Все, что следует за "int:" является телом

обработчика прерываний.

- Обработчик прерываний позволяет осуще

ствлять переходы к основной программе

и вызывать подпрограммы.

Вход сигнала Reset "подтягивается" к напряжению питания через резистор номиналом 10К.

Выводы RBO-RB7 используются в качестве входов данных ЖКИ.


Сигнал на выводе RAO "подтягивается" к напряжению питания.

Перевод сигнала в низкое состояние приведет к переходу устройства в режим установки времени.

Вывод RA2 используется для управления 4-м выводом ЖКИ (сигнал R/S)

Вывод RA3 используется для управления 6-м выводом ЖКИ (сигнал Е)

Вывод RA4 используется для обмена с DS1820, причем сигнал на нем "подтягивается" к напряжению питания. 5-й вывод ЖКИ (R/W) подключен к земле.

file 16F84.DEF ; Вставить код для инициализации регистров 16F84 ; Определение переменных

i byte

j byte

count word

SP[ 9 ] byte ; Данные, возвращаемые DS1820

Frac word = 0 ; Текущая часть байта

FracHi byte = 0 ; Старший байт 24-разрядного счетчика

uDlay byte = ObOOOOOOOOl


Second byte = 0 ; Текущее время

Minutes byte = 0 ; Начальная установка соответствует 12:00

Hours byte = 0

E = 3 RS = 2

; Биты управления ЖКИ

DSBit = 4 ; Бит управления DS1820

; Основная программа для ThermoS

PORTA = 0x010 ; Установить высокое состояние на линии

; обмена с DS1820 PORTB = О

TRISA = 1 ; Вывод RAO служит входом сигнала от кнопки

TRISB = 0 ; Порт В служит для вывода данных

OPTION_REG = OXOD7 ; Разрешить работу таймера

; Код инициализации ЖКИ
call DlayS ; Ожидать 15 мс для установки,


; начального состояния ЖКИ call DlayS call DlayS

PORTB = 0x030

call SendlNS call DlayS

call SendlNS call SendlNS

PORTB = 0x038 call SendlNS POPRB = 0x010 call SendlNS PORTB = 0x001 call SendlNS POPRB = OxOOC call SendlNS

Установить ЖКИ на вывод двух строк по 8 символов

; Повторить несколько раз

; Использовать две строки ЖКИ

; Выключить дисплей

; Очистить память ЖКИ

; Разрешить работу дисплея

; Теперь послать сообщения в LCD

j = О


call SendlNS PORTB = ОхОСО call SendlNS

; Послать первое сообщение

; Переместить курсор на вторую строку

j = 1

call SendMSG

Послать второе сообщение

; Разрешить обработку прерываний

INTCON = ОХОАО

; Разрешить обслуживание прерываний ; от таймера

goto DispTime ; Показать время перед модификацией

; Цикл ожидания длительностью в 1 секунду Loop:

call DS_Reset i = ОхОСС call SendDS i = 0x044 call SendDS

call Dlay160 call Dlay160 call Dlay160

call DS_Reset i = OxOCC call SendDS i = OxOBE call SendDS call Dlay160 call GetDS SP[ 0 ] = i call Dlay160 call GetDS SP[ 1 ] = i call Dlay160 call GetDS SP[ 2 ] = i call GetDS SP[ 3 ] = i call GetDS SP[ 4 ] = i call GetDS SP[ 5 ] = i call GetDS SP[ 6 ] = i call GetDS SP[ 7 ] = i call GetDS SP[ 8 ] = i


call DS_Reset

PORTB = ОхОСб call SendlNS

if ( SP[ 1 ] & 1 ) SP[ 0 ] = 0 - SP[

Получить текущее значение температуры Послать команду Skip ROM

Выполнить преобразование температуры

Ожидать 500 мкс преобразования температуры

Теперь считать значение температуры

Считать блок памяти и контрольную сумму (CRC)

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

; Выполнить инициализацию DS1820 ; Ввести значение температуры

== 0 then DispTemp

О ] ; Температура отрицательна, преобразовать ее

PORTB = '-' call

SendCHAR


DispTemp SP[ 0 ] = SP[ 0 ] / 2;

Вывести на экран знак '-'

; Вывести значение температуры

; Вычислить значение температуры ; в градусах Цельсия

if SP[ 0 ] <= 99 then DispTens ; Не выводить, если темпера-

; тура выше 100С

PORTB = 'V call SendCHAR

DispTens if SP[ 0 ] <= 9 then DispOnes

; Вывести на экран значение десятков

PORTB = ( ( SP[ 0 ] / 10 ) / / 10 ) + 'О'

call SendCHAR ; Послать в ЖКИ число десятков

DispOnes PORTB = ( SP[ 0 ] / / 10 ) + 'О1 call SendCHAR

; Вывести на экран значение единиц

; Теперь определить, следует ли модифицировать значение времени
UPDTime ; Обновить значение времени


if ( FracHi & 0x04 ) == 0 then Loop ; Ничего не посыпать в ЖКИ

if ( PORTA & 1) != О then CheckTime ; Клавиша "Set" нажата?

Minutes = Minutes + uDlay - 1 ; Обновить число минут
Seconds = Seconds + 60 ; Обновить число секунд

uDlay = ( ( uDlay « 1 ) + 1 ) & Ox03F

goto IncTime ; Произвести увеличение значения времени

CheckTime: ; Сбросить значение переменной uDlay

uDlay = 1

IncTime: ; Определить, надо ли менять

;

PORTB = '-' call SendCHAR

DispTemp SP[ 0 ] = SP[ 0 ] / 2

; Вывести на экран знак '-'

; Вывести значение температуры


; Вычислить значение температуры ; в градусах Цельсия

if SP[ 0 ] <= 99 then DispTens ; Не выводить, если темпера-

; тура выше 100С

PORTB = 'V call SendCHAR

DispTens if SP[ 0 ] <= 9 then DispOnes

; Вывести на экран значение десятков

PORTB = ( ( SP[ 0 ] / 10 ) / / 10 ) + 'О'

call SendCHAR ; Послать в ЖКИ число десятков

DispOnes PORTB = ( SP[ 0 ] / / 10 ) + 'О1 call SendCHAR

; Вывести на экран значение единиц

; Теперь определить, следует ли модифицировать значение времени
UPDTime ; Обновить значение времени

if ( FracHi & 0x04 ) == 0 then Loop ; Ничего не посыпать в ЖКИ

if ( PORTA & 1) != О then CheckTime ; Клавиша "Set" нажата?


Minutes = Minutes + uDlay - 1 ; Обновить число минут
Seconds = Seconds + 60 ; Обновить число секунд

uDlay = ( ( uDlay « 1 ) + 1 ) & Ox03F

goto IncTime ; Произвести увеличение значения времени

CheckTime: ; Сбросить значение переменной uDlay

uDlay = 1

IncTime: ; Определить, надо ли менять отображение

; времени

if Frac >= 0x00090 then IntTimeSkip

FracHi = FracHi - 1 IntTimeSkip:

Frac = Frac - OxOD090 FracHi = FracHi - 3

Seconds = Seconds + 1

Выполнить перенос для FracHi

if Seconds < 60 then Loop ; He производить изменение значения


; минут

Seconds = О

Minutes = Minutes + 1

if Minutes < 60 then DispTime

Minutes = 0

Hours = Hours + 1

if Hours < 24 then DispTime

Hours = 0

DispTime: ;

PORTB = 0x086

Выполнить инкремент минут

Отобразить значение времени на экране ЖКИ

Отобразить текущее время путем вызова SendlNS

j = Hours


if j <= 12 then DispTimeHoursSkip j = j - 12

DispTimeHoursSkip

PORTB = ' '

if ( j < 10 ) && ( j != 0 ) then DispTimeNoTens

PORTB = '1' DispTimeNoTens: call SendChar

PORTB = ( j // 10 ) + ( 2 * ( j == 0 ) ) + '0' call SendChar

PORTB = ':' call SendChar

PORTB = ( Minutes / 10 ) + 'О' call SendChar

PORTB = ( Minutes // 10 ) + '0' call SendChar

j = 3

if Hours > 11 then DispTimePM

j = 2

DispTimePM: call SendMSG

Теперь отобразить минуты


goto Loop

; Завершить процедуру вывода времени на ; экран

; Подпрограммы для работы с DS1820

GetDS:

j = 8 GetDSLoop:

bcf PORTA, DSBit

bsf PORTA, DSBit пор

Чтение информации из DS1820

Для чтения значения выполнить цикл 8 раз

Переключить линию обмена с DS1820, чтобы посмотреть на его отклик

Команда введена для соответствия первоначальному коду чтения бита

bsf STATUS, С

btfss PORTA, DSBit ; Сигнал на линии еще в высоком состоянии?
bcf STATUS, С ; Нет, сохранить нулевое значение.


rrf i

cal Dlay4

call Dlay4 decfsz j goto GetDSLoop

; Добавить бит к содержимому счетчика

; Теперь ввести задержку в 8 циклов ; перед следующим запросом

return SendDS:

j = 8 SendDS_Loop:

; Послать команду DS1820

; Цикл посылки каждого бита

bcf PORTA, DSBit ; Переслать бит
btfsc i, 0 ; Переслать 1?

bsf PORTA, DSBit ; Да ..

rrf i

call Dlay4


call Dlay4

goto $ + 1

; Ввести задержку в 12 циклов при посылке О

bsf PORTA, DSBit ; Установить на линии высокое состояние

decfsz j goto SendDS_Loop

return DS_Reset bcf PORTA, DSBit

call Dlay160 call Dlay160 call Dlay160

Запуск DS1820

Сформировать задержку в 500 мкс.

bsf PORTA, DSBit ; Теперь установить на линии высокое состояние

call Dlay160

call Dlay160

call Dlay160

call Dlay160


call Dlay160

call Dlay160

return

Сформировать задержку длительностью не менее 1 мкс

: ; Послать команду в PORTB

bcf PORTA, RS ; Установить бит RS в 1

bsf PORTA, E ; Переключить на вывод данных

bcf PORTA, E

call Dlay160 ; Ожидать 160 мкс

if ( PORTB & OxOFC ) !+ 0 then SendlNSJEnd
call DlayS ; Ожидать выполнения команды в течение 5 мс.

SendlNS_End: return

; Завершить выполнение подпрограммы

SendCHAR: ; Переслать символ в PORTB


bsf PORTA, RS ; Установить бит RS в 1

bsf PORTA, E ; Переключить на вывод данных

bcf PORTA, E

call Dlay160 return SendMSG:

i = 0

; Ожидать 160 мкс.

; Послать сообщение на ЖКИ

; Задать нулевое смещение для обращения к •Table"

SendMSG_Loop1:

if j = = 0 then SendMSG_Loop2 ; Если j=0, то индекс i указы-

; вает на правильное ; сообщение call MsgTable

iorlw 0 ; Был возвращен О?

btfsc STATUS, Z

decf j ; Да, выполнить декремент j


i = i + 1

goto SendMSG_Loop1

; Повторить цикл для следующего символа

SendMSG_Loop2:

call MsgTable ; Получить текущий символ с индексом i movwf PORTB

i = i ; Переход к "call SendCHAR" в PICLite

call SendCHAR i = i + 1

call MsgTable ; Это конец сообщения?

iorlw О

btfss STATUS, Z goto SendMSG_Loop2

return MsgTable:

; Сообщение отправлено в ЖКИ ; Таблица сообщений

movlw Table » 8 ; Установить PCLATH перед изменением PCL movwf PCLATH

movf i, w ; Получить значение для i


ADDLW Table & OxOFF

btfsc STATUS, С ; Выполнить инкремент PCLATH, если надо

PCLATH movwf PCL

incf

; переход к элементу таблицы Table

Table:

dt " Time: ", О dt "Temp: ", 0 dt " ", 0 dt " PM", 0

Сообщения в коде ASCIIZ

; Подпрограммы задержки

Dlay4 ; Задержка в четыре цикла до возврата

return

Dlay160 count = 13 decfsz count goto $ - 1 return

DlayS

count = ( 256 * 2 ) + 160 decfsz count goto $ - 1 decfsz count + 1 goto $ - 3 return


Int: ; Обработчик прерывания

bcf INTCON, TOIF

FracHi = РгэсН! + 1 ; Инкремент счетчика до 64Кх4 мкс ; Конец процедуры обработки прерываний

; Конец программы TheimoS.PIC

Разработанный язык не соответствует уровню коммерческого продукта, однако, он довольно полезен и учитывает большее число особенностей микроконтроллеров PICMicro среднего уровня. Мне представляется удачной реализация интеграции команд ассемблера и текста, написанного на PICLite.

Одной из особенностей, которая мне на самом деле нравится в этом компиляторе, является использование индексного регистра FSR только для работы с массивами переменных. В написанных мной ранее компиляторах FSR служил также для организации стека выполняемых операций. Б PICLite для организации стека и указания на элементы массива вместо FSR используются отдельные файловые регистры.

Данный компилятор не является конечным продуктом. Ранее, когда я предполагал разработать коммерческую версию, я хотел добавить макропроцессор, позволяющий использовать структурированные конструкции, такие как «if» — «else» — «endif» и «while» — «endwhile». На самом деле, одной из причин, по которым макропроцессор не был добавлен, стало мое желание переписать компилятор (четвертая версия) таким образом, чтобы обеспечить вызов стандартных функций, а не только выполнение основной программы и обработку прерываний.


глава

30

ЗАКЛЮЧЕНИЕ ПО СЕМЕЙСТВУ PICMICRO

Краткое содержание

Информационная поддержка PICMicro

Web-сайты Информационные серверы

Из всех микроконтроллеров, представленных в данной книге мне, пожалуй, больше всех нравится PICMicro. Наиболее ироничные читатели могут сказать, что PICMicro мне нравится больше потому, что я написал первую книгу о PICMicro, которая занимает определенное место в моем сердце. На самом деле, у меня есть особые чувства к каждому из микроконтроллеров. Микропроцессор 6800 был первым, на котором я изучал программирование. После окончания университета я много работал с микроконтроллерами 8048 и 8051. Мне нравится семейство AVR, так как его архитектура хорошо приспособлена для написания программ на языке высокого уровня. Мне нравится также микроконтроллер Stamp, который стал для меня введением в PICMicro.


Причина, по которой мне нравится PICMicro, заключается в элегантности его архитектуры. По сравнению с другими микроконтроллерами PICMicro очень прост. Однако эта простота имеет свою цену, которая состоит в необходимости применения определенного стиля программирования для создания эффективных приложений. Из всех микроконтроллеров, представленных в данной книге, PIC является, пожалуй, наиболее сложным для начального освоения методики разработки программного обеспечения.

Простота его архитектуры отражается в наборе команд, который насчитывает всего 35 команд, каждая из которых выполняется за один командный цикл, за исключением тех случаев, когда производится загрузка нового содержимого программного счетчика.

Заслуживают высокой оценки две аппаратные особенности микроконтроллеров PICMicro — простота программирования моделей среднего уровня и наличие в серии 12С50х внутреннего осциллятора, который мне очень понравился. Я надеюсь, что такой осциллятор появится и в других моделях PICMicro.

Если сказать о том, что мне хотелось бы изменить в PICMicro, то список пожеланий будет очень мал. Я бы изменил две вещи (или хотел бы видеть их измененными). Во-первых, я бы уменьшил число циклов, требуемых для выполнения таких команд, как «goto», «call» и «return», а во-вторых, модифицировал бы аппаратную реализацию стека таким образом, чтобы обеспечить возможность создания для PICMicro систем реального времени.


Уменьшение числа циклов, затрачиваемых на выполнение команд «goto», «call», «return», позволило бы упростить анализ временных характеристик. Практически отпала бы необходимость использования команд «пор» и «goto $+1» для того, чтобы выполнение различных ветвей программы при выполнении различных условий происходило за одинаковое число циклов, независимо от выбранного пути.

Я считаю, что отсутствие доступа к пространству стека PICMicro стало самым большим препятствием в разработке ОСРВ, применение которых позволило бы повысить эффективность многих приложений. Когда я в первый раз задумался над этим вопросом, я начал искать методы чтения и модификации сохраненного в стеке содержимого программного счетчика, однако чем дальше я думал над этой проблемой, тем больше склонялся к мысли, что гораздо эффективнее иметь массив стеков. Идея состоит в том, что каждая задача имеет свой стек, выбор которого осуществляется ядром ОСРВ перед выполнением команды «retfie».

Наверное, архитектура PICMicro может показаться странной и довольно сложной для использования, особенно если вы хорошо знаете процессоры с архитектурой фон Неймана. Однако я думаю, что после получения некоторого опыта его применения вы придете к выводу, что микроконтроллеры PIC весьма эффективны, легко программируются и обеспечивают простой интерфейс с другими устройствами.


WEB сайт фирмы Microchip http://www. microchip, com Содержание:

Документация на PICMicro и информация по их применению.

Ответы на часто задаваемые вопросы

Документация на выпускаемые микросхемы памяти EEPROM фирмы

Microchip и ответы на часто задаваемые вопросы по ним.

Средства разработки для PICMicro (MPASM, MPSIM, MPLAB, и т.д.).

Информация об имеющихся в сети материалах.

Информация о дистрибьюторах продукции Microchip

Архив "GNUPIC"

h ttp ://www. execpc. com/ ~rdm iller/gnupic/

Содержание:

Свободно распространяемые ассемблеры, компиляторы и симуляторы

Страница Эрика Смита, содержащая проекты на базе PIC:

~eric/pic


Содержание:

Проекты Эрика Смита. «Маленькие хитрости». Различная информация Internet no PICMicro.

Англоязычная страница фирмы Ormix http://www. ormix. riga. Iv/eng/index. htm Содержание:

Различная информация по PICMicro.

Программное обеспечение для разработки и программирования.

Схемы программаторов.

Список внутрисхемных эмуляторов.

Отладочные платы и наборы разработчика.

Приложения.

Страница фирмы Fast Forward (администратор Энди Уорен)

. com/Silicon Valley/2499

Содержание:

Раздел «Встраиваемые системы» содержит список вопросов и ответов по PICMicro и другим микроконтроллерам.


Страница Давида Тэйта с материалами по микроконтроллерам PIC

~mbhstdj/piclinks.html

Содержание:

Программатор Давида Тэйта и программное обеспечение к нему. Информация о ресурсах PICMicro и продукции на его основе.

Страница фирмы DonTronics (администратор Дон Макензи)

http://www. dontronics.com

Содержание:

• Форум для разработчиков и программистов.

• Ссылки на информацию о PICMicro и продукции на его основе

Страница фирмы Parallax Inc.

 

Содержание:

• Продукты и информация по применению PICMicro.

• Базовая информация по Stamp и информация по применению.


• Информация для доступа к списку разработок на базе микроконтролле

ров PICMicro и Stamp, использующих программное обеспечение фирмы

Parallax.

Информационные серверы

PICLIST является информационным сервером в сети Internet, который занимается распространением почты для всех подписчиков. Для того чтобы подписаться на издание необходимо послать сообщение по e-mail: со словами «subscribe piclist» в первой строке сообщения (но не в поле темы).

Для того чтобы отказаться от подписки надо послать сообщение по e-mail: listser\' со словами «unsubscribe piclist» в первой строке сообщения.

Необходимо сделать одно замечание: так как информации очень много, то приходит большое количество сообщений (свыше IOO сообщений в день). Конечно, вместо регулярного чтения почты вы можете просматривать архив.

Архив информации находится по адресу:

http://www. iversofi. com/piclist/


Фирма Parallax также поддерживает информационный сервер для микроконтроллеров PICMicro и Stamp. Вы можете подписаться на получение информации, для чего надо зайти на сайт Parallax () и, пользуясь системой ссылок, сформировать запрос на подписку.

Microchip

Microchip Technology Inc.

2355 West Chandler Blvd.

Chandler, AZ 85224-6199

Tel: (602)782-7200

Fax: (602)899-9210