Написание программы

Текст программы можно набирать в любом текстовом редакторе, такие как встроенный редактор Norton Commander, FAR, а также Microsoft Word, WordPad и других. Также можно использовать специально предназначенные для этого программы Wavrasm, AVR Studio

Для создания программы не обязательно использовать ассемблер, программное обеспечение AVR поддерживает также и язык C или С++. Но в лабораторном комплексе этот вариант не рассматривается.

Программа, написанная на ассемблере, должна иметь определенную структуру.

Предлагается следующий шаблон (для AT90S8535)

;*******************************************

; название программы,

; краткое описание, необходимые пояснения

:*******************************************

;******подключаемые дополнительные файлы

.include “8535def.inc”; файл описания AT90S8535

.include «имя_файла1.расширение»; включение дополнительных

.include «имя_файла2.расширение»; файлов

;****** глобальные константы

.equ имя1 = xxxx;

.equ имя2 = nnnn

;****** глобальные регистровые переменные

.def имя1= регистр

.def имя2= регистр

;******* сегмент данных

.dseg

.org xxxx; адрес первого зарезервированного байта

label1:.BYTE 1; резервировать 1 байт под переменную label1
label2:.BYTE m; резервировать m байт под переменную label2

;****** сегмент EEPROM (ЭСППЗУ)

.eseg

.org xxxx; адрес первого зарезервированного байта

.db выражение1,выражение2,…; записать список байтов в EEPROM.

.dw выражение1,выражение2,…; записать список слов в EEPROM.

;****** сегмент кодов

.cseg

.org $0000; адрес начала программы в программной памяти

;****** вектора прерываний (если они используются)

rjmp reset;прерывание по сбросу

.org $0002

rjmp INT0;обработчик прерывания IRQ0

.org $0004

rjmp INT1;обработчик прерывания IRQ1

.org adrINTx;адрес следующего обработчика прерываний

rjmp INTx;обработчик прерывания x

…….;далее по порядку располагать обработчики остальных;прерываний

;******* начало основной программы

main: <команда> xxxx

… …

;******* подпрограммы

;******* подпрограмма 1

subr1: <команда> xxxx

…… ………. ……

ret

;******* подпрограмма 2

subr2: <команда> xxxx

…… ………. ……

ret

…………….

;******* программы обработчиков прерываний

INT0: <команда> xxxx

…… ………. ……

reti

INT1: <команда> xxxx

…… ………. ……

reti

INTx: <команда> xxxx

…… ………. ……

reti

………………………

; конец программы никак не обозначается.

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

Как уже указывалось, программа простейшая: вычесть из числа 5 число 3. Если включен тумблер SA1 (рис. 1.2), то на индикацию выдать результат вычитания. Если тумблер SA1отключен – на индикацию вывести цифру ноль.

Десятичное число Код
  3f
   
  5b
  4f
   
  6d
  7d
   
  7f
  6f

Рис. 1.5 Алгоритм программы №1

Алгоритм программы (рис. 1.5) соответствует программе №1, использующей директиву equ ассемблера.

Программа №2 отличается от программы №1 резервированием по одному байту оперативной памяти под семисегментные коды цифр от 0 до 9.

Программа №3 самая короткая. Она использует директиву.dw для определения слов в программной памяти. В программе используется команда LPM ассемблера. По этой команде загружается байт, адресуемый регистром Z в регистр R0. Команда обеспечивает доступ к любому байту памяти программы, организованной как 16 битное слово. Младший бит регистра Z определяет, осуществляется ли доступ к младшему байту слова (0) или к старшему (1).

;Программа №1.Использование директивы equ

.include "8535def.inc";включить файл – описание для AT90S8535

.dseg;сегмент данных

.equ cod0=$64;присвоение имен ячейкам SRAM

.equ cod1=$65

.equ cod2=$66

.equ cod3=$67

.equ cod4=$68

.equ cod5=$69

.equ cod6=$6a

.equ cod7=$6b

.equ cod8=$6c

.equ cod9=$6d

.cseg

.org 0

rjmp reset

.org $30;начало программы

reset:

ldi r16,$00;определение стека с вершиной по адресу $00ff

out sph,r16

ldi r16,$ff

out spl,r16

ldi zl,$64;задание адреса начала зарезервированных ячеек

ldi zh,$00

ldi r16,$ff;настроить порт С на выход

out ddrc,r16

ldi r16,00;настроить порт А на вход

out ddra,r16

ldi r16,$c;настроить порт В: биты 2 и 3 на выход, остальные на вход

out ddrb,r16

ldi r16,$f0;настроить порт D: биты 0...4 на вход, остальные на выход

out ddrd,r16

sbi portB,3;выдать 1 на разряд 3 порта В

ldi r17,$3f;задание семисегментных кодов

sts cod0,r17

ldi r17,$06

sts cod1,r17

ldi r17,$5b

sts cod2,r17

