Методическое пособие 491
.pdfПсевдокомандой END программист дает ассемблеру указание об окончании трансляции.
В результате трансляции должна быть получена карта памяти программ, где каждой ячейке памяти поставлен в соответствие хранящийся в ней код.
Ниже приведен фрагмент рабочей программы, содержащий операнды с различным способом задания и псевдокоманду END:
MOVLW |
B'01010101' |
; Загрузить константу 01010101 |
|
|
; в регистр WREG |
MOVLW |
DATAPORT |
; Записать содержимое регистра |
; WREG в регистр DATAPORT (определенный ранее как порт В) |
||
GOTO |
$ ; Бесконечный цикл (вечный; цикл для |
; проверки программы в динамическом режиме). Выход только по преры-
ванию. |
|
END |
; Конец трансляции и окончание |
; программы |
|
|
3.4. Структура рабочей программы |
Рабочая программа для ОMK PIC 16/17 состоит из трех основных секций:
1)секция заголовка;
2)рабочая секция;
3)секция окончания.
В секции заголовка определяются логические имена для всех импользуемых в программе ресурсов: портов, битовых и байтовых переменных, регистров. Это начальная часть исходной программы до строки с выражением ORG 0 (для PIC 16С84). Для других типов микроконтроллеров семейств PIC 16/17 адрес начала следующей секции (сегмента) рабочей программы может быть другим.
29
Рабочая секция программы начинается с выражения ORG 0 (для
PIC 16С84), которое является указателем для Ассемблера о том, что код следующий за этим выражением начинается с нулевого адреса памяти программ. Пример этого фрагмента рабочей программы для
PIC 16С84 приведен ниже:
;Рабочая секция
;Начало исполняемой части рабочей программы
ORG 0H
;Следующая команда будет расположена в памяти программ по
;адресу 0h
GOTO
BEGIN
; Первая команда, которая будет выполнена процессором
ORG 100h
;Следующая команда будет расположена по адресу 100h BEGIN
;Инициализация микроконтроллера
;(Конфигурация портов ввода/вывода, TMRO, WDT и т.п.)
Секция окончания в простейшем случае содержит только псевдокоманду END.
3.5. Пример программы на PIC16C84
Теперь перейдем непосредственно к написанию программы на ассемблере. В качестве примера будет создана и подробно разобрана короткая программа.
Начнем с описания базового кода, который будет использован в примере. Написание программы для PIC контроллера как уже было сказано начинается с создания секции заголовка (весь код до строки с
30
выражением ORG 0), в которой учитываются особенности ее дальнейшего применения. Обычно в секции заголовка определяются логические имена для всех используемых в проекте ресурсов – портов, битовых и байтовых переменных и регистров.
Для того чтобы поставить в соответствие логическому имени,
какое либо числовое значение используется директива определения константы ассемблера EQU. Эту директиву применяют в секции заголовка, она имеет следующий синтаксис: <имя> EQU <значение>.
Для того чтобы обращаться к регистрам общего и специального назначения было легче, целесообразно в секции заголовка имя регистра ставить в соответствие его адресу. Как это сделано в ниже приведенном примере.
В секции заголовка нашего примера будут заданы значения слов инициализации для портов ввода/вывода. Фактически слово инициализации – это константа при помощи которой мы установим разряды порта на выход.
Ниже приведен пример секции инициализации.
; Секция заголовка
;
; описание операционных регистров
TMR0 |
EQU |
01h |
PC |
EQU |
02h |
STATUS |
EQU |
03h |
FSR |
EQU |
04h |
; регистры ввода/вывода |
||
CNTRLPORTEQU |
05h |
|
DATAPORT EQU |
06h |
|
; ячейки ОЗУ |
|
|
SCRATCH |
EQU |
0Ch |
DIGIT |
EQU |
0Dh |
; биты регистра STATUS
31
C |
|
EQU |
0h |
DC |
EQU |
1h |
|
Z |
|
EQU |
2h |
PD |
EQU |
3h |
|
TO |
EQU |
4h |
|
RP |
EQU |
5h |
|
; управляющие регистры |
|
||
TRISA |
EQU |
85h |
|
TRISB |
EQU |
86h |
|
; слова инициализации для портов ввода/вывода
INITA |
EQU |
B'00000000' |
INITB |
EQU |
B'00000000' |
Разберем подробно каждую строку кода. Во-первых, все строки,
начинающиеся со знака ";", воспринимаются ассемблером как комментарии. Перейдем к выражению TMR0. Эта строка дает команду ассемблеру, каждый раз, когда встретится слово TMR0
заменить его на значение 01h (01 шестнадцатеричное). Таким образом, символьному имени TMR0 было присвоено значение 1h. Как видно из табл. 5, регистр TMR0 действительно имеет адрес 1h.
Можно использовать 01h каждый раз, когда есть необходимость адресовать регистр TMR0, но это неудобно, поскольку нужно будете все время помнить, что означает 01h. Кроме того, могут существовать и данные, равные 01h. Использование символьных имен устраняет двусмысленность и позволяет облегчить чтение исходного текста.
В секции заголовка примера также можно видеть выражения для определения регистров PC, STATUS и FSR. Имя PC соответствует регистру с адресом 02h, имя STATUS соответствует регистру с адресом 03h, имя FSR – регистру с адресом 04h и так далее.
Аналогично заданы имена для портов ввода/вывода, CNTRLPORT
(05h) и DATAPORT (06h).
32
Ячейки ОЗУ также могут иметь имена. В примере были выбраны имена "SCRATCH" для ячейки с адресом 0Ch и "DIGIT" для ячейки с адресом 0Dh.
Можно определять имена и потом не использовать их. В этом нет ошибки, работа ассемблера как раз и заключается в проверке текста на соблюдение всех правил.
Можно именовать не только регистры, но и отдельные биты внутри регистров. Обратите внимание на секцию, задающую регистр
STATUS. Символу С присвоено значение 0h, поскольку C или
CARRY, это нулевой бит слова состояния STATUS.
Теперь стало ясно, как описываются регистры, и мы можем перейти к исполняемому коду. Перед тем, как начать исполняемый код, нужно задать директиву ORG, устанавливающую адрес программы.
ORG 0 – это указатель для ассемблера, что код, следующий за этим выражением, начинается с нулевого адреса ПЗУ. Директива
ORG используется для размещения сегментов кода по различным адресам в пределах размеров ПЗУ. Еще одно выражение ORG
находится перед меткой BEGIN, имеющей адрес 100h, как задано выражением ORG 100h.
Исполняемый код должен заканчиваться директивой END,
означающей, что за этой директивой отсутствуют исполняемые команды.
;Рабочая секция
;начало исполняемого кода
ORG 0 GOTO BEGIN
ORG 100h BEGIN
33
; Инициализация порта А |
|
|
BCF |
STATUS,RP ; Выбор банка 0 |
|
CLRF |
CNTRLPORT; Очистить регистр |
|
MOVLW INITA |
; Загрузить B'00000000' в регистр WREG |
|
BSF |
STATUS,RP ; Выбор банка 1 |
|
MOVWF TRISA |
; Все разряды порта A установить как выходы |
|
; Инициализация порта В |
|
|
BCF |
STATUS,RP ; Выбор банка 0 |
|
CLRF |
DATAPORT ; Очистить регистр DATAPORT |
|
MOVLW INITB |
; Загрузить B'00000000' в регистр WREG |
|
BSF |
STATUS,RP ; Выбор банка 1 |
|
MOVWF TRISB |
; Все разряды порта В установить как выходы |
|
; |
|
|
BCF |
STATUS,RP ; Выбор банка 0 |
|
; |
|
|
;Здесь будет расположена основная программа
;
;
END
При включении питания PIC16С84 переходит на адрес 000h.
Первая инструкция, которая будет выполнена процессором, это команда GOTO BEGIN, она передаст управление на адрес 100h и
дальнейшая работа продолжится с этого адреса. BEGIN – это выбираемое пользователем имя метки (метки всегда должны начинаться с первой позиции строки), которое ассемблер использует в качестве адресной ссылки. В процессе работы ассемблер определяет расположение метки BEGIN и запоминает, что если это имя будет встречено еще раз, вместо него будет подставлен адрес метки.
Команды CALL и GOTO используют метки для ссылок в исходном тексте.
Теперь рассмотрим команды, используемые для инициализации
34
портов. Команда MOVLW INITA загружает в рабочий регистр W
значение, присвоенное имени INITA. Это значение задано в заголовке и равно B'00000000', то есть 00h. Символы B' означают, что данные заданы в двоичном формате. Можно было бы написать в этом же месте 0 (десятичный) или 0h (шестнадцатеричный) и получить тот же самый результат. Двоичное представление удобнее использовать в тех случаях, когда предполагается операция с битами в регистре.
Следующая команда MOVWF TRISA загружает значение из рабочего регистра W в регистр управления конфигурацией порта A,
TRISA. Задание нуля в разряде этого регистра определяет, что соответствующий разряд порта A является выходом. В нашем случае все разряды порта A устанавливаются выходами. Обратите внимание,
что порт A имеет только 5 разрядов, и старшие 3 бита значения,
записываемого в регистр TRISA, также имеющего 5 разрядов, не используются. Если бы мы захотели, например, установить младший разряд порта A как вход, мы бы задали в секции описания регистров значение INITA равным B'00000001'. Если по ходу работы программы нам потребуется переопределять назначение отдельных разрядов портов, например, при двунаправленной передаче, то удобнее всего задать все необходимые слова конфигурации в секции описания, как это было сделано для INITA и INITB.
Следующие две команды MOVLW INITB и MOVWF TRISB
определяют конфигурацию порта B. Можно было не писать команду
MOVLW INITB, поскольку в нашем случае INITB также равен 0h.
Однако этого не стоит делать, поскольку это может привести к трудно обнаружимым ошибкам, если впоследствии потребуется изменить назначение какого-либо одного разряда. Вместо того, чтобы изменить только один разряд в одном порту, изменятся два разряда с одинаковым номером в двух портах. Поэтому пока программа не закончена, такую экономию делать не желательно, хотя в конце, на
35
этапе оптимизации кода, такие повторы можно удалять.
Команды BCF STATUS,RP и BSF STATUS,RP нужны для переключения между банками памяти. Дело в том, что вся память данных микроконтроллера разбита на два банка. Банку 0
соответствуют адреса 00h..7F, банку 1 -8F..FF. Выбор банка определяется состоянием бита 5 в регистре STATUS. Когда этот бит установлен в 1, выбран банк 1, иначе – банк 0.
В качестве примера напишем простую программу для нее нам хватит всего трех команд:
MOVLW k
MOVWF f
GOTO l
Эти команды уже использовались в заголовке базового кода.
Команда MOVLW загружает байтовый литерал или константу в рабочий регистр WREG. Следующая команда MOVWF пересылает байт из рабочего регистра WREG в заданный регистр f. Команда
GOTO передает управление на адрес l. Следующая программа записывает в рабочий регистр WREG значение 01010101 и затем выдает его содержимое на PortB.
MOVLW |
B'01010101' |
; загрузить 01010101 в регистр WREG |
MOVWF |
DATAPORT |
;записать WREG в поpт B (DATAPORT) |
GOTO |
$ |
;зациклиться навсегда |
Директива ассемблера "$" означает текущее значение программного счетчика (PC). Поэтому команда GOTO $ означает переход туда, где мы в данный момент находимся. Такой цикл бесконечен, поскольку не существует способа (кроме прерывания)
выйти из него. Команда GOTO $ часто применяется для остановки кода при отладке.
36
Ниже полностью приведена рассмотренная в качестве примера
программа.
; Пример программы
;Секция заголовка
; описание операционных регистров
TMR0 |
EQU |
01h |
PC |
EQU |
02h |
STATUS |
EQU |
03h |
FSR |
EQU |
04h |
; регистры ввода/вывода |
|
|
CNTRLPORTEQU |
05h |
|
DATAPORT EQU |
06h |
|
; ячейки ОЗУ |
|
|
SCRATCH |
EQU |
0Ch |
DIGIT |
EQU |
0Dh |
; биты регистра STATUS |
|
|
C |
EQU |
0h |
DC |
EQU |
1h |
Z |
EQU |
2h |
PD |
EQU |
3h |
TO |
EQU |
4h |
RP |
EQU |
5h |
; управляющие регистры |
|
|
TRISA |
EQU |
85h |
TRISB |
EQU |
86h |
; слова инициализации для портов ввода/вывода
INITA |
EQU |
B'00000000' |
INITB |
EQU |
B'00000000' |
;Рабочая секция
;начало исполняемого кода
ORG 0 GOTO BEGIN
37
ORG |
100h |
|
BEGIN |
|
|
; Инициализация порта А |
|
|
BCF |
STATUS,RP |
; Выбор банка 0 |
CLRF |
CNTRLPORT ; Очистить регистр |
|
MOVLW INITA |
; Загрузить B'00000000' в регистр WREG |
|
BSF |
STATUS,RP |
; Выбор банка 1 |
MOVWF TRISA |
; Все разряды порта A установить как выходы |
|
; Инициализация порта В |
|
|
BCF |
STATUS,RP |
; Выбор банка 0 |
CLRF |
DATAPORT |
; Очистить регистр DATAPORT |
MOVLW INITB |
; Загрузить B'00000000' в регистр WREG |
|
BSF |
STATUS,RP |
; Выбор банка 1 |
MOVWF TRISB |
; Все разряды порта В установить как выходы |
|
BCF |
STATUS,RP |
; Выбор банка 0 |
; Основная программа |
|
|
MOVLW B'01010101' |
; загрузить 01010101 в регистр WREG |
|
MOVWF DATAPORT |
; записать WREG в поpт B (DATAPORT) |
|
GOTO |
$ |
; зациклиться навсегда |
;
END
4. МЕТОДИЧЕСКИЕ УКАЗАНИЯ ПО ВЫПОЛНЕНИЮ
ЛАБОРАТОРНОЙ РАБОТЫ
При выполнении лабораторной работы необходимо:
изучить основные команды ассемблера среднего семейства
PICmicro, руководствуясь теоретическим введением;
ознакомиться с организацией регистров общего и специаль-
ного назначения;
создать проект и подключить к нему файл подкачки и проте-
стировать программу приведенную в качестве примера, а затем рас-
38