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

 

Текст программы можно набирать в любом текстовом редакторе, такие как встроенный редактор 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

return false">ссылка скрыта

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