ELEMANIA
Z80 - Handshake
Handshake e interfacciamento di periferiche complesse

Nei semplici esempi considerati finora non abbiamo problemi di sincronizzazione tra le periferiche e il processore. Infatti i display a sette segmenti risultano in ogni istante "disponibili" al processore (che può accenderli e spegnerli quando vuole) e così pure gli interruttori (che possono essere “letti” in qualunque momento).

Ma in generale una periferica può essere qualcosa di più complesso, come ad esempio una stampante, una tastiera, un modem o un mouse. Una stampante, nel momento in cui il processore cerca di utilizzarla, può ad esempio essere spenta, oppure priva di carta, o ancora in stato di blocco a causa di un precedente errore di funzionamento (come un inceppamento della carta). Inoltre molti tipi di periferica possono rimanere occupati per un certo intervallo di tempo, impossibilitati ad accettare o inviare un dato. In tutti questi casi, quindi, da parte del processore si renderà necessario un controllo circa la disponibilità della periferica stessa allo scambio di informazioni.

Il trasferimento dei dati sarà gestito mediante un opportuno protocollo di sincronizzazione, chiamato handshake (letteralmente "stretta di mano"). Questo si realizza  aggiungendo un certo numero di collegamenti tra il microcomputer e le periferiche, necessari per lo scambio di opportuni segnali di controllo. Questi segnali risultano indispensabili per sincronizzare correttamente il colloquio tra i dispositivi interessati senza perdita (o duplicazione) di dati. Detti segnali sono necessari sia nel caso in cui è il microcalcolatore a trasmettere i dati alla periferica, sia nel caso contrario. I segnali di controllo saranno poi gestiti dal software e da un hardware locale “dedicato”.  

In questo caso si dice che dobbiamo interfacciare i dispositivi periferici al sistema. Un’interfaccia, dal punto di vista hardware, consiste in un insieme di porte di ingresso-uscita, di circuiti logici e di opportuno software che permettono di collegare una certa periferica al sistema a µP.

Per meglio capire la situazione, riprendiamo l’esempio della stampante, che immaginiamo connessa ad un personal computer. Si consideri il caso di dover stampare un documento molto lungo. Quando il microprocessore invia alla stampante il documento, utilizza la memoria presente nella stampante stessa. Una volta accettata una certa percentuale del documento, la stampante non sarà più in grado di ricevere il resto fino a quando non avrà stampato la prima parte, liberando la sua memoria interna. Ci sarà dunque un intervallo di tempo durante il quale il µP dovrà arrestare temporaneamente la trasmissione dei dati, per riprenderla quando la stampante avrà liberato la sua memoria “di lavoro”. Tale situazione dev'essere gestita attraverso lo scambio di opportuni segnali di sincronizzazione fra il computer e la stampante stessa (detti appunto segnali di handshake).