ldi r17,$4f

sts cod3,r17

ldi r17,$66

sts cod4,r17

ldi r17,$6d

sts cod5,r17

ldi r17,$7d

sts cod6,r17

ldi r17,$07

sts cod7,r17

ldi r17,$7f

sts cod8,r17

ldi r17,$6f

sts cod9,r17

ldi r17,5;задание уменьшаемого

ldi r18,3;задание вычитаемого

m1: sbis pina,4;если включен тумблер SA1,то пропустить

rjmp m2;следующую команду

mov r20,r17; в r20 поместить уменьшаемое

sub r20,r18; вычесть вычитаемое

rjmp vv

m2:

ldi r20,0

vv:

push zl;сохранить zl в стеке

add zl,r20;сложить zl с результатом

ld r0,z;семисегментный код результата переслать в r20

pop zl;извлечь zl из стека

out portc,r0;выдать результат на индикацию

rjmp m1

;Программа №2. Использование оперативной памяти под переменные

.include "8535def.inc";подключение файла описания AT90S8535

.dseg;сегмент данных

.org $64;адрес первого зарезервированного байта

cod0:.byte 1;резервирование по одному байту под переменные

cod1:.byte 1

cod2:.byte 1

cod3:.byte 1

cod4:.byte 1

cod5:.byte 1

cod6:.byte 1

cod7:.byte 1

cod8:.byte 1

cod9:.byte 1

.cseg;сегмент кодов

.org $0;адрес начала программы в программной памяти

rjmp reset;прерывание по сбросу при подаче питания

;или при нажатии на кнопку "Сброс"

reset:

ldi r16,$00;определение стека с вершиной по адресу $00ff

out sph,r16

ldi r16,$ff

out spl,r16

ldi zl,$64;задание адреса начала зарезервированных ячеек

ldi zh,$00

ldi r16,$ff;настроить порт С на выход

out ddrc,r16

ldi r16,00;настроить порт А на вход

out ddra,r16

ldi r16,$c;настроить порт В: биты 2 и 3 на выход, остальные на вход

out ddrb,r16

ldi r16,$f0;настроить порт D: биты 0...4 на вход, остальные на выход

out ddrd,r16

sbi portb,3;выдать 1 на разряд 3 порта В

ldi r17,$3f;задание семисегментных кодов

sts cod0,r17

ldi r17,$06

sts cod1,r17

ldi r17,$5b

sts cod2,r17

ldi r17,$4f

sts cod3,r17

ldi r17,$66

sts cod4,r17

ldi r17,$6d

sts cod5,r17

ldi r17,$7d

sts cod6,r17

ldi r17,$07

sts cod7,r17

ldi r17,$7f

sts cod8,r17

ldi r17,$6f

sts cod9,r17

ldi r17,5;задание уменьшаемого

ldi r18,3;задание вычитаемого

m1: sbis pina,4;если включен тумблер SA1,то пропустить

rjmp m2;следующую команду

mov r20,r17; в r20 поместить уменьшаемое

sub r20,r18; вычесть вычитаемое

rjmp vv

m2:

ldi r20,0

vv: push zl;сохранить zl в стеке

add zl,r20;сложить zl с результатом

ld r0,z;семисегментный код результата переслать в r20

pop zl;извлечь zl из стека

out portc,r0;выдать результат на индикацию

rjmp m1

;Программа №3. Использование директивы.dw

.include "8535def.inc";подключение файла описания AT90S8535

.cseg

.org 0

rjmp reset

.dw $063f,$4f5b,$6d66,$077d,$6f7f,$7c77,$5e39,$7179;семисегментные коды

reset:

ldi r16,$00;определение стека с вершиной по адресу $00ff

out sph,r16

ldi r16,$ff

out spl,r16

ldi r16,$ff

out ddrc,r16;настроить порт С на выход

ldi r16,00

out ddra,r16;настроить порт А на вход

ldi r16,$c

out ddrb,r16;настроить порт В: биты 2 и 3 на выход, остальные на вход

ldi r16,$f0

out ddrd,r16;настроить порт D: биты 0...4 на вход, остальные на выход

sbi portb,3;выдать 1 на разряд 3 порта В

ldi zl,02;установить адрес семисегментного кода нуля в регистр Z

ldi zh,00

ldi r17,5;задание уменьшаемого

ldi r18,3;задание вычитаемого

m1: sbis pina,4;если включен SA1, то пропустить следующую команду

rjmp m2

mov r20,r17;в r20 поместить уменьшаемое

sub r20,r18;вычесть вычитаемое

rjmp vv

m2:

ldi r20,0;присвоить результату значение нуль

vv: push zl;сохранить zl в стеке

add zl,r20; сложить zl с результатом

lpm;загружаем бит, адресуемый регистром Z, в регистр R0

pop zl;извлечь zl из стека

out portc,r0;выдать результат на индикацию

rjmp m1


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: