- •Запись и выполнение простых программ
- •Задания для домашней подготовки
- •Задания к лабораторной работе
- •Организация условных переходов, подпрограмма и стек
- •Задания для домашней подготовки
- •Задания к лабораторной работе
- •Выполнение арифметических операций. Обмен данными с eeprom.
- •Задания для домашней подготовки
- •Задания к лабораторной работе
- •Организация работы с внешними устройствами. Порты ввода/вывода.
- •Регистр данных порта b - portb
- •Регистр направления данных порта b - ddrb
- •Выводы порта b - pinb
- •Задания для домашней подготовки
- •Задания к лабораторной работе
Организация условных переходов, подпрограмма и стек
Цель работы:изучение программных способов маскирования данных и организации условных переходов; исследование особенностей записи и обращения к подпрограммам; изучение методов использования стека при создании программ.
Краткие сведения из теории
Организация условных переходов в МК осуществляется с помощью регистра флагов(статуса, состояния) SREG. Этот регистр имеет 8 разрядов, каждый из которых устанавливается по определенному правилу в соответствии с выполнением МК последней команды. Этими разрядами являются:
Разряд переполнения C – CARRY Flag (флаг переноса) устанавливается и сбрасывается целым рядом операций над данными (арифметические операции, операции сдвига), и его состояние может быть непосредственно программно проверено. Если, например, в результате сложения возник перенос из старшего разряда (7), то он устанавливает флаг переноса. Если же в результате сложения переноса из старшего разряда нет, то флаг переноса сбрасывается.
Разряд нулевого результата Z – ZERO Flag (флаг нуля) устанавливается, если при выполнении арифметической или логической операции во всех разрядах числа в регистре назначения имеются нули. В противном случае – флаг нуля сбрасывается.
Разряд отрицательного числа N – Negative Flag (флаг знака). Байт данных можно интерпретировать как число со знаком, в этом случае седьмой бит считается знаковым. Флаг устанавливается после выполнения операции в соответствии со значением седьмого бита результата.
Разряд переполнения с дополнением V – Two’s complement overflow indicator.
Разряд знака S показывает всегда результат N xor V и используется для определения нестрогих условий (больше либо равно, меньше либо равно).
Разряд половинного переноса H – Half Carry Flag (вспомогательный перенос). Этот флаг свидетельствует о возникновении переноса из третьего разряда в четвертый.
Разряд передачи бита T – Transfer Bit Flag. Этот флаг используется для сохранения/восстановления бита данных. Программно доступен для специальных команд BitLoaD(BLD) и BitSTore (BST).
Разряд прерываний I – Interrupt Flag показывает состояние триггера глобальных прерываний: 1 – прерывания разрешены, 0 – запрещены.
Во многих случаях при выполнении программ необходимо проверять или изменять(маскировать) состояние одного или нескольких разрядов числа в регистре МК. Это можно осуществить с помощью следующих операций:
логического умножения числа в регистре и маски, которая очищает разряд числа, если в соответствующем разряде маски будет записан 0, и не изменяет его, если в разряде маски записана 1;
логического сложения числа в регистре и маски, которое устанавливает разряд числа в 1, если в таком же разряде маски будет записана 1, и не изменяет его, если в этом разряде записан 0;
логического «исключающего ИЛИ» числа в регистре и числа маски, которое инвертирует содержание разряда числа, если в соответствующем разряде маски записана 1, и не изменяет его, если в этом разряде записан 0.
специальных операций по установке и сбросу битов по маске – SBRиCBR, а также специальных операций сохранения и загрузки битовBSTиBLDс использованием регистра статуса.
Примеры использования этих команд приведены в таблице Т-2.1.
Таблица Т-2.1
Мнемокод |
Содержимое регистра Rd |
Маска K/Rr |
Комментарий |
Результат |
ANDI Rd, K AND Rd, Rr |
00111010 11111111 00000000 10101010 11110000 00001111 00100010 |
10101100 00100010 00100010 00100010 11111111 11111111 00000000 |
Логическое умножение содержимого регистра Rdс числомK(или содержимым регистраRr). |
00101000 00100010 00000000 00100010 11110000 00001111 00000000 |
ORI Rd, K OR Rd, Rr SBR Rd, K |
00111010 00001111 11110000 |
10101100 00001111 00001111 |
Логическое сложение содержимого регистра Rdс числомK(или содержимым регистраRr). Операция установки битов по маске. |
10111110 00001111 11111111 |
EOR Rd,Rr |
00111010 00001111 11110000 |
10101100 00001111 00001111 |
Логическое “исключающее ИЛИ” содержимого регистра Rdс числомK(или содержимым регистраRr). |
10010110 00000000 11111111 |
CBR Rd,K |
00111010 11111111 00000000 10101010 11110000 00001111 00100010 |
01010011 11011101 11011101 11011101 00000000 00000000 11111111 |
Операция сброса битов по маске. |
00101000 00100010 00000000 00100010 11110000 00001111 00000000 |
Программа маскирования отдельных разрядов числа, записанного по адресу $0000 (программа П-2.1) приведена ниже. Программа помещает результат маскирования по адресу $0001.
П-2.1
Адрес |
Маш. код |
Метка |
Мнемокод |
Комментарий |
0000 |
9100 0000 |
|
LDS R16,0x0000 |
Загрузка байта в R16 с адреса 0x0000 |
0002 |
7A0C |
|
ANDI R16,0xAC |
Логическое «И» R16 с байтом 0xAC |
0003 |
9300 0001 |
|
STS 0x0001,R16 |
Сохранение результата по адресу 0x0001 |
0005 |
9508 |
|
RET |
Возврат |
При выполнении всех логических команд задействуются флаги регистра статуса. Это позволяет проверить состояние любого разряда числа и выполнить условные переходы в программах. Условные переходы организуются в программах с помощью команд условных переходов (Branchif). При выполнении этих команд МК проверяет состояние соответствующего разряда регистра статусаSREG. Если при проверке условие не подтверждается, то выполняется следующая по порядку команда программы. Помимо этого, существуют команды «условного пропуска» (Skipif). Они используются для пропуска одной команды, следующей непосредственно за командой условного пропуска.
Таким образом, команды условных переходов позволяют строить ветвящиеся алгоритмы и, в зависимости от текущего значения результата выполнения команд, переходить на различные участки программы.
Ниже приведена программа(П-2.2), которая увеличивает значение регистра R0 на единицу, однако в случае, когда второй разряд установлен в 1, значение регистра увеличивается на 4. Цикл выполняется бесконечно.
П-2.2
Адрес |
Маш. код |
Метка |
Мнемокод |
Комментарий |
0000 |
2400 |
|
CLR R0 |
Очистка регистра R0 |
0001 |
9403 |
M0: |
INC R0 |
Увеличиваем R0 на 1 (R0=R0+1) |
0002 |
2D00 |
|
MOV R16,R0 |
Копируем R0 в R16 чтобы не изменять значение в R0 |
0003 |
7004 |
|
ANDI R16,0x04 |
Проверяем установлен ли бит 2 в единицу? Если бит не установлен, то результатом логического «И» будет 0, что приведет к установке флага нуля Z=1 |
0004 |
F411 |
|
BRNE M1 |
Если Z=0, то переход на метку M1 – прибавляем 4 к R0 |
0005 |
940C 0001 |
|
JMP M0 |
Иначе – повторяем цикл, начиная с прибавления 1 к R0 |
0007 |
0E00 |
M1: |
ADD R0,R16 |
Поскольку в регистре R16, после операции ANDI остается значение 4, то мы его и прибавляем к R0 |
0008 |
940C 0001 |
|
JMP M0 |
Повторяем цикл |
Память микроконтроллера весьма ограничена (2 Кбайт Репрограммируемое ПЗУ, 128 байт EEPROM, Статическое ОЗУ), поэтому при разработке программ нужно стараться сделать их как можно короче. С этой целью часть программы, которая неоднократно повторяется, или программа, которая часто используется, могут быть оформлены в виде подпрограмм – последовательностей команд, выполнение которых может быть вызвано из любого места программы любое количество раз. Процесс передачи управления подпрограмме называется ее вызовом. Данные и адреса, требуемые для работы подпрограммы, называются входными параметрами. Результаты работы подпрограммы, передаваемые по окончании ее работы в основную программу, называются выходными параметрами.
Для вызова подпрограмм и возврата из них используются команды CALL (RCALL, ICALL, EICALL) и RET. Команда CALL загружает в программный счетчик значение своего операнда, при этом МК автоматически сохраняет в стеке адрес основной программы, к которому он будет обращаться после выполнения подпрограммы.
Стек – специально организованная область ОЗУ, задействованная в МК для временного сохранения данных или адресов. Число, записанное в стек последним, извлекается из него первым (Last Input-First Output).
Команда RET помещает в программный счетчик последнее записанное на данный момент в стеке число. После чего выполнение программы будет осуществляться с этого адреса. Любая подпрограмма должна завершаться командой RET.
Автоматическое сохранение и восстановление адреса основной программы при выполнении подпрограмм позволяет сделать подпрограммы вложенными, т.е. осуществить вызов одной подпрограммы из другой. Уровень вложенности для МК определяется лишь размером стека.
Помимо команд вызова подпрограмм и возврата из них со стеком можно обмениваться информацией с помощью команд PUSH Rr(записать в стек содержимое регистра) и POP Rd(записать данные из стека в регистр). При записи в стек содержимое указателя стека уменьшается (SP=SP-1). При извлечении из стека данные в памяти не изменяются, а лишь происходит их чтение и увеличение указателя стека (SP=SP+1).
При разработке программ необходимо первоначально назначить область стека, записывая в SP адрес с помощью команд:
LDI R16, адрес (например, 0xDF) STS 0x5D,R16 |
или |
LDI R16, адрес (например, 0xDF) OUT 0x3D,R16 |
Все операции со стеком должны быть сбалансированы, т.е. каждая подпрограмма должна содержать равное количество команд PUSH и POP и оканчиваться командой RET. В противном случае выполнение команды RET в конце подпрограммы приведет к записи в программный счетчик случайного числа из стека. Адрес возврата в основную программу будет потерян, и нарушится последовательность ее выполнения.
Как правило, в начале каждой подпрограммы в стеке сохраняют содержимое всех задействованных при ее выполнении регистров (с помощью команды PUSH). В конце подпрограммы восстановление содержимого регистров осуществляется с помощью команд POP и в обратной последовательности по отношению к их записи в стек.
Алгоритм работы простой подпрограммы временной задержки приведен на рис.2.1.
Рис 2.1. Алгоритм простой подпрограммы временной задержки
Общее время задержки вычисляется по формуле: , гдеN – число в регистре R16 (параметр подпрограммы). Команда «нет операции» нужна для увеличения времени выполнения цикла, а следовательно и общей задержки. Вместо этой команды может быть записана любая последовательность команд, выполнение которых не изменяет содержимого регистров МК.
Подпрограмма Delay (П-2.3) представляет собой программу временной задержки, в соответствии с алгоритмом на рис. 2.1.
П-2.3
Адрес |
Маш. код |
Метка |
Мнемокод |
Комментарий |
0000 |
2E00 |
Delay: |
MOV R0,R16 |
Копируем значение регистра R16 |
0001 |
0000 |
M1: |
NOP |
Нет операции |
0002 |
940A |
|
DEC R0 |
Уменьшаем R0 на 1 |
0003 |
F7E9 |
|
BRNE M1 |
Если не 0 (флаг Z не установлен), то переход на метку M1 |
0004 |
9508 |
|
RET |
Выход из подпрограммы |
Для организации более длительных задержек необходимо создать внешний цикл, в котором будет происходить вызов подпрограммы Delay столько раз, сколько потребуется. Программа П-2.4 осуществляет данную функцию.
П-2.4
Адрес |
Маш. код |
Метка |
Мнемокод |
Комментарий |
0000 |
ED0F |
|
LDI R16,0xDF |
Определяем область стека, начиная с 0xDF |
0001 |
BF0D |
|
OUT 0x3D,R16 |
Устанавливаем указатель стека |
0002 |
E015 |
|
LDI R17,0x05 |
Регистр R17 – внешний счетчик, устанавливаем равным 5 |
0003 |
2700 |
CNT0: |
CLR R16 |
Очистка входного параметра R16 для Delay (максимальная задержка) |
0004 |
D003 |
|
RCALL Delay |
Вызов подпрограммы |
0005 |
951A |
|
DEC R17 |
Уменьшаем внешний счетчик на 1 |
0006 |
F7E1 |
|
BRNE CNT0 |
Если в R17 не получен 0, то переход на CNT0 |
0007 |
CFFF |
M0: |
RJMP M0 |
Бесконечный цикл |
С помощью стека можно осуществлять неявную передачу управления в программе. Это достигается нестандартным использованием команд RET, RJMP/IJMP, POP и PUSH.
Пример неявного вызова (CALL) подпрограммы Delay. После выполнения подпрограммы, необходимо передать управление по адресу Metka. Для этого заносим в стек сначала младший байт адреса, затем старший и передаем управление подпрограмме Delay с помощью команды RJMP, а не RCALL. По команде RET в подпрограмме, МК извлечет из стека адрес возврата (Metka) и передаст управление по этому адресу.
ldi R16,0xDF
out 0x3D,R16
ldi R16,Low(Metka)
push R16
ldi R16,High(Metka)
push R16
rjmp Delay
Metka: nop
Пример неявного возврата из подпрограммы (RET). Изменим подпрограмму Delay так, чтобы в ней отсутствовала команда RET, но передача управления вызывающей программе осуществлялась. Для этого извлечем из стека адрес возврата в регистры R31 и R30 (эти два регистра образуют регистровую пару Z, используемую для косвенной адресации). Затем выполним команду косвенного перехода IJMP, которая передаст управление по адресу R31:R30, то есть в вызывающую программу.
Delay: mov R0,R16
M1: nop
dec R0
brne M1
pop R31
pop R30
ijmp
Пример неявной непосредственной передачи управления (JMP) осуществляется достаточно просто. Для этого необходимо поместить адрес, куда необходимо передать управление, в стек и вызвать команду RET:
ldi R16,Low(Metka)
push R16
ldi R16,High(Metka)
push R16
ret
...
Metka: nop
...