Fig 2.5.2 Structura registrului de control
Registrul de control este de tip write-only și poate fi accesat utilizând instrucțiunea OUT și portul de adresă 64h. Fiecare octet trimis pe această cale este perceput de controlerul tastaturii ca o comandă. Pentru a scrie comenzile de tastatură în buffer-ul de intrare se utilizează o instrucțiune OUT, ce conține codul comenzii, prin portul 60h.
Câteva exemple de funcții de tastatură sunt următoarele:
aah – autotest (controlerul de tastatură execută un test și scrie octetul 55h în bufferul de ieșire dacă nu se detectează nicio eroare)
adh – dezactivare tastatură
aeh – activarea tastatură
c0h – citire port intrare ( citește portul de intrare și transferă datele în portul de ieșire)
d0h – citire port ieșire ( citește portul de ieșire și transferă datele în bufferul de ieșire)
d1h – scriere port ieșire (scrie octetul de date următor în portul de ieșire)
O secvență pentru dezactivarea tastaturii este următoarea:
start :
IN AL, 64h ; citește registrul de stare
TEST AL,02h ; verifică dacă buffer-ul de intrare este plin
JNZ start ; așteaptă cât timp un caracter este în buffer
OUT 64h, 0ADh ; activează tastatura
Transferul de date între controlerul tastaturii și tastatura în sine se realizează utilizând buffer-ele de intrare/ieșire. Buffer-ul de intrare poate fi accesat utilizând instrucțiunea OUT la portul de adresă 60h, numai dacă bitul INPB al registrului de stare are valoarea 0. Octeții din buffer-ul de intrare aparțin unei comenzi de control generată în avans la adresa de port 64h și sunt eventual transferați la controlerul de tastatură.Pentru a trimite o comandă de la controler la tastatură, octetul trebuie scris în buffer-ul de intrare al controlerului, care atunci când transferă comandă o interpretează și ulterior o execută.
2.5.2 Recepționarea caracterelor de la tastatură
Controlerul scrie toate datele în urma comenzii de control primită de la CPU în buffer-ul de ieșire. Atunci când se apasă o tastă, tastatura trimite un cod de scanare sub formă SDU la controlerul de tastatură, care îl scrie mai departe în buffer-ul de ieșire. Cu alte cuvinte, controler-ul generează prin IRQ1 o întrerupere hardware INT 09h dacă a recepționat un caracter de la tastatură și scrie caracterul în buffer-ul de ieșire. Rutina de tratare a acestei întreruperi aduce caracterul caracterul utilizând o instrucțiune IN prin portul 60h, determină codul ASCII și pune ambele date în buffer-ul tastaturii din spațiul de date al BIOS-ului.
Codurile de scanare reprezintă un număr întreg pe 8 biți de ordine al unei anumite taste care are valoarea cuprinsă între 1 și numărul total de taste. Dacă o tastă este apăsată un timp mai îndelungat, este generat în mod repetat același cod de scanare până când tasta este eliberată. Codul de scanare care se generează la eliberarea unei taste este la fel cu cel generat la apăsarea ei cu excepția bitului 7 (cel mai semnificativ bit) care primește valoarea 1. Spre exemplu, tasta ESC produce codul 01h la apăsare și 81h la eliberare.
Handler-ul întreruperii 09h citește codurile de scanare de la tastatură și le convertește în acțiuni sau coduri de caractere astfel:
-
Pentru tastele ASCII, atunci când se întâlnește codul de scanare, se plasează codul ASCII și codul de scanare al tastei în zona tampon a tastaturii care are o dimensiune de 32 de octeți și este aflată la adresa 0000:041Eh
-
Pentru tastele ALT, CTRL sau SHIFT se actualizează octeții de stare de la adresele 0000:0417h și 0000:0418h
-
Dacă se apasă CTRL+ALT+DEL se inițializează octeții de la adresa 0000:0472h cu valoarea 1234h
2.5.3 Comenzi pentru tastatură
Tastaturile AT pot implementa anumite comenzi care se transmit prin intermediul buffer-ului de intrare al controlerului de tastatură. Câteva astfel de comenzi sunt:
Edh – turn on/off LEDS (aprinde/stinge LED-urile tastaturii și returnează EEh)
Eeh – echo (returnează octetul Eeh)
F0h – set/identify scan codes (setează un cod și identifică codul scanat curent)
F2h – identify keyboard (identifică tastatura)
F3h – set repetition rate/delay (setează rata de repetiție și întârziere a tastaturii)
FEh – resend (tastatura transferă ultimul caracter transmis din nou)
FFh – reset (se execută un reset intern al tastaturii)
-
Comanda Turn on/off LEDS : După ce s-a transmis comanda, tastatura trimite un semnal ACK către controler, anulează citirea matricei de scanare și așteaptă octetul indicator de la controler, care va fi transmis rin buffer-ul de intrare.
Fig 2.5.3.1 Structura octetului indicator
Exemplu: Aprinderea LED-ului NumLock şi stingerea celorlalte
OUT 60h, EDh ; trimite comanda "turn on/off LEDs"
wait: IN AL, 64h ; citeşte registrul de stare
TEST AL, 02h ; verifică dacă buffer-ul de intrare este plin
JNZ wait ; aşteaptă cât timp buffer-ul de intrare e plin
OUT 60h, 02h ; aprinde LED-ul NumLock
-
Comanda Echo: Verifică calea de transfer și logica de comandă a tastaturii. Atunci când tastatura a recepționat o comanda, ea returnează un octet ca răspuns EEh ce corespunde ecoului întors de la controler.
-
Comanda Set/Identify Scan Codes : Selectează unul din seturile de coduri de scanare și anume 01h,02h sau 03h. Standard se utiliează codul de scanare 02h. Valoarea 00h anunță tastatura ca trebuie să returneze pe lângă semnalul de ACK un octet care specifică codul de scanare activ pe setare.
-
Comanda Identify Keyboard : Determină dacă este conectată sau nu o tastatură. Tastaturile de tip PC nu produc niciun răspuns și din această cauză conduc deseori la apariția unei erori de time-out. Tastaturile de tip AT, însă, returnează un semnal ACK.
-
Comanda Set repetition rate/delay : Oferă posibilitatea de a seta rata de repetiție și întârzierea tastaturilor AT. După ce s-a transmis o comandă, tastatura returnează un semnal ACK și așteaptă octetul de date.
-
Comanda Resend : Dacă în timpul transferului de date între tastatură și controler apare o eroare, această comandă solicită retransmiterea ultimului caracter.
-
Comanda Reset : Efectuează un test intern al tastaturii. După ce se recepționează un octet de comandă, tastatura transmite un semnal ACK iar controlerul trebuie să răspundă prin modificarea perioadei liniilor de date și ceas la 500µs. În aceste condiții tastatura îndeplinește cererea testului BAT (basic assurance test). Dupa finalizarea acestui test, se trimite către controler fie un cod AAh (test passed) fie FCh (keyboard error). Pentru a seta perioada liniilor de date și ceas se utilizează biții 6 și 7 din portul de ieșire.
2.5.4 Crearea unui driver în limbaj de nivel înalt [Bib7,Bib6]
În cadrul acestui subcapitol se vor prezenta exemple de programe scrise în limbaj de nivel înalt ce au rolul de a realiza legătura între sistemul de operare și tastatură în sine. Înainte de asta, însă , este important să fie făcută o diferență clară între spațiul kernel și spațiul utilizatorului, cele două fiind menționate în figura 2.1.1 (pag 1).
Prin urmare, spațiul kernel administrează simplu și eficient partea hardware a dispozitivului, oferindu-i utilizatorului o interfață uniformă de programare. În acest mod, kernel, îndeosebi driver-ele dispozitivelor, formează o punte sau o interfață între utilizator/programator și componenta hardware. Orice subrutină sau funcție care face parte din kernel (cum ar fi module și driver-e de dispozitive) este considerată ca aparținând spațiului kernel.
În spațiul utilizatorului se regăsesc programe de tipul shell al UNIX sau alte aplicații bazate pe GUI (spre exemplu, kpresenter). Evident, aceste aplicații trebuie să interacționeze cu partea hardware a sistemului. Cu toate acestea, ele nu inteacționează direct ci prin intermediul funcțiilor spațiului kernel.
Dacă se dorește utilizarea instrucțiunilor prezentate mai sus în cadrul unui program scris într-un limbaj de nivel înalt, cum ar fi C, acest lucru se poate realiza utilizând prefixul asm și introducerea directivei #pragma inline pentru a anunța compilatorul că urmează să se folosească astfel de instrucțiuni.
Ex: asm {
start :
IN AL, 64h
TEST AL,02h
JNZ start
OUT 64h, 0ADh
}
Dacă se dorește implementarea unor noi rutine de tratare a întreruperilor hardware și software și instalarea lor în locul celor existente, limbajul C pune la dispoziție următoarele funcții:
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt(*old_intr)(__CPPARGS);
void interrupt newIntr(__CPPARGS) {... }
Această funcție reprezintă echivalentul în C al funcției 35h a întreruperii 21h. Prin prima instrucțiune se definește o variabilă de tip întrerupere numită old_intr în care se poate salva adresa vechii rutine de tratare a întreruperii. A doua instrucțiune reprezintă declararea unei noi rutine de tratare a întreruperii. Constanta “__CPPARGS” este folosită drept parametru pentru cele două instrucțiuni și este necesară pentru a putea face diferența între definirea unei întreruperi în C și una în C++.
Pentru a prelua adresa unei rutine de tratare a unei întreruperi se folosește funcția getvect care are prototipul:
old_intr = getvect(nr_intr);
Unde nr_intr reprezintă indexul întreruperii de la care se dorește preluarea vectorului de întrerupere. Funcția returnează adresa rutinei de tratare a întreruperii respective.
void interrupt(*old_21h)(...); //declaraţie – pointer la o funcţie de tip întrerupere
…………………………………………
old_21h = getvect(0x21); // citirea vectorului de întreruperi
Pentru scriererea noi adrese a rutinei în tabela vectorilor de întreruperi se folosește funcția setvect:
void setvect(int nr_intr, void newIntr);
unde nr_intr reprezintă indexul întreruperii iar newIntr reprezintă adresa noii rutine de tratare a înreruperii.
Următorul exemplu de program este utilizat pentru a apela tastele cursor. În acest caz nu se poate utilize funcția predefinită getch() deoarece ea este utilizabilă doar în cazul tastelor ce conțin caractere sau numere. Pentru tastele cursorului (săgețile) sau pentru tastele cu funcții sunt necesare coduri precum cel de mai jos.
#include
#include /* pentru kbhit */
#include
int getkey(void);
void main(void)
{
int key;
while(1)
{
if (kbhit)
{
key=getkey();
printf("%d %x\n", key, key);
}
}
}
int getkey(void)
{
union REGS in, out;
in.h.ah = 0x08;
int86(0x21, &in, &out);
if (out.h.al == 0)
{
return(getkey()+0x100);
}
else
{
return(out.h.al);
}
}
Câteva întreruperi pot fi executate din software utilizând funcția int86. Întreruperea de nivel 21 a fost dezvoltată de către fondatorii originali ai DOS-ului ca o intefață standard de colectare a informații specifice.Identitatea informației specific este introdusă în octetul mare al registrului A(in.h.ah).De exemplu, dacă în h.ah este 0x2a, anul, luna, ziua și ziua actuală a săptămânii sunt returnate în mai mulți regiștrii.
Valorea din ih.h.ah pentru a citi tastatura este 0x08 și valorea caracterului este returnată în octetul inferior a lui A (out.h.al). Aceasta funcționează pentru apăsările obișnuite ale tastelor.
Cu toate acestea, IBM a avut nevoie de mai mult de 256 de caractere care pot fi găzduite într-un octet.Așadar, ei au definit un “ASCII extins” prin rezervarea codului 0x00 de întoarcere la o medie. Așadar, dacă nu se mai apasă caracterul c’, out.h.a va fi 0x63 care este valorea în ASCII a caracterului c’.
Dar, dacă nu se apasă tasta săgeții drepte, out.h.al va fi 0x00 și un al doilea apel utilizând int86 va returna 0x4d. Adică, codul ASCII pentru săgeata de dreapta este 0x00 0x4d.
În program, dacă out.h.al este egal cu zero, funcția getkey() este din nou apelată S-a adăugat 0x100 rezultatului pentru a indica rezultatul ca fiind ASCII extins. Așadar, în programul rulat, dacă nu se mai ține apăsată tasta c’ este afișată valorea 0x63. Dacă nu se mai apasă pe săgeata de dreapta se afișează 0x14d.
2.6 ANEXĂ
Fig 2.1.1 - https://technet.microsoft.com/en-us/library/cc776371(v=ws.10).aspx
Fig 2.2.1- http://www.computerhope.com/jargon/p/pcxtkeyb.htm
Fig 2.2.2 - http://www.pcguide.com/ref/kb/layout/stdAT84-c.html
Fig 2.2.3 - http://www.ethoberon.ethz.ch/images/uskeyb.gif
Fig 2.2.4 - http://wiki.logkeys.googlecode.com/git/images/keyboard.png
Fig 2.2.5 - http://media.engadget.com/img/product/10/8fo/microsoft-wireless-multimedia-keyboard-1-1-hov-800.jpg
Fig 2.3.1 - http://smg.photobucket.com/user/guggenheim/media/din5pin.jpg.html
http://i00.i.aliimg.com/wsphoto/v0/790470416_2/5-Pin-DIN-male-Plug-Cable-Connector-with-Plastic-Handle.jpg
Fig 2.3.2.1 - http://www.e-ucenje-kel.ftn.uns.ac.rs/eSite/images/stories/AVR/AVR_PS2_tastature/PS2MaleConnector%20pinout.png
http://www.ps2mouse.com/images/PS2connection_sm.jpg
Fig 2.3.2.2 - Radu Rădescu “Echipamente periferice”
Fig 2.3.3 - https://www.keelog.com/images/usb_pinout.gif
Fig 2.4.1, 2.5.1, 2.5.2, 2.5.3.1 - http://www.cs.ucv.ro/staff/cpatrascu/SIE.php
2.7 Bibliografie
1. Radu Rădescu, Echipamente periferice, Editura Electra, Bucureşti, 2006.
2. Z. Baruch, Sisteme de intrare/iesire ale calculatoarelor, Editura Albastra, Cluj-
Napoca, 2003.
3. http://www.cs.ucv.ro/staff/cpatrascu/SIE.php
4. http://www.Computer-Engineering.org
5. A.S. Tanenbaum, Operating Systems – Design and Implementation, Prentice Hall Software Series, Ediţia a 3-a, 2006
6. http://webspace.ulbsibiu.ro/daniel.morariu/html/StudentDoc/IPC/Indrumar_IPC.pdf
7. http://www.phanderson.com/C/getkey.html
Gestiunea de catre utilizatori
-
Introducere
Faptul ca lucrurile functioneaza intr-un anume mod ne-a fascinat dintodeauna ca oameni ai stiintei, ai ratiunii. Ce face norii sa nu cada? De ce exista anotimpuri? Ce face ca apa sa fiarba, plantele sa fie verzi sau cerul albastru? Omul de stiinta se deosebeste de ceilalti prin faptul ca nu suporta sa nu cunoasca raspunsul la asemenea intrebari. In anii nostri mai tineri acul unei busole era destul de frustrant. Faptul ca acel ac se comporta intr-un mod atat de hotarat “nu se potrivea deloc cu natura evenimentelor... in lumea lipsita de constiinta a conceptelor.”
In cazul acesta, in spatele lucrurilor trebuie, cu siguranta, sa se afle ceva adanc ascuns, un adevar imposibil de observat fara o inspectie atenta. Probabil aceasta este cauza din care atat de multi dintre noi isi desfaceau jucariile atunci cand voiam sa aflam cum functioneaza.
Acelasi lucru vom incerca si in lucrarea aceasta, vom incerca sa disecam la nivel teoretic problema dispozitivelor de intrare-iesire, pentru ca, spre deosebire de mai marile si mult mai complicatele subiecte ale ratiunii cum ar fi conceptele filosofice sau teorema relativitatii, avem de-a face cu obiecte facute de om, pe care le intelegem in intregime.
Tehnologia este cu siguranta lucrul de care noi oamenii am ajuns sa depindem cel mai mult. Progresele tehnologice, cu mult mai rapide in comparatie cu progresele curentele lingvistice sau cele artistice, au creeat o nevoie ca utilizatorii sa detina cat mai mult control asupra a ceea ce vor sa obtina prin procesul tehnologic.
Aici intervin dispozitivele de intrare - iesire. Acestea, impreuna cu interfetele de intrare iesire creeaza posibilitatea comunicarii lume-masina. Poate aceasta e o viziune prea romantica pentru niste suflete matematice ca ale celor ce probabil ca vor citi mterialul acesta insa este o metafora potrivita a realitatii.
Diagrama urmatoare arata organizarea pe care am urmarit-o in scrierea acestui material.
3.2.Clasificare
2.a Din punct de vedere funcțional, dispozitivele periferice se împart în:
2.a.i. dispozitive periferice de schimb: imprimanta, plotter-ul, rețelele de comunicare cu alte periferice;
2.a.ii. dispozitive periferice purtătoare de informatii permanent pe medii magnetice: benzile magnetice, discurile (hard-discurile, dischetele);
Preluarea datelor de pe aceste suporturi se face prin intermediul unui cap de citire. Benzile magnetice sunt dispozitive cu acces secvential la informatiile memorate. Capul de citire are pozitie fixa si el citeste la un moment dat continutul benzii care este in dreptul sau.
La discurile magnetice, informatia poate fi accesata in mod direct. Citirea se face prin deplasarea capului de citire pana in dreptul zonei de pe disc unde este memorata informatia cautata.
Observatie: Discurile si benzile magnetice pot fi discutate si in contextul unitatilor de memorie auxiliara
2.b Din punctul de vedere al direcției de transfer al informației, dispozitivele periferice se clasifică în:
2.b.i. Dispozitive periferice de intrare (input device): tastatura, mouse, scanner, joystick, touch board, touch screen, touch pad, microfon, webcam, creion grafic, etc
2.b.ii. Dispozitive periferice de ieșire (output device): monitor, imprimanta, boxe, căsti, etc.
2.b.iii. Dispozitive periferice de intrare/iesire (I/O device): hard disk, memorie flash, streamer, CD-RW, DVD-RW, MO-disk, RAM/static-drive, placa de retea, router, switch (comutator).
Din aceasta categorie fac parte si retelele interne destinate comunicarii intre periferice.
Dispozitivele care sunt folosite pentru a introduce datele și programele din computer sunt cunoscute sub numele de "Dispozitive de intrare". Un dispozitiv de intrare are funcţia de a citi datele și de a le converti într-o formă pe care un calculator poate să le utilizeze.
Dispozitivele de ieșire transformă produsul final al prelucrării mașinii într-o formă utilizabilă de către om. Acesta oferă comunicarea computerului cu utilizatorul.
2.c Din punct de vedere al tipului de transfer:
2.c.i dispozitive periferice caracter;
2.c.ii dispozitive periferice bloc;
Diferența dintre acestea se poate observa datorită literei care apare pe prima coloană în ieșirea comenzii ls-1, această coloană indică tipul fișierului. Fișierele care au tipul C indică dispozitivele de tip caracter, iar cele care au tipul B indică dispozitivele de tip bloc.
Unele dintre dispozitive sunt generate de kernel si au componente aparte. Acestea se numesc pseudo-dispozitive.
Dispozitivele caracter corespund dispozitivelor care transmit câte un caracter odată. Acestea trimit sau primesc un șir de caractere(stream) fără nicio organizare a informației pe adrese, de aceea nu se poate accesa o anumită porțiune.
Dispozitivele bloc corespund dispozitivelor care lucrează cu datele la nivel de bloc (citesc,scriu,sterg blocuri de date). Acestea memorează informația în blocuri de dimensiuni fixe (512 la 32,768byte) fiecare cu adresa proprie. Caracteristica fundamentală a acestora este ca informația poate fi citită doar din blocurile care interesează, desigur pentru un cost de timp (ex: hard-disk).
Dispozitivele care funcționeaza astfel sunt cele de stocare:
-
Fizice - unităti CD-ROM/DVD-ROM, hard-diskuri
-
Virtuale – dispozitive loop
-
Asociate zonelor de memorie
Dispozitivele de tip bloc sunt mult mai performante decât cele de tip caracter, deoarece viteza celor de tip bloc este mult mai mare decât celelalte. Importanța acesteia este foarte mare, pentru ca Linux tratează diferit cele două tipuri de dispozitive. Pe când ,Windows, prin intermediul I/O managerul oferă o interfața unificata pentru tratarea dispozitivelor.
2.c.ii.1. Subsistemul block I/O
Lucrul cu dispozitivele de tip caracter e mult mai ușor față de celelalte. Acestea au o singură pozitie curentă, în timp ce cele de tip bloc trebuie să se poată mișca la orice poziție din dispozitiv pentru asigurarea accesului aleator la date. Pentru a simplifica lucrurile cu dispozitivele de tip bloc, nucleul Linux pune la dispozitie un întreg subsistem denumit subsistemul block I/O (block layer).
Cererile de citire/scriere sunt create de nivelurile de cod superioare subsistemului de I/O din nucleu. De obicei, subsistemul care creează cereri pentru dispozitive de tip bloc este subsistemul de gestiune a fiierelor. Subsistemul de I/O actionează ca intermediar între subsistemul de gestiune a fisierelor si driverul de dispozitiv de tip bloc. Principalele operatii care intră în responsabilitatea subsistemului de I/O sunt adăugarea cererilor în coada de cereri a dispozitivului de tip bloc specifici sortarea si comasarea cererilor (sorting and merging) din considerente de performanță.
Pseudo-dispozitivele (ceasurile) sunt o serie de dispozitive care nu corespund unei componente hardware. Acestea pot fi echivalente unor dispozitive virtuale care implementează comportamentul dispozitivelor normale de tip caracter.
-
Modalitati de transfer I/O
3.a Prin program
3.a.i Transfer direct
La acest tip de transfer, toate transferurile se iniţiază şi se controlează prin program. Transferul poate fi direct, caz în care procesorul citeşte un port de intrare (PI) sau scrie un port de ieşire (PO), fără nici o verificare prealabilă a stării perifericului corespunzător portului. Acest mod de transfer se foloseşte pentru sistemele simple de control numeric, dedicate unor aplicaţii fixe, în faza de proiectare şi testare a transferului (program plus hardware), sau în cazul rulării unor rutine de iniţializare a circuitelor programabile de interfaţă.
Transferul presupune transferul datelor între unitatea centrala de prelucrare si modulul de intrare/iesire, unitatea centrala de prelucrare executänd un program prin care controleaza direct operatia de intrare/iesire.
Transferul se realizeaza în urmatoarele etape: - sesizarea starii perifericului; - transmiterea unei comenzi de citire/scriere; - transferul propriu-zis al datelor. Executia unei instructiuni de intrare/iesire implica unitatea centrala de prelucrare determinänd-o sa transmita si adresa dispozitivului periferic, continuta în comanda de intrare/iesire.
3.a.ii. Transferul prin interogare
Al doilea mod de transfer prin program este transferul prin interogare. Intrarea în conversaţie cu un periferic se face sub controlul programului, de obicei într-o buclă de interogare (polling - scrutare a stării circuitelor periferice implicate în transfer). UCP interoghează dispozitivele periferice, după o anumită strategie stabilită prin program, dacă doresc sau nu schimb de date sau mesaje, sau dacă sunt active (gata pentru a primi informaţii). Pentru a determina dacă o operaţie de I/O este cerută, sau dacă poate avea loc, se pot folosi bistabile de condiţie (fanioane) locale, setate conform condiţiilor portului. Aceste fanioane se implementează fizic fie ca bistabile singulare, fie sunt incluse în registre de stare ale porturilor. Datorită simplităţii ei, tehnica de comunicare prin interogare programată este recomandată în sistemele în care timpul pierdut în rutina de interogare nu este critic pentru aplicaţia respectivă.
Atunci când programul are de controlat mai multe periferice, pe baza unei liste a porturilor asociate perifericelor, procesorul testează pe rând starea perifericelor şi le serveşte din punctul de vedere al transferului, dacă starea citită permite acest lucru. În acest fel perifericele sunt deservite în mod secvenţial şi implicit apar întârzieri la servirea acestora, mai ales dacă numărul de periferice controlate este mare. Dacă unele dintre periferice se consideră mai importante decât altele, adresa acestora se poate introduce de mai multe ori în lista de testare din bucla de interogare.
Dezavantajul principal al modului de transfer programat este constituit de timpul pierdut de UCP pentru testarea stării perifericelor, chiar dacă acestea nu cer servicii la momentele de timp respective.
Acest mod de transfer prezintă însă avantaje din punctul de vedere al costurilor (minim de echipament fizic suplimentar pentru transfer). Alt avantaj este că se cunoaşte exact momentul de timp când se testează sau când se face transfer de date cu un periferic; de aceea se spune că acest tip de transfer este sincron cu programul.
Dostları ilə paylaş: |