На asm:
public Ini_COM1, Start_COM1
DGROUP group DATA
DATA segment word public 'DATA' use16
assume ds:DGROUP
Star_INT_0Ch dd 0 ; Адрес старого обработчика перывания 0Ch
Start_Data db 0 ; Переменная для контроля начала передачи
db 0
Shet_Size_Data dw 44 ; счетчик передаваемых данных
DATA ends
SYSTEM segment byte public 'CODE'
assume ds:DGROUP, cs:SYSTEM
;--------------------------------------------------------------------
;;;; < Обработчик прерывания СОМ 1 > ;;;;
;--------------------------------------------------------------------
New_INT_0Ch: ; Начало нового обработчика прерывания (0Ch)
; (INT 0Ch) - прерывание последовательного порта СОМ1
; вызывается, если порт СОМ1 получил данные.
push ax ; Сохранить ax в стек
push ds ; Сохранить ds в стек
push dx ; Сохранить dx в стек
push bx ; Сохранить bx в стек
Indet_INT:
;;;;;;{идентификация прерывания}
mov dx, 3FAh ; Адресс порта в dx (03FAh для чтения) - регистр
in al, dx ; Считать данные из порта 03FAh в al
and al, 07h ; Логическое И, обнуление 3-7 бит (00000111b)
cmp al, 2 ; Сравнение al с 2 (00000010b)-буфер передачи пуст. Сбрасывается после записи в 03F8h
je Vix_INT ; если равно, то на Vix_INT (прерывание по завершению передачи символа)
;;;;;;{сброс остальных прерываний}
; ---------------------------------------------------------------------------
;(сброс - пришли данные)
mov dx, 03F8h ; Адресс регистра передачи данных в dx
in al, dx ; Считать данные из порта 03F8h в al
jmp short $+2
;(сброс - состояние BREAK или ошибка)
mov dx, 03FDh ; Адресс регистра состояние break или ошибка в dx
in al, dx ; сбрасываем прерывание чтением из рег. состояния линии
jmp short $+2 ; задержка
;(сброс - изменилось состояние модема)
mov dx, 03FEh ; Адресс регистра состояния линии в dx
in al, dx ; сбрасываем прерывание чтением из регистра
jmp short $+2
jmp Exit_Indet_INT ; на выход
; ---------------------------------------------------------------------------
Vix_INT: ; прерывание по завершению передачи символа
;;;;;;{передача символа}
mov bx, Shet_Size_Data ; получаем значение счетчика
cmp bx, 44 ; сравнение
jge Exit_Indet_INT ; если больше или равно, то на метку, иначе
inc Shet_Size_Data ; инкремент, увеличиваем на 1
mov al, byte ptr Byffer_Peredahi+bx ; считываем значение из буффера передачи
mov dx, 03F8h ; адрес порта
out dx, al ; пишем в порт
;===============================
Exit_Indet_INT: ; послать в контроллер прерывания - прерывание обработано
mov dx, 0FF22h
mov ax, 0Ch
out dx, ax
pop bx
pop dx
pop ds
pop ax
iret ; возвращение в основную программу
;===============
; Инициализация СОМ 1
Ini_COM1 proc pascal near
push ds ; сохранить ds в стек
push es ; сохранить es в стек
push bx ; сохранить bx в стек
push dx ; сохранить dx в стек
mov ax, 350Ch ; АН = 35h, AL = номер прерывания (0Ch)
; (INT 0Ch) - прерывание последовательного порта СОМ1
; вызывается, если порт СОМ1 получил данные.
int 21h ; функция DOS: определить адрес старого обработчика
; (ES:BX)
mov word ptr Star_INT_0Ch, bx ; В bx смещение
mov word ptr Star_INT_0Ch+2, es ; В es сегментный адресс
mov ax, cs ; В ax адресс сегмента из cs (cs:SYSTEM)
mov bx, ds ; сохраняем ds в bx
mov ds, ax ; Установить ds на :SYSTEM (ds:SYSTEM)
assume ds:SYSTEM
lea dx, New_INT_0Ch ; Вычисление эффективного адреса New_INT_0Ch
mov ax, 250Ch ; АН = 25h, AL = номер прерывания (0Ch)
; сегментный адрес в DS
; смещение в DX
int 21h ; функция DOS: установить новый обработчик прерывания (0Ch)
mov ds, bx ; Востановить ds:DGROUP из bx
assume ds:nothing
;;;;;;{запрещение прерывания}
mov dx, 0FF28h ; Адресс порта в dx
in ax, dx ; Считать данные из порта 0FF28h в ax
and al, 0EFh ; Логическое И, обнуление 4 бита (11101111b)
out dx, ax ; Записать данные (ax) в порт (dx - (0FF28h))
;;;;;;{сбрасываем регистр данных}
mov dx, 3F8h ; чтением из порта 03F8h
in al, dx ; Считать данные из порта 3F8h в al
jmp short $+2 ; задержка
;;;;;;{сбрасываем регистр состояния линии}
mov dx, 3FDh ; чтением из порта 3FDh
in al, dx ; Считать данные из порта 3FDh в al
; 03FDh (для чтения) - регистр состояния линии
jmp short $+2 ; задержка
;;;;;;{сбрасываем регистр состояния модема}
mov dx, 3FEh ; чтением из порта 3FDh
in al, dx ;
jmp short $+2 ; задержка
;;;;{режим ввода делителя}
mov dx, 3FBh ;
mov al, 80h ; 7: бит DLAB : 1 = порты 3F8h и 3F9h в режиме ввода делителя
out dx, al ;
jmp short $+2
;;;;;;(Запись в Регистр управления модемом)
mov al, 00001100b ; (0Ch) Запись в Регистр управления модемом
; 0: 1 = установить выход DTR
; 1: 1 = установить выход RTS
; 2: 1 = установить OUT1 (не используется)
; 3: 1 = установить OUT2 (разрешить прерывания от RS-232)
mov dx, 3FCh
out dx, al
jmp short $+2
;;;;;;{младший байт делителя}
mov dx, 3F8h
mov al, 06h ; скорость 19 200
; задаем делитель скорости (0006h - 19200)
out dx, al ;
jmp short $+2
;;;;;;{старший байт делителя}
mov dx, 3F9h ;
mov al, 0 ; Скорость 19 200
out dx, al ;
jmp short $+2
;;;;;;{буферизация FIFO}(отключаем)
mov al, 00000000b ; бит 0 : Разрешение использования буферизации при приеме и предаче
; бит 1 : Сброс приемного буфера FIFO
; бит 2 : Сброс буфера FIFO передатчика
; биты 6-7: Установка значения числа символов в приемном буфере FIFO для
; инициирования прерывания (FIFO Trigger Level)
; 00 - 1 бит
mov dx, 3FAh
out dx, al
jmp short $+2
;;;;;;{режим работы}
mov dx, 3FBh
mov al, 00000011b ; Режим работы
; 0-1: число битов данных : 11 = 8 бит
; 2 : число стоп-битов : 0 = 1 стоп бит
; 3-4: тип четности : X0 = нет
; 5 : постоянная четность: 0 = отмена постоянной четности
; 6 : : 1 = имитировать обрыв линии
; 7 : бит DLAB : 0 = порты 3F8h и 3F9h в обычном режиме
out dx, al
jmp short $+2
;;;;;;(Запись в Регистр управления прерываниями)
mov al, 00000010b ; (5) Запись в Регистр управления прерываниями
; 0: прерывание по приему символа
; 1: прерывание по завершению передачи символа
; 2: прерывание по обрыву линии или ошибке в линии
; 3: прерывание по изменению состояния модема (любой из линий CTS, DSR, RI и DCD)
mov dx, 3F9h
out dx, al
jmp short $+2
; устанавливаем формат даты и времени "двоичный"
mov al,0Bh ; CMOS OBh - управляющий регистр В
out 70h,al ; порт 70h - индекс CMOS
in al,71h ; порт 71h - данные CMOS
or al,00000110b ; установить бит 1 и 2
; бит 1: 1/0 — 24-часовой/12-часовой режим
; бит 2: 1/0 — формат даты и времени двоичный/BCD
out 71h,al ; и записать обратно
pop dx ; восстановить dx основной программы
pop bx ; восстановить bx основной программы
pop es ; восстановить es основной программы
pop ds ; восстановить ds основной программы
retn
Ini_COM1 endp
;--------------------------------------------------------------------
; Подпрограмма Start_COM1 используется для передачи данных из буффера
; для передачи символов (44 байт) на дисплей
; ОПИСАНИЕ:
; Входные данные:
; DDD (Boolean) - управляющий сигнал (запуск передачи на дисплей)
; D_day (Integer) - день (число месяца)
; D_month (Integer) - месяц
; D_hour (Integer) - час
; D_min (Integer) - минут
; D_sec (Integer) - секунд
; D_N_pehi(Integer) - номер текущей печи
; D_minus (Integer) - минус или плюс
; D_M_min (Integer) - минут до выдачи
; D_M_sec (Integer) - секунд до выдачи
; D_Tok (Integer) - значение тока
Start_COM1 proc pascal near
arg DDD:word, D_day:word, D_month:word, D_hour:word, D_min:word, D_sec:word, D_N_pehi:word, D_minus:word, D_M_min:word, D_M_sec:word, D_Tok:word
;===============================
Push bx ; сохраняем регистр bx
Push dx ; сохраняем регистр bx
mov bx, DDD ; получаем адрес управляющей переменной (Boolean)(1 писать, 0 не писать)
mov al, byte ptr [bx] ; получаем значение переменной
cmp al,0 ; сравнение
jnz Next_Start_COM1 ; если не ноль, то на метку, иначе
jmp Exit_Start_COM1
Next_Start_COM1:
assume ds:DGROUP
mov bx, D_day ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Date_day, ax ; пишем в переменную
mov bx, D_month ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Date_month, ax ; пишем в переменную
mov bx, D_hour ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Date_hour, ax ; пишем в переменную
mov bx, D_min ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Date_min, ax ; пишем в переменную
mov bx, D_sec ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Date_sec, ax ; пишем в переменную
mov bx, D_N_pehi ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
mov bx, 100 ; делитель
xor dx, dx ; обнуление dx
div bx ; Целочисленное деление без знака
; ax на bx, результат в AX, остаток в DX
call AL_word ; вызываем подпрограмму
mov ds:Sotni_pehi, ah ; пишем в переменную
mov ax, dx ; остаток в ax
call AL_word ; вызываем подпрограмму
mov ds:Des_pehi, ax ; пишем в переменную
mov bx, D_M_min ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
cmp ax, 99 ; сравнение
jne D_M_min_Ne_99 ; если не равно, то на метку, иначе
mov ds:Plus_minus, 20h ; пишем в переменную " "(пробел)
mov ds:Plus_minus_min, 2020h ; пишем в переменную " "(два пробела)
mov ds:Plus_minus_sec, 2020h ; пишем в переменную " "(два пробела)
mov ds:Dvoetohie, 20h ; пишем в переменную " "(пробел)
jmp NNNN_
D_M_min_Ne_99:
mov bx, D_minus ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
cmp ax, 0 ; сравнение
jnz D_minus_ne_0 ; если не ноль, то на метку, иначе
mov ds:Plus_minus, 2Bh ; пишем в переменную "+"
jmp Next_Plus_minus
D_minus_ne_0:
mov ds:Plus_minus, 2Dh ; пишем в переменную "-"
Next_Plus_minus:
mov bx, D_M_min ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Plus_minus_min, ax ; пишем в переменную
mov bx, D_M_sec ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
call AL_word ; вызываем подпрограмму
mov ds:Plus_minus_sec, ax ; пишем в переменную
mov ds:Dvoetohie, 3Ah ; (3A) - :
NNNN_:
mov bx, D_Tok ; получаем адрес переменной
mov ax, word ptr [bx] ; получаем значение переменной
mov bx, 100 ; делитель
xor dx, dx ; обнуление dx
div bx ; Целочисленное деление без знака
; ax на dx, результат в AX, остаток в DX
call AL_word ; вызываем подпрограмму
cmp al, 30h ; сравнение
jne Ne_30h ; если не равно, то на метку, иначе
mov al, 20h ; пишем " " (пробел)
Ne_30h:
mov ds:Tok_ah, ax ; пишем в переменную
mov ax, dx ; остаток в ax
call AL_word ; вызываем подпрограмму
mov ds:Tok_al, ax ; пишем в переменную
;;;;;;{передача символа}
cmp Start_Data, 0 ; сравнение (Переменная для контроля начала передачи)
jnz Next_peredahi ; если не ноль, то на продолжение передачи, иначе
inc Start_Data ; инкремент (+1), начало передачи
mov Shet_Size_Data, 1 ; записываем значение счетчика
mov al, byte ptr ds:Byffer_Peredahi ; считываем значение из буффера передачи
mov dx, 03F8h ; адрес порта
out dx, al ; пишем в порт
jmp Exit_Start_COM1 ; на выход
Next_peredahi:
inc Start_Data ; инкремент (+1) чтобы раз в 256 сек. перезапускать дисплей
mov Shet_Size_Data, 4 ; записываем значение счетчика
mov al, byte ptr ds:Byffer_Peredahi+3 ; считываем значение из буффера передачи
mov dx, 03F8h ; адрес порта
out dx, al ; пишем в порт
Exit_Start_COM1:
;===============================
pop dx ; востанавливаем регистр dx
pop bx ; востанавливаем регистр bx
ret ;все остальное додумает ассемблер (T320+)
Start_COM1 endp