INCLUDE MACROS80.ASM
; ======================================================================
; ----------------------------------------------------------------------
; Константы:
;
; Адреса запуска программ в ОЗУ и ПЗУ
CONST:
RAM_BASE EQU 04000h ; Адрес запуска в ОЗУ
ROM_BASE EQU 0F800h ; Адрес запуска в ПЗУ
IO_BASE EQU 0C8h ; Адрес програмируемого интерфейса
CT_BASE EQU 074h ; Адрес таймера
; Программируемый интерфейс IO
; Режимы работы программируемого интерфейса - биты байта состояния
IOSB_SETMODE EQU 10000000b ; IO STATUS BITS
IOSB_SETCBITS EQU 00000000b
IOSB_AMODE0 EQU 00000000b
IOSB_AMODE1 EQU 00100000b
IOSB_AMODE2 EQU 01000000b
IOSB_A70IN EQU 00010000b
IOSB_A70OUT EQU 00000000b
IOSB_C74IN EQU 00001000b
IOSB_C74OUT EQU 00000000b
IOSB_BMODE0 EQU 00000000b
IOSB_BMODE1 EQU 00000100b
IOSB_B70IN EQU 00000010b
IOSB_B70OUT EQU 00000000b
IOSB_C30IN EQU 00000001b
IOSB_C30OUT EQU 00000000b
; Адреса портов программируемого интерфейса (IO)
IO_MODE_PORT EQU IO_BASE+03h ; Порт программирования IO
IO_C_PORT EQU IO_BASE+02h ; Порт C
IO_B_PORT EQU IO_BASE+01h ; Порт B
IO_A_PORT EQU IO_BASE+00h ; Порт A
; Константы для работы с IO
IO_MODE = IOSB_SETMODE+IOSB_AMODE0+IOSB_A70IN+IOSB_C74IN+IOSB_BMODE0
IO_MODE = IO_MODE+IOSB_B70OUT+IOSB_C30OUT
; Таймер CT:
; Режимы работы таймеров - биты байта состояния
CTSB_TIMER0 EQU 00000000b ; CT STATUS BITS
CTSB_TIMER1 EQU 01000000b
CTSB_TIMER2 EQU 10000000b
CTSB_STOP EQU 00000000b
CTSB_LOWBYTE EQU 00010000b
CTSB_HIGHBYTE EQU 00100000b
CTSB_TWOBYTES EQU 00110000b
CTSB_MODE0 EQU 00000000b
CTSB_MODE1 EQU 00000010b
CTSB_MODE2 EQU 00000100b
CTSB_MODE3 EQU 00000110b
CTSB_MODE4 EQU 00001000b
CTSB_MODE5 EQU 00001010b
CTSB_BINCODE EQU 00000000b
CTSB_BINDECCODE EQU 00000001b
; Адреса портов таймера (CT)
CT_MODE_PORT EQU CT_BASE+03h ; Порт программирования CT
CT_TIMER2_PORT EQU CT_BASE+02h ; Таймер 2
CT_TIMER1_PORT EQU CT_BASE+01h ; Таймер 1
CT_TIMER0_PORT EQU CT_BASE+00h ; Таймер 0
; Константы для работы с таймерами
TIMER_MODE_PORT EQU CT_MODE_PORT
TIMER_STATE_PORT EQU IO_C_PORT
TIMER0_FREQUENCY EQU 1000 ; Задание основного тактирования по T0, Гц
TIMER0_DELAY EQU 2000000 / TIMER0_FREQUENCY
TIMER0_MODE = CTSB_TIMER0+CTSB_TWOBYTES+CTSB_MODE2+CTSB_BINDECCODE
TIMER1_MODE = CTSB_TIMER1+CTSB_TWOBYTES+CTSB_MODE0+CTSB_BINCODE
TIMER2_MODE = CTSB_TIMER2+CTSB_TWOBYTES+CTSB_MODE0+CTSB_BINCODE
; Прочие константы
; Константы для работы с нагревателем
HEATER_MODE_PORT EQU IO_C_PORT
HEATER_STATE_PORT EQU IO_A_PORT
HEATER_ON EQU 1
HEATER_OFF EQU 0
; ОСНОВНАЯ ПРОГРАММА
; См. входные параметры подпрограмм
ORG RAM_BASE ; Эта программа находится в ОЗУ
mvi a,IO_MODE ; Инициализация контроллера ввода-вывода
out IO_MODE_PORT
xra a ; Очистка аккумулятора
call Restart_Timer ; Запуск таймера 0
; === Работа на участке 1 (dT=-50C, dt=5сек)
mvi a,200 ; Начальная температура
mvi b,TIMER0_FREQUENCY * 5 SHR 4 ; Время регулировки 5 секунд
mvi c,TIMER0_FREQUENCY * 5 AND 0FFh
mvi d,TIMER0_FREQUENCY * 5 / 50 SHR 4 ; Время изменения T
mvi e,TIMER0_FREQUENCY * 5 / 50 AND 0FFh ; на 1 градус
mvi h,-1 ; Уменьшать температуру
call reg
; === Работа на участке 2 (dT=0, dt=5сек)
mvi a,150 ; Начальная температура
mvi d,0FFh ; Время изменения температуры
mvi e,0FFh ; велико (T = const)
mvi h,0 ; температура постоянна
; === Работа на участке 3 (dT=-100C, dt=2сек)
mvi b,TIMER0_FREQUENCY * 2 SHR 4 ; Время регулировки 2 секунды
mvi c,TIMER0_FREQUENCY * 2 AND 0FFh
mvi d,TIMER0_FREQUENCY * 2 / 100 SHR 4 ; Время изменения температуры
mvi e,TIMER0_FREQUENCY * 2 / 100 AND 0FFh ; на 1 градус
; === Отключение нагревателя
call Off_Heater
; === Завершение программы
hlt
; Подпрограммы для работы с нагревателем
; On_Heater и Off_Heater: включить и выключить нагреватель соответственно
; ВХОД: НЕТ
; ВЫХОД: НЕТ
; РЕГИСТРЫ: НЕ ИЗМЕНЯЕТ
; ФЛАГИ: НЕ ИЗМЕНЯЕТ
On_Heater:
push b
mov b,a
mvi a,HEATER_MODE_PORT
out HEATER_ON
mov a,b
pop b
ret
Off_Heater:
out HEATER_OFF
; Heater_Control: подпрограмма поддержки заданной температуры. Если
; температура больше или равна заданной, выключает нагреватель,
; иначе включает.
; ВХОД: a - заданная температура
; ВЫХОД: если нагреватель включен CF=1, иначе CF=0
; ФЛАГИ: CF
Heater_Control:
in HEATER_STATE_PORT
cmp b
jnc Temperature_Is_Normal
call On_Heater
jmp Exit_Heater_Control
Temperature_Is_Normal:
Exit_Heater_Control:
; Подпрограммы для работы с таймерами
; Restart_Timer - запуск таймера на отсчёт N отрезков.
; ВХОД: a - номер таймера
; b,c - число отрезков для отсчёта для таймеров 1 или 2
Restart_Timer:
push psw
jnz IsTimer1
mvi a,TIMER0_MODE ; Инициализация таймера 0
out TIMER_MODE_PORT
mvi a,TIMER0_DELAY AND 0FFh ; Ввод младнего байта величины задержки
out CT_TIMER0_PORT
mvi a,TIMER0_DELAY SHR 4 ; Ввод старшего байта
jmp Exit_Restart_Timer
IsTimer1:
dcr a
jnz IsTimer2
mvi a,TIMER1_MODE
mov a,c
out CT_TIMER1_PORT
IsTimer2:
jnz Exit_Restart_Timer
mvi a,TIMER2_MODE
out CT_TIMER2_PORT
Exit_Restart_Timer:
pop psw
; Check_Timers - проверить, не было ли срабатывания таймера
; ВЫХОД: если сработал таймер 1, установит бит 1 аккумулятора,
; если таймер 2 - бит 2 (т.е. 1 - таймер 1, 2 - таймер 2)
; кроме того, если таймер сработал, установит флаг CF
; РЕГИСТРЫ: a
Check_Timers:
stc
in TIMER_STATE_PORT
ani 11000000b
jnz TimeOut
cmc
TimeOut:
rlc ; Rotate bits to positions 0 and 1
rlc
; Подпрограмма регулирования температуры
; Reg: регулирование температуры
; ВХОД: a - начальная температура
; b,c - тактов таймера 0 до окончания регулирования
; d,e - тактов таймера 0 до изменения уставки по T
; h - направление изменения T - +1, -1 или 0
Reg:
push b ; Сохранить все основные регистры
push d
push h
push psw ; Запустить таймер 2 на счёт времени
mvi a,2 ; регистры b,c уже установлены, см. ВХОД
call Restart_Timer
push d ; Регистровую пару (d,e) поместить в (b,c)
mov d,a ; Store temperature in d
T_Changed:
mvi a,1 ; Таймер 1...
call Restart_Timer ; ... запустить на подсчёт времени до новой уставки
Reg_Next:
mov a,d ; Восстановим уставку T
call Heater_Control ; Подрегулируем температуру
call Check_Timers ; Проверим, не сработал ли таймер
jnc Reg_Next
cpi 1
jnc Exit_Reg ; Если сработал таймер 2 (ВРЕМЯ) - на выход
mov a,d
add h ; Иначе изменим уставку по температуре,
mov d,a ; сохраним её
jmp T_Changed ; и перезапустим подсчёт времени уставки
Exit_Reg:
pop psw ; restore general registers
pop h
pop d
ENDALL