Программное управление технологическим оборудованием
.pdf
return
Sub2:
…
return
Программа работает следующим образом: с помощью команды btss W0, #0 анализируется бит 0 регистра W0: если он равен 0, то выполняется следующая за инструкцией команда, а если он равен 1, то следующая за командой инструкция пропускается. Таким образом, если бит 0 установлен, то в регистре W2 остаётся адрес вызова процедура Sub1, если же бит 0 сброшен, то в регистр W2 перезаписывается адрес вызова процедуры Sub2. Для того чтобы вызвать процедуру посредством адреса, содержащегося в рабочем регистре W2, выполняется команда «call W2». В данном примере бит 0 регистра W0 принудительно устанавливается в 1, поэтому вызывается процедура Sub1.
В примере значение стартового адреса одной из процедур (Sub1 или Sub2) записывается в регистр с помощью специального оператора handle в одной из команд:
mov #handle(Sub1),W2 mov #handle(Sub2),W2
Команды работы со стеком
Программный стек управляется командами push и pop. Эти инструкции эквивалентны инструкции mov с регистром W15 в качестве указателя приёмника. Для сохранения данных в стек необходимо выполнить следующую команду:
push W0
Значение, содержащееся на вершине стека, может быть получено следующей инструкцией:
pop W0
Во время выполнения инструкции вызова подпрограммы call, значение счётчика команд (PC) сохраняется в стек. Благодаря этому, после завершения работы подпрограммы, основная программа может продолжить своё выполнение с правильной позиции. Сохранение счётчика команд в стек происходит следующим образом: биты 15..0 располагаются по первому доступному адресу в стеке, а биты 22..16 помещаются по следующему адресу, при этом старшие биты второго слова дополняются нолями.
451
2 Пример выполнения работы
Задача: Вычислить значение выражения (25 + 13) * (18 – 9), результаты промежуточных вычислений хранить в регистрах. Выделить младшую тетраду результата и поместить её в старшую.
Листинг программы: |
|
|
|
|
|
|
|
; W0 = |
|
||
mov |
#25, W0 |
25 |
|
|
|
|
|
; W1 |
= |
|
|
mov |
#13, W1 |
13 |
|
|
|
|
|
; W2 |
= |
|
|
add |
W0, W1, W2 |
W0 |
|
|
+ W1 |
|
|
; W3 |
= |
|
|
mov |
#18, W3 |
18 |
|
|
|
mov |
#9, W4 |
; W4 |
= 9 |
|
|
|
|
; |
= |
|
|
sub |
W3, W4, W5 |
W5 |
W3 |
- W4 |
|
|
|
; |
= |
|
|
mul.ss |
W2, W5, W6 |
W6 |
W2 |
* W5 |
|
|
|
; |
= |
& |
|
and |
#0x000F, W6 |
W6 |
W6 |
0x000F |
|
|
|
; |
= |
|
|
sl |
W6, #12, W6 |
W6 |
W6 |
<< 12 |
|
3 Варианты индивидуальных заданий к лабораторной работе
2.7Загрузить в регистр число 15. Сложить его с 25 и результат поместить на вершину стека. Поместить по адресу 20h внутренней памяти данных младшую десятичную цифру результата, а по адресу 21h – старшую.
2.8Найти разницу чисел 4836 и 2454. Младший байт результата поделить на 2. Поместить по адресу 30h внутренней памяти данных младшую десятичную цифру результата, а по адресу 32h – старшую.
2.9Найти адрес ячейки памяти данных путем перемножения двух чисел 0Сh и 0Eh. В эту ячейку записать результат логической операции "исключающее или" между текущим содержимым регистра W0 и числа
09h.
2.10Найти частное чисел 236 и 59. Результат умножить на 8 используя операции сдвига. По вычисленному таким образом адресу ячейки внутренней памяти данных размесить результат двойного декремента полученного числа.
Загрузить регистр W7 числом 023h. Найти сумму W7 + 32. В ячейку
452
внутренней памяти данных, расположенную по вычисленному таким образом адресу, загрузить число десятичных единиц результата сложения.
3.1Вычислить значение выражения (81 + 64) * (112 - 25) OR 10011010b, сохраняя промежуточные результаты в стеке.
3.2Найти разницу чисел 4801 и 209. Число десятичных единиц старшего байта результата поместить в старшую тетраду порта RA. Младшую тетраду оставить без изменений.
4 Контрольные вопросы
1.Сколько команд включает в себя система команд микроконтроллера?
2.На какие группы разделены команды микроконтроллера?
3.Как длительность машинного цикла микроконтроллера соотносится с его тактовой частотой?
4.Для чего предназначены биты конфигурации микроконтроллера и в чём их особенность?
5.Сколько источников тактирования может иметь микроконтроллер?
6.Каким образом настраивается источник тактирования микроконтроллера?
7.Какую функцию выполняет система прерываний?
8.Какое событие может быть причиной возникновения прерывания?
453
Лабораторная работа 3
Изучение системы программирования микроконтроллеров dsPIC33 с помощью языка программирования ассемблер
Цель работы:
Изучить алгоритмы типовых программ обработки информации, основные правила программирования и наиболее употребительные директивы. Составить алгоритм и программу обработки, исследовать ход её выполнения.
Порядок выполнения работы:
1 Краткие теоретические сведения
1.1 Обзор MPLAB ASM30 ассемблера
Язык ассемблера – машинно-ориентированный язык низкого уровня с командами, соответствующими командам микроконтроллера.
Условно текст программы на ассемблере можно разбить на следующие секции:
1. блок определений
o секция подключаемых файлов;
секция определения битов конфигурации; секция определения констант; секция определения макросов;
1.7секция объявления переменных. блок кода
1.7обработчик прерываний; o основной цикл программы; o подпрограммы
Таким образом, в блоке определений указывается модель используемого контроллера, подключаются заголовочные файлы, объявляются константы и переменные, содержатся иные директивы, определяющие параметры работы ассемблера и варианты сборки программы. В блоке кода содержатся
непосредственно |
исполняемые |
микроконтроллером |
инструкции, |
сгруппированные в подпрограммы и обработчики событий. |
|
||
Пример исходного файла на языке ассемблер: |
|
||
.list p=p33FJ32MC204 |
|
|
|
.include "p33FJ32MC204.inc" |
|
||
.global __reset |
;Метка начала кода |
|
|
__reset:
454
main:
nop
goto main
service: |
|
no |
|
p |
|
no |
|
p |
|
retfie |
|
.end |
;Конец кода |
Основу языка ассемблера составляют директивы и инструкции. Директивы ассемблера интерпретируются во время выполнения работы ассемблера и используются для определения секций памяти, инициализации констант, декларирования и определения символов и т.д. Инструкции являются командами микроконтроллера, непосредственно исполняются им во время работы.
1.2 Общий формат инструкций и директив
Общий формат инструкций и директив ассемблера следующий:
[метка:] инструкция [операнды] [;комментарии] [метка:] директива [аргументы] [;комментарии]
Таким образом, каждая строка исходного файла может содержать до четырёх информационных полей:
вметка;
вмнемоника команды;
воперанды команды;
вкомментарии.
Метки используются для отметки позиции в коде. Во время компоновки, метки определяют адреса в памяти. Метки должны начинаться с первой колонки. За меткой должно следовать двоеточие (:). Метка должна начинаться с символа латинского алфавита или символа подчёркивания (_) и может состоять из цифр и букв латинского алфавита и символа подчёркивания (_).
Мнемоники инструкций микроконтроллера, директивы ассемблера и макрокоманды должны начинаться со второй (и далее) колонки.
Операнды и аргументы следуют за мнемоникой команды. Операнды должны быть отделены от мнемоники не менее чем одним символом пробела
455
либо табуляции. Список операндов разделяется запятыми. Операнды используются в инструкциях для обеспечения информации об источнике и приёмнике. Аргументы подобны операндам и используются как источник и приёмник информации директив.
Любой текст до конца строки после символа «;» трактуется как комментарий. Комментарии могут следовать за операндами, мнемониками и метками и могут начинаться в любой колонке. Строковые константы, содержащие символ «;», как комментарий не воспринимается. Так же комментарии могут быть многострочными. В этом случае начало комментариев обозначается сочетанием символов «/*», а конец – сочетанием
«*/».
1.3 Директивы ассемблера
Существует 5 основных типов директив:
директивы контроля – управляют созданием разделов условно компилированного кода;
директивы данных – управляют разделением памяти и назначением символических имён переменным и константам;
директивы листинга – определяют формат и состав файла листинга. Эти директивы позволяют указывать заголовки, нумеровать страницы и настраивать другие параметры;
макро директивы – управляют работой макросов и распределением данных в теле макроса;
директивы объектного файла – используются только при создании объектного файла.
Основные директивы ассемблера перечислены ниже.
.list
Директива .list используется для управления процессом сборки программы. В частности, с помощью данной директивы можно указать используемый микроконтроллер, систему счисления по умолчанию, параметры работы со строками и т.д.. Пример использования директивы:
.list p=p33fj32mc204
456
.include
Директива .include добавляет содержимое указанного файла в исходный файл. Эффект аналогичен копированию полного текста включаемого файла в место расположения директивы. Параметр директивы – подключаемый файл
– может указываться как с полным путём, так и без. Во втором случае поиск файла будет осуществляться в текущей рабочей директории, директории исходного файла и служебных директориях. Пример использования директивы:
.include “p33fj32mc204.inc”
.global
Директива .global используется для того, чтобы позволить меткам, определённым внутри файла, использоваться в другом файле. Пример использования директивы:
.global __reset
.global __OscillatorFail
.global __AddressError
В данном примере метки сделаны глобальными, чтобы компоновщик использовать их как адрес для перехода программы в указанные точки при наступлении соответствующих событий. Метка __reset используется для обозначения начала кода и используется как адрес для перехода из вектора сброса.
.section
Директива .section декларирует секцию памяти. Атрибутами, следующими за директивой, задается расположение секции – например, в памяти RAM либо в программной памяти. Пример использования директивы:
.section .data
.data
Директива используется для информирования ассемблера, что последующие данные будут помещены в секцию инициализированных данных. Если адрес секции не определён, то он будет назначен автоматически при связи объектных файлов.
.text
Директива .text используется для информирования ассемблера, что следующий код будет помещён в секцию программной памяти.
457
.equ
Директива .equ используется для определения символа и присвоения ему значения. Пример использования директивы:
.equ FCY, #7370000
В данном примере символу FCY присваивается литеральное значение 7370000. В таком контексте FCY является константой, которая может использоваться в коде.
.hword
Директива .hword используется для объявления инициализированных данных в пределах секции. Данные могут быть в виде констант, внутренних и внешних меток или их выражений. Пример использования директивы:
MinX: .hword 0x7FFF
.extern
Директива .extern используется для объявления переменной либо метки, которая может использоваться в данном файле кода, однако определена как глобальная в другом файле. Пример использования директивы:
.extern label
.end
Директива .end используется для обозначения окончания ассемблерного исходного файла. Пример использования директивы:
.list
p=p33fj32mc204
; текст программы
.end
1.4 Числовые константы и системы счисления
MPASM поддерживает шестнадцатеричную, десятичную и двоичную системы счисления. Для обозначения числового значения используется символ «#».
Синтаксические правила числовых значений приведены в таблице 1.1.
458
|
|
Таблица 1.1 |
Синтаксис числовых значений |
|
|
Тип |
Синтаксис |
Пример |
Шестнадцатеричный |
0x< числовое значение > |
#0x9f |
Десятичный |
<числовое значение> |
#123 |
Двоичный |
0b<числовое значение> |
#0b11 |
1.5 Текстовые строки
Текстовые строки могут состоять из знаков ASCII. Определение строки завершается специальным символом окончания строки – «\n».
2 Пример выполнения работы
Задача: Вычислить значение выражения (25 + 13) * (18 – 9), результаты промежуточных вычислений хранить в регистрах. Выделить младшую тетраду результата и поместить её в старшую. Проверить корректность выполнения алгоритма и результаты промежуточных вычислений в симуляторе. Указать результат выполнения алгоритма.
Листинг программы:
.include "P33FJ32MC204.inc"
.global __reset
__reset:
|
|
; W0 = |
|
|
mov |
#25, W0 |
25 |
|
|
|
|
; W1 = |
|
|
mov |
#13, W1 |
13 |
|
|
|
|
; W2 = |
|
|
add |
W0, W1, W2 |
W0 |
|
+ W1 |
|
|
; W3 = |
|
|
mov |
#18, W3 |
18 |
|
|
|
|
; |
|
|
mov |
#9, W4 |
W4 |
= 9 |
|
|
|
; |
= |
|
sub |
W3, W4, W5 |
W5 |
W3 |
- W4 |
|
|
; |
= |
|
mul.ss |
W2, W5, W6 |
W6 |
W2 |
* W5 |
and |
#0x000F, W6 |
|
|
|
|
|
; |
= |
<< |
sl |
W6, #12, W6 |
W6 |
W6 |
12 |
.end
459
3 Варианты индивидуальных заданий к лабораторной работе
Разработать программу в соответствии с вариантом задания. Проверить корректность выполнения алгоритма и результаты промежуточных вычислений в симуляторе. Пометить промежуточные значения переменных на каждом шаге и указать результат выполнения алгоритма.
Загрузить в регистр число 15. Сложить его с 25 и результат поместить на вершину стека. Поместить по адресу 20h внутренней памяти данных младшую десятичную цифру результата, а по адресу 21h – старшую.
Найти разницу чисел 4836 и 2454. Младший байт результата поделить на 2. Поместить по адресу 30h внутренней памяти данных младшую десятичную цифру результата, а по адресу 32h – старшую.
Найти адрес ячейки памяти данных путем перемножения двух чисел 0Сh и 0Eh. В эту ячейку записать результат логической операции "исключающее или" между текущим содержимым регистра W0 и числа
09h.
Найти частное чисел 236 и 59. Результат умножить на 8 используя операции сдвига. По вычисленному таким образом адресу ячейки внутренней памяти данных размесить результат двойного декремента полученного числа.
Загрузить регистр W7 числом 023h. Найти сумму W7 + 32. В ячейку внутренней памяти данных, расположенную по вычисленному таким образом адресу, загрузить число десятичных единиц результата сложения.
Вычислить значение выражения (81 + 64) * (112 - 25) OR 10011010b, сохраняя промежуточные результаты в стеке.
Найти разницу чисел 4801 и 209. Число десятичных единиц старшего байта результата поместить в старшую тетраду порта RA. Младшую тетраду оставить без изменений.
4 Контрольные вопросы
Из каких блоков состоит программа на ассемблере?
В чём отличие директив и инструкций?
Укажите синтаксис директив.
Укажите синтаксис инструкций.
Каково назначение литералов?
460