Analoga situazione si presenta nel caso dell’ingresso di dati provenienti da una periferica. Si pensi, ad esempio, ad una tastiera. La velocità di battitura non è costante (dipende dall'operatore umano), e potrebbe passare anche molto tempo tra due battute. Anche in questo caso sarà necessario che il processore rivolga attenzione alla tastiera solo quando necessario per acquisire un carattere battuto.

Handshake unidirezionale

Si parla di handshake unidirezionale quando il dispositivo che riceve o che fornisce i dati è abbastanza veloce e può essere gestito dal µP con un unico segnale di controllo che dal µP  va verso la periferica. Tale segnale di controllo viene spesso detto strobe.

In pratica il segnale di strobe viene attivato dal µP ogni volta che questi vuole leggere o scrivere un dato (a seconda che si tratti di un dispositivo di ingresso o di uscita). Fra un'attivazione e l'altra dello strobe il µP può inserire un tempo di ritardo, per tener conto del tempo impiegato dalla periferica per trattare il dato. Tuttavia in questo tipo di collegamento il µP non controlla in alcun modo lo stato della periferica, ma si limita ad assumere che la periferica sia sempre pronta al trasferimento (dopo l'eventuale ritardo fisso). Per esempio interfacciando una stampante in questo modo il µP invierebbe i dati a cadenza fissa e non potrebbe accorgersi di eventuali inceppamenti della carta o di altri problemi.

Si consideri per esempio la seguente soluzione circuitale:

In questo caso la periferica di output è associata a due porte, ognuna col proprio indirizzo. La prima porta (registro parallelo uno) serve per inviare il dato alla periferica, mentre della seconda porta (registro parallelo due) è usato solo un bit che serve come segnale di strobe.

Supponiamo piuttosto arbitrariamente che il registro uno abbia indirizzo 40h e che il registro due sia associato all'indirizzo 41h. Sempre in modo arbitrario, decidiamo di collegare la linea strobe al bit C4 del registro parallelo due (è sufficiente un solo bit di questo registro, dal momento che il segnale di strobe è costituito da un solo bit).

Supponiamo di voler trasferire sulla periferica una serie di dati contenuti in memoria a partire dall'indirizzo (arbitrario) 1234h. Il programma che genera i segnali necessari è il seguente:

  LD A,00h  ; inizializza A con zero
  OUT (41h), A ; azzera il segnale di strobe
  LD HL,1234h ; inizializza un contatore in memoria
  ... ; il programma prosegue con altre istruzioni
inizio: LD A,(HL) ; carica in A un valore dalla memoria
  INC HL ; incrementa il contatore
  OUT (40h), A ; invia il dato al registro uno
  LD A, 10h ; prepara in A l'attivazione dello strobe
  OUT  (41h), A ; attiva lo strobe
  CALL RITARDO ; chiama un sottoprogramma di ritardo
  LD A,00h ; azzera A
  OUT (41h), A ; azzera lo strobe
  JP inizio ; ripete dall'inizio
           

Si osservi l'istruzione LD A,10h usata per mandare a 1 (settare) il bit C4 del registro due (linea di strobe).

Handshake bidirezionale

Nel caso in cui la periferica non sia abbastanza veloce oppure quando la sua velocità è variabile e non può essere gestita con una routine di ritardo fissa (si pensi per esempio a una tastiera), occorre gestire un handshake bidirezionale, cioè in cui il µP attende un segnale di conferma dalla periferica prima di proseguire con l'invio (o la ricezione, a seconda dei casi) dei dati.

In questo caso è necessario dunque gestire un secondo segnale di handshake, denominato generalmente busy, il quale, come suggerisce il nome, dice al µP se la periferica è occupata oppure no. Si consideri il seguente schema circuitale:

Si noti il buffer 3-state che è stato aggiunto per gestire il segnale di busy che la periferica invia al µP. Supponendo di voler trasferire un gruppo di dati dalla memoria alla periferica, come nell'esempio visto prima, il programma di gestione dell'handshake è il seguente:

  LD A,00h  ; inizializza A con zero
  OUT (41h), A ; azzera il segnale di strobe
  LD HL,1234h ; inizializza un contatore in memoria
  ... ; il programma prosegue con altre istruzioni
inizio: LD A,(HL) ; carica in A un valore dalla memoria
  INC HL ; incrementa il contatore
  OUT (40h), A ; invia il dato al registro uno
  LD A, 10h ; prepara in A l'attivazione dello strobe
  OUT  (41h), A ; attiva lo strobe
test: IN A, (42h) ; legge il buffer 3-state
  BIT 7,A ; testa il bit 7 del buffer (segnale busy)
  JP NZ, test ; se busy è alto (periferica occupata), torna a testare il bit 7
  LD A,00h ; azzera A
  OUT (41h), A ; azzera lo strobe
  JP inizio ; ripete dall'inizio
           

Si noti come in questo programma il µP sia inutilmente impegnato a non fare nulla in attesa che la periferica sia pronta per fornire un altro dato. Chiaramente non si tratta di una gestione molto efficiente dei tempi di esecuzione del µP! Un'alternativa senz'altro migliore è quella di usare un interfacciamento a interrupt, come vedremo fra poco.

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it