INCLUDE "2313def.inc"; @ 8 МГц
.DEF tmp=r0
.DEF SSREG=r1
.DEF tem=r25
.DEF temp=r26
.DEF TheByte=r27
.DEF Time0=r16
.DEF Time1=r17
.DEF Time2=r18
.DEF TimeA=r19
.DEF TimeB=r20
.DEF Flags=r21
.EQU END_DATA_AREA=$DB; 41 запись общей длиной 123 байта
.CSEG
.ORG 0
rjmp Reset
.ORG OC1addr; $0004
nop
.ORG OVF1addr; $0005
in SSREG,SREG
inc Time0
brne NoOvf
inc Time1
brne NoOvf
inc Time2
NoOvf: ldi r30,$60
ldi r31,0
LoopCheck:; Loop of verify time for all records
set ; Флаг T указывает на совпадение текущего и заданного
Id tmp,Z+; Чтение младшего байта времени
cp tmp,Time0
breq E1
clt
Е1: Id tmp,Z+; Чтение среднего байта времени
cp tmp,Time1
breq E2
clt
Е2: Id tmp,Z+; Чтение последней тетрады времени (биты 0–3)
brtc NoMath; и типа события (биты 4–7)
mov tem,tmp
eor tem,Time2
andi tem,15
brne NoMath
mov tem,tmp; Время совпало, выполняем заданное действие
bndi tem,$F0
cpi tem,$00
brne Off0
cbi PORTB,0; Отключение канала 0
Off0: cpi tem,$10
brne On0
sbi PORTB,0; Включение канала 0
On0: cpi tem,$20
brne Off1
cbi PORTB,1: Отключение канала 1
Off1: cpi tem,$30
brne On1
sbi PORTB,1
On1: cpi tem,$40
brne Off2
cbi PORTB,2
Off2: cpi tem,$50
brne On2
sbi PORTB,2
On2: cpi tem,$60
brne Off3
cbi PORTB, 3
Off3: cpi tem,$70
brne On3
sbi PORTB,3
On3: cpi tem,$80
brne Off4
cbi PORTB,4
Off4: cpi tem,$90
brne On4
sbi PORTB,4
On4: cpi tem,$A0
brne Off5
cbi PORTB,5; Отключение канала 5
Off5: cpi tem,$60
brne On5
sbi PORTB, 5; Включение канала 5
On5: cpi tern,SC0
brne Off6
andi Flags,$FE; Отключение канала 6 (используется как будильник)
Off6: cpi tem,$D0
brne On7
ori Flags,1;Включение канала 6
On7: cpi tem,$E0
breq TimeReset; Обнуление счетчика времени
cpi tem,$F0
brne NoMath
TimeReset:;Если биты 4–7 равны 1, то сбрасываем счетчик времени
clr Time0
clr Time1
clr Time2
NoMath:
cpi r30,END_DATA_AREA
breq Loop_Check
rjmp LoopCheck
Loop_Check:
; Включение секундного светодиода
clr TimeB
sbi PORTB,7
out SREG,SSREG
reti
Reset:
; Установка указателя стека на максимальный адрес SRAM
ldi r30,$DF
out SPL,r30
; Настройка направления работы линий порта В
ldi r30,$FF
out DDRB,r30
ldi r30,$7Е
out DDR0,r30
; Режим работы таймера 1 со сбросом и прерыванием при совпадении
; Частота прерываний равна 8 000 000 / 256 / 31250 (7А12) = 1 Гц
ldi r30,12
ut TCCR1B,r30
ldi r30,$7A
out OCR1AH,r30
ldi r30,$12
out OCR1AL,r30
ldi r30,$CO
out TIMSK,r30
; Настройка WDT на 2 секунды
ldi r30,S0F
out WDTCR,r30
; Настройка UART на прием с параметрами 9600 8N1
ldi r30,$18
out UCR,r30
ldi r30,$33
out UBRR,r30
; Обнуление счетчика времени
clr Time0
clr Time1
clr Time2
; Задание тестовых точек включения (после отладки схемы убрать)
ldi r30,$05
sts $60,r30
ldi r30,$00
sts $61,r30
ldi r30,$10
sts $62,r30
ldi r30,$07
sts $63,r30
ldi r30,$00
sts $64,r30
ldi r30,$00
sts $65,r30
ldi r30,$0F
sts $66,r30
ldi r30,$00
sts $67,r30
ldi г30,$10
sts $68,r30
clr Flags
sei
UnlessLoop:
rcall GetByte; Прием сообщения говорящего о начале данных
cpi TheByte, 'T'
brne UnlessLoop
rcall GetByte
cpi TheByte,'i'
brne UnlessLoop
rcall GetByte
cpi TheByte,'m'
brne UnlessLoop
rcall GetByte
cpi TheByte,'e'
brne UnlessLoop
rcall GetByte
cpi TheByte,'r'
brne UnlessLoop
clr Time0; Обнуление счетчиков времени
clr Time1
clr Time2
ldi r28,$60
ldi r29,0
LoopRX:
rcall GetByte:; Чтение байта данных
St Y+,TheByte; Сохранение считанного байта
cpi r28,END_DATA_AREA
brlo LoopRX
rjmp UnlessLoop
ser Time0 ; Обнуление счетчиков времени
ser Time1
ser Time2
ldi r28,$10
out TCNT1L,r28
ldi r28,$7A
out TCNT1H,r28
; Процедура чтения байта с UАRТ
; Программа все свое свободное время находится внутри нее
GetByte:
wdr; Сброс сторожевого таймера
inc TimeA; Увеличение асинхронного счетчика времени
brne Early
inc TimeB
brne Early
cbi PORTB,7 ; Выключение секундного светодиода
Early:
sbrs Flags,0
rjmp NoBell
mov temp,TimeB; Звуковой сигнал включен
andi temp.$E7
breq NoBell
sbis PORTB,6; Инвертирование состояния вывода PB.6
rjmp NoCBI
cbi PORTB,6
rjmp NoBell
NoCBI: sbi PORTB.6
NoBell:
sbis USR,RXC
rjmp GetByte
in TheByte,UOR
ret
; Протокол управления таймером
; Формат загрузки расписания управления каналами от компьютера
; * Настройки порта 9600 8N1
; * Загрузка производится одним блоком, состоящим из 41-й записи
; * Перед блоком с записями надо отправить строку Timer
; * Каждая запись состоит из 3 байтов, сначала передается младший байт времени
; включения, затем средний, затем байт, состоящий из двух частей: младшие
; 4 бита — это самая старшая тетрада времени, бит 4 — это состояние, в которое
; будет переведен канал, и оставшиеся 3 бита — это номер канала. Если номер
; канала равен 7, то будет обнулен внутренний счетчик времени таймера и
; выполнение программы начнется сначала
; * Время считается с момента загрузки новой программы в секундах
. EXIT