3 регістри передачі 378h записати 1. У момент часу t2 приймач визначає, що поступив сигнал готовності від передавача і дані можна вважати. Приймач прочитує дані з приймального регістра (див. нижчий) і встановлює сигнал підтвердження прийому (ACK2). Це потрібно для того, щоб передавач зміг визначити, коли можна буде посилати наступні дані.
Якщо цього не зробити, то передавач може послати дані в той момент, коли пріємніх їх ще не рахував і це може привести до збою передачі або прийому.
Блок-схема загальної програми
У момент часу t3 передавач отримує сигнал підтвердження прийому (ACK2) від приймача і скидає сигнал готовності (ACK1). Це потрібно для того, щоб приймач зміг скинути свій сигнал підтвердження (ACK2). Якщо цього не зробити те цикл обміну буде порушений, оскільки в следущем циклі обміну передавач не знатиме чи прийняв приймач дані чи ні, якщо сигнал ACK2 буде завжди встановлений. У момент часу t4 приймач визначає, що сигнал готовності (ACK1) скинутий і скидає свій сигнал підтвердження прийому (ACK2). Таким чином завершується цикл обміну півбайтом - передавач знову готовий до передачі даних, а приймач - до прийому.
У наступному циклі посилається інший півбайт - якщо посилався молодший півбайт, то посилається старший і навпаки. У наступному за цим циклі обміну знову посилається молодший півбайт і т.д. При читанні даних з приймального регістра 379h слід враховувати, що битий 7 приймального регістра є інверсією бита 4 регістри передачі. Таким чином при читанні даних битий 7 приймального регістра необхідно інвертувати. При записі даних в регістр передачі 378h не слід змінювати значення бита 3, оскільки в даному варіанті алгоритму обміну він використовується для інших цілей.
Організація обміну по опитуванні При організації обміну даними по опиту можлива наступна реалізація приведеного вище алгоритму обміну (приклади дій зв'язані між собою):
Дії передавача
1. Дочекатися скидання сигналу підтвердження прийому даних (ACK2) попереднього циклу обміну:
mov dx, 379h
m1: in al, dx
test al, 40h
jnz m1
2. Записати передавані дані в регістр передачі 378h (у прикладі проводиться запис молодшого півбайта регістра BL):
mov al, bl
shl al, 1
and al, 00010000b
or al, bl
and al, 00010111b
mov dx, 378h
out dx, al
Блок-схема прийому
3. Виставити сигнал готовності (ACK1):
or al, 08h
out dx, al
4. Дочекатися приходу сигналу підтвердження прийому (ACK2) від приймача:
mov dx, 379h
m2: in al, dx
test al, 40h
jz m2
5. Скинути сигнал готовності (ACK1)
xor al, al
mov dx, 378h
out dx, al
Дії приймача
1. Дочекатися приходу сигналу готовності (ACK1) передавача:
mov dx, 379h
m3: in al, dx
test al, 40h
jz m3
2. Прочитати дані з приймального регістра 379h (у прикладі півбайт читається в регістр BL):
in al, dx
xor al, 80h
mov cl, 3
shr al, cl
mov bl, al
and bl, 07h
shr al, 1
and al, 00001000b
or bl, al
3. Виставити сигнал підтвердження прийому (ACK2):
mov al, 08h
mov dx, 378h
out dx, al
4. Дочекатися зняття сигналу готовності передавача (ACK1):
mov dx, 379h
m4: in al, dx
test al, 40h
jnz m4
5. Скинути сигнал підтвердження прийому (ACK2):
mov dx, 378h
xor al, al
out dx, al
Організація обміну по перериванню
При організації обміну по перериванню приймач приймає дані тоді, коли поступило переривання від LPT порту. Генерацію переривань LPT портом можна вирішити, встановивши біт 4 регістри управління (37Ah) в 1. Заборонити переривання можна скиданням даного біта. Коли переривання від LPT порту дозволені вони генеруються при зміні бита 6 приймального регістра (сигнал ACK) з 0 на 1. Таким чином, при організації обміну по перериванню в приймачі відсутня перевірка приходу сигналу готовності передавача (дія 1 приймача), оскільки обробник переривань від LPT порту буде викликаний відразу після появи сигналу готовності. Далі обробник переривань від LPT порту приймача виконує приведений вище цикл обміну без змін. Переривання порту LPT1 - 0Fh. Після закінчення обробки цього переривання слід послати сигнал EOI (End Of Interrupt - кінець переривання) в контроллер переривань.
Блок-схема передачі
3. Текст програми передачі файлу через LPT-порт
.286
.model tiny
.code
org 100h
start:
mov si,0 ; index 0
xor ch,ch
mov cl,cs:[80h] ; dovgina command line
mov bx, 81h ; pershyj symvol command line
l1: mov al,cs:[bx][si] ; chytaemo symvol
cmp al,'s' ; perevirjaemo 's'
jne filename
mov ah,cs:[bx][si+1] ; if al = 's' perevirjaemo nastupnyj
cmp ah,' ' ; if ah = ' '
jne filename
mov serv,1 ; vstanovluemo flag SEND
next: inc si ; cikl
loop l1
err_sysline:
mov dx,offset sys_line_err
mov ah,09h
jmp fin ; pomylka v parametrah
filename:
cmp al,' ' ; if al = ' '
je next ; chytaemo nastupnyj
cmp al,0dh ; if al = 0dh -> error
je err_sysline
mov fn_offset,si ; poluchaemo filemane
add fn_offset,bx
jmp next2
l2: mov al,cs:[bx][si] ; sukaemo end of filename
cmp al,' '
je eo_filename
next2: inc si
loop l2
eo_filename:
mov al,0 ; dodaemo v kinec filename 0,'$'
mov cs:[bx][si],al
mov al,'$'
mov cs:[bx][si+1],al
cmp serv,0
jz receive
jmp transmit
receive:
mov ah,3ch ; ctvoryty file
mov dx,fn_offset
mov cx,0 ; atribut
int 21h
mov handle,ax ; zberegty handle
mov dx,offset receive_mess
mov ah,09h
int 21h
mov dx,fn_offset
int 21h
receive_loop:
mov dx,378h ; skynuty ACK2
xor al,al
out dx,al
mov ah,00 ; zberegty timer
int 1ah
mov tick,dx
;;;;;;;; dochekatysja ACK1 on
ack1off:
mov dx,379h
in al,dx
test al,40h
jnz ack1on
call test_timeout ; perevirka timeout
cmp ah,09h
jne m1
jmp fin
m1: call test_esc ; perevirka Esc
cmp ah,09h
jne m2
jmp fin
m2:
jmp ack1off
ack1on:
mov dx,379h
in al,dx ; prochytaty piv baita
xor al,80h
mov cl,3
shr al,cl
mov bl,al
and bl,07h
shr al,1
and al, 00001000b
or bl,al
and bl,00001111b
not hi
cmp hi,0 ;
jz r_low_byte
mov bh,bl ; starshi piv baita v bh
shl bh,4
jmp receive_cont
r_low_byte: ; molodshi piv baita v bh
mov buf,bh
add buf,bl
mov dx,offset buf ; bufer
mov cx,1h ; kilkist bajt
mov bx,handle ; file handle
mov ah,40h ; zapysaty u file
int 21h
receive_cont:
mov al,08h ; vystavyty ACK2
mov dx,378h
out dx,al
mov ah,00
int 1ah
mov tick,dx
ack1up:
mov