Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КП_МК_Ашанина.docx
Скачиваний:
7
Добавлен:
01.05.2025
Размер:
203 Кб
Скачать
☆

Листинг программы

.INCLUDE "C:\Program Files\Atmel\AVR Tools\AvrAssembler\Appnotes\2313def.inc"

.DSEG

.ORG 0x60

count: .byte 1

.CSEG

.ORG 0x0000

rjmp Reset

rjmp INT0_interrupt

rjmp INT1_interrupt

rjmp T1CAPT_interrupt

rjmp T1COMP_interrupt

rjmp T1OVF_interrupt

rjmp T0OVF_interrupt

rjmp UART_RX_interrupt

rjmp UART_UDRE_interrupt

rjmp UART_TX_interrupt

rjmp ANCOMP_interrupt

Reset:

;Настройка (инициализация) указателя стека

ldi r16, 0x7F

out SPL, r16

;ЗАПОМИНАЕМ ПОСТОЯННЫЕ ВЕЛИЧИНЫ В РЕГИСТРАХ ДЛЯ УДОБСТВА

ldi r17, 0x3A ; ':'

ldi r18, 0x0D ; CR

ldi r19, 0x0A ; LF

ldi r20, 0x30 ; 00110000 '0'

ldi r21, 0x31 ; 00110001 '1'

clr r1 ; count

ldi r16, 0x60

mov r0, r16 ; adress

clr r16

ldi r16, 0x30 ;смещение для преобраз в/из ascii

mov r5, r16

clr r16

;Настройка последовательного порта (UART)

;Настройка линии PD1, pd3,pd4,pd5 на вывод

ldi r16, 0x3A

out DDRD, r16

;Задание наибольшей скорости передачи данных

ldi r16, 0x00

out UBRR, r16

;Разрешение приемника и передатчика UART

;Разрешение прерываний по окончанию приема байта данных

ldi r16, 0x98 ;10011000

out UCR, r16

;Настройка порта B на вывод

ldi r16, 0xff

out DDRB, r16

;Глобальное разрешение прерываний

sei

ldi zh, high(string*2)

ldi zl, low(string*2)

adiw zl, 0x05

Main:

;Цикл основной программы

ldi r16, 0x03

mov r1, r16

ldi r16, 0x08

mov r12, r16

clr r16

loop1:

;Выбираем из памяти программ символ строки

lpm

rcall from_ascii

rcall to_indicator

;Посылаем символ нафиг. и он идет.

cpi R1, 0x03

brne lab1

rjmp lab_s

lab1: cpi R1, 0x02

brne lab2

ldi r16, 0x10

mov r12, r16

rjmp lab_s

lab2: cpi R1, 0x01

ldi r16, 0x20

mov r12, r16

rjmp lab_s

lab_s: out PORTD, r12

out PORTB, r0

nop

nop

nop

nop

nop

nop

nop

adiw zl, 0x01

dec r1

brne loop1

;Конец цикла вывода

wdr

rjmp Main

string: .db 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30

error: .db 0x3A, 0x30, 0x31, 0x31, 0x30, 0x39, 0x39, 0x39, 0x39, 0x33, 0x0D, 0x0A

ind: .db 0xFC, 0x50, 0xDA, 0xF2, 0x55, 0xB6, 0xBE, 0xE0, 0xFE, 0xF5

;Обработчики прерываний

INT0_interrupt:

reti

INT1_interrupt:

reti

T1CAPT_interrupt:

reti

T1COMP_interrupt:

reti

T1OVF_interrupt:

reti

T0OVF_interrupt:

reti

UART_RX_interrupt:

;Обработка прерываний по приему байта данных

in R16, UDR

wdr

cpi R1, 0x00

brne l1

CPSE R16, R17 ;if count=0, udr=':'

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l1: cpi R1, 0x01

brne l2

CPSE R16, R20 ;if count=1, udr='0'

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l2: cpi R1, 0x02

brne l3

CPSE R16, R21 ;if count=2, udr='1'

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l3: cpi R1, 0x03

brne l4

CPSE R16, R21 ;if count=3, udr='1'

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l4: cpi R1, 0x04

brne l5

CPSE R16, R20 ;if count=4, udr='1'

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l5: cpi R1, 0x05 ;data1

brne l6

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l6: cpi R1, 0x06 ;data2

brne l7

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l7: cpi R1, 0x07 ;data3

brne l8

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l8: cpi R1, 0x08 ;lrc1

brne l9

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

l9: cpi R1, 0x09 ;lrc2

brne lA

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

lA: cpi R1, 0x0A ;cr

brne lB

CPSE R16, R18 ;if count=0a, udr=cr

rjmp ln

st Z, R16

adiw zl, 0x01

inc R1

rjmp ll

lB: cpi R1, 0x0B ;lf

brne ln

CPSE R16, R19 ;if count=4, udr=lf

rjmp ln

st Z, R16

adiw zl, 0x01

clr R1

rjmp ll

ln: ;if not ':' -> error

rcall error_frame

ll: reti

UART_UDRE_interrupt:

reti

UART_TX_interrupt:

reti

ANCOMP_interrupt:

reti

;functions

error_frame:

;строка уже сформирована и лежит в памяти по адресу error

;Инициализация указателя на строку

ldi zh, high(error*2)

ldi zl, low(error*2)

;Начало цикла вывода строки

ldi r16, 12

mov r1, r16

clr r16

cycle:

;Выбираем из памяти программ символ строки

lpm

;Посылаем символ в последовательный порт

out UDR, r0

;Ждем (цикл wait), когда освободитмя регистр данных последовательного порта

wait:

nop

sbis USR, 5

rjmp wait

adiw zl, 0x01

dec r1

brne cycle

;Конец цикла вывода строки

ret

to_ascii:

; маска 0х0f и 0xf0 - разбиваем на 2 байта

; второй сдвигаем на 4 вправо

; к каждому прибавляем 0х30

;исходное - r0. результат - r10, r11

ldi r16, 0x30

mov r7, r16

ldi r16, 0x0f

mov r9, r16

ldi r16, 0xf0

mov r8, r16

mov r10, r0

mov r11, r0

and r10, r8

and r11, r9

lsr r10

lsr r10

lsr r10

lsr r10

add r10, r7

add r11, r7

ret

ret

from_ascii:

; отнимаем от каждого байта ascii 0х30

ldi r16, 0x30

sub r0, r16

clr r16

ret

to_indicator:

;преобразуем двоичный код числа для индикатора

;Инициализация указателя на строку

ldi zh, high(ind*2)

ldi zl, low(ind*2)

add zl, r0

lpm

ret

LRC:

; не считаются ':', cr, lf - итого остается 9 байт

ldi r16, 0x09

mov r2, r16

clr r16

clr r3

ldi xh, high(string*2)

ldi xl, low(string*2)

adiw xl, 0x01 ; ':' не считается

loop:

ld r1, X

adiw xl, 0x01

add r3, r1

dec r2

brne loop

mov r4, r3

neg r4

sub r3, r4

mov r4, r3

and r3, 0xf0

lsr r3

lsr r3

lsr r3

lsr r3

and r4, 0x0f

add r4, r5

add r3, r5

ld r1, X

cp r1, r3

brne label

adiw xl, 0x01

ld r1, X

cp r1, r4

brne label

rjmp m

label: rcall error_frame

m: RET