La porta parallela, così come ormai la seriale, va sempre più scomparendo (purtroppo!) soprattutto dai portatili. Veniva (viene) utilizzata per lo più per il collegamento delle stampanti (ma anche, tanto tempo fa, per scanner, drive iomega zip, chiavette per la protezione del software ecc). Per la sua semplicità di utilizzo, però, viene ancora oggi preferita dagli hobbysti per l’interfacciamento con numerosi dispositivi, primi tra tutti le CNC o i programmatori di microcontrollori/smartcard, ma anche per tante altre applicazioni.
La porta parallela è facile da utilizzare per il comando di dispositivi, proprio perchè consente l’invio contemporaneo di un byte su 8 distinte linee (trasmissione parallela – a differenza della trasmissione seriale che utilizza un’unica linea e quindi invia gli 8 bit uno dietro l’altro sulla stessa linea) : 8 linee di I/O, impostabili con un’unico invio di dati, che possono comandare altrettanti attuatori. In realtà, sulla porta parallela, di linee di I/O ce ne sono qualcuna in più, il che la rende appunto ideale per il controllo di relè, triac, mosfet ecc (per l’attuazione di motori, lampade ed altro) senza la necessità di dover “impazzire” con il codificare/decodificare una comunicazione seriale su di un’unica linea e quindi senza utilizzare microcontrollori e software “complicato”. In molti la usano per comandare display LCD (in maniera diretta) o motori passo/passo (tramite interfacce a transistor), soprattutto nelle CNC.
Per seguire meglio questa lezione, vi consiglio innanzitutto di scaricare dapprima il documento “Piedinatura e note di utilizzo della porta parallela” che ho appositamente preparato per voi nella sezione risorse: si tratta di un’unica pagina in formato PDF che può risultare molto utile tenerla sempre a portata di mano nel nostro piccolo laboratorio di elettronica.
La porta parallela
La porta parallela si presenta sul pc come un connettore di tipo Dsub a 25 poli:

Le linee su cui normalmente vengono inviati i dati alla stampante (o ad altri dispositivi), sono quelle colorate in viola nel disegno (pin da 2 a 9). Per tale motivo vi sono anche 8 pin di massa: generalmente ogni linea dati va intrecciata con una linea di massa in maniera tale da avere una migliore schermatura per la protezione dai disturbi.
Come vedete ho colorato i pin in maniera differente: questo perchè ogni gruppo di linee (identificato da un colore) appartiene ad un differente registro. Mi spiego meglio: la porta parallela, sul pc, viene controllata via hardware da 3 differenti registri chiamati Data, Status e Control.
Per controllare lo stato delle linee Data (indicate come Dn, e colorate in viola sullo schema), dovremo impostare opportunamente il registro Data ecc. Le linee Dati (data), sui nuovi pc sono bidirezionali: normalmente sono utilizzate come linee di output, ma settando ad 1 il bit 5 del registro Control, possono essere utilizzate come porte di ingresso.
Gli indirizzi esadecimali dei 3 registri delle porte parallele sono riportati nel documento che citavo prima nella sezione risorse: per la LPT1 (acronimo di Line Printer Terminal 1), che è la porta parallela presente di default sui pc (che la hanno), gli indirizzi sono:
0×378 per il registro Data (indicato anche come indirizzo Base)
0×379 per il registro Status (Base + 1)
0×37A per il registro Control (Base + 2)
L’indirizzo base, che è quello del registro Data, può anche essere dedotto dal Pannello di Controllo, Sotto Windows XP ci si arriva da Start -> Impostazioni -> Pannello di Controllo -> Sistema -> Hardware -> Gestione Periferiche -> Porte (Com e LPT) :

Doppio click su “Porta stampante …” -> Scheda Risorse

Il primo indirizzo I/O (0378 in questo esempio) è l’indirizzo del registro Data espresso in esadecimale.
I tre registri che comandano la parallela, sono registri ad 8 bit: per la linea dati, tutti e 8 bit li ritroviamo anche sul connettore (D0-D7).
Per la linea Status vediamo che mancano sul connettore i bit S0, S1 e S2: S0 e S1 non sono utilizzati, S2 è un IRQ negato: se su tale bit leggiamo uno stato logico 0, vuol dire che si è verificato un interrupt.
Per la linea Control vediamo invece che mancano sul connettore i bit da C4 a C7: C4 abilita l’interrupt, C5 come detto prima se impostato a 1 rende le porte D come ingressi, C6 e C7 non sono utilizzati.
Ci sono inoltre da fare ulteriori considerazioni: alcuni bit hanno uno stato invertito: ovvero sul corrispondente pin della porta parallela leggeremo 5volt (livello logico alto) quando il corrispondente bit è posto a Zero, di contro leggeremo 0volt (livello logico basso) quando il corrispondente pin è posto a Uno: questi sono i bit Co (pin n°1), S7 (pin n°11), C1 (pin n°14) e C3 (pin n°17), gli altri pin/bit si comportano in maniera normale (1 => 5Volt, 0 => oVolt).
Per inviare quindi un byte sulla linea dati basterà quindi impostare il registro Data in maniera opportuna.
Esempio
Ho una serie di relè collegati alla LPT1 (tramite apposita interfaccia), e voglio attivare unicamente i relè posti sulle linee D0 e D5, disattivando tutti gli altri: mi basterà impostare il registro 0×378 sul valore:
0b00010001 (in binario), oppure 17 in decimale oppure ancora 0×11 in esadecimale
Ovvero ci sarà bisogno di una funzione del tipo: port(0×378,0×11)
Capite quindi come è semplice potersi interfacciare con la seriale e perchè viene ancora così ampiamente utilizzata in campo elettronico.
Allo stesso modo è possibile inviare o ricevere dati sugli altri 2 registri (Control e Status), tenendo sempre conto che alcuni bit si comportano in maniera inversa rispetto allo standard e che alcuni pin sono a collettore aperto per cui non possono fornire i 5V (e ci sarà quindi bisogno di una resistenza di pull-up collegata ad una sorgente di alimentazione esterna) ma soltanto la linea di massa (fate riferimento al documento “piedinatura e note di utilizzo della porta parallela“).
Utilizzo pratico della porta parallela: semplice interfaccia a Led

In questo esempio, collegheremo 8 diodi led alla linea dati della porta parallela, e li faremo accendere via software. C’è innanzitutto da fare una premessa importantissima prima di cominciare:
La corrente in uscita dai pin della porta parallela è bassissima (circa 24mA) quindi è inadatta a comandare grossi carichi: a stento si possono pilotare dei Led tramite resistenza. La corrente inviata dagli altri pin di uscita, (a parte quelli della linea Data), è ancora più bassa: si parla di circa 7/8 mA (inutilizzabili per comandare direttamente anche un led), per cui la raccomandazioni sono:
1- Utilizzate una porta parallela aggiuntiva: sui pc fissi si può acquistare una scheda PCI che aggiunge una porta parallela in più. In questo caso se combiniamo guai, guasteremo unicamente la scheda aggiuntiva (il cui costo si aggira nei negozi intorno ai 15euro, in rete si può trovare ad un prezzo ancora più basso) e non tutta la scheda madre! Difatti se mandiamo in corto circuito un pin, o preleviamo più corrente di quella che la porta può fornire, il chip di controllo della parallela può guastarsi (ricordate sempre la legge di Murphy: se qualcosa potrà andare storto, ci andrà!), e questo è un bel guaio se utilizziamo la porta parallela integrata sul pc: dovremo sostituire la scheda madre e nel caso di un pc portatile… dovremo buttare tutto il portatile! Quindi: Attenzione! Soprattutto ai cortocircuiti!
2 – Utilizzate almeno un sistema di interfacciamento a transistor sia per non correre rischi di sovraccarico sia per tenersi isolati in qualche modo dalla porta parallela: collegare un transistor su ogni porta per stare tranquilli e alimentare i led (o i relè o altro) con una sorgente di alimentazione esterna. Potete utilizzare il seguente schema (i segnali di massa sia della porta parallela che dell’alimentazione esterna, andranno collegati insieme):
Questa configurazione va utilizzata per ogni pin di uscita. Al posto del BC237 (o BC337) potete utilizzare tanti altri transistor NPN come indicato nel documento “Pinout ed equivalenza transistor bjt di bassa potenza” presente nell’area risorse. Il transistor NPN va in conduzione quando sulla base giunge un livello logico alto, si trova in interdizione normalmente quando il pin sulla parallela si trova a livello logico basso, per tale motivo non ho inserito la resistenza di pull-down sulla base.
Lo schema con il transistor qui esposto può essere utilizzato per pilotare anche un relè al posto del diodo led. Un buon sistema di interfacciamento di uscite digitali con relè è proposto da Mauro Laurenti nella pagina “Scheda di controllo 4 Relays” che riporta anche il pcb e le istruzioni di funzionamento.
Molto più comodo sarebbe utilizzare gli array di transistor per risparmiare spazio e cablaggi, come un integrato tipo ULN2003 (il quale contiene 7 transistor al suo interno).
3 – Noi abbiamo fatto così e funziona, ma non si esclude che a qualcuno possa guastarsi la porta parallela. Se combinate guai, o qualcosa si guasta utilizzando questo circuito, settorezero nelle persone del webmaster e degli autori, non possono essere ritenuti responsabili: noi vi abbiamo avvisato (leggi anche il disclaimer).
Lo schema da me utilizzato per fare le prove è il seguente:

Il connettore disegnato è quello femmina visto frontalmente, oppure quello maschio visto dal lato saldature.
Come vedete ho collegato i led, tramite resistenze, unicamente alle otto porte dati e ho utilizzato un’unica linea di massa. Le resistenze utilizzate sono da 470Ω, che a 5 Volt consentono una corrente di 10,6mA, per cui come margine di sicurezza (rispetto ai 24mA) ci siamo, come led ho utilizzato i classici led rossi da 5mm (non usate quelli ultraluminosi, che richiedono più corrente per funzionare!).
Come gestire la porta parallela da VB.NET (e da altri linguaggi di programmazione)
Il Visual Basic (sia il vecchio 6.0 che il nuovo .NET) ha normalmente incluso il componente per la comunicazione seriale, per la comunicazione parallela invece no. Esistono tantissime librerie (gratuite) in giro che permettono di interfacciarsi con la porta parallela, tra le tante che ho provato ne ho “eletta” una che per me è davvero ottima e fornita con un bel corredo di funzioni, la libreria si chiama IO.DLL e può essere scaricata gratuitamente dal sito del suo sviluppatore: http://www.geekhideout.com/iodll.shtml
La cosa bella di tale libreria, a parte il fatto che sia gratuita e ben documentata, è che può accedere anche ad altre porte di I/O oltre alla parallela (fate riferimento alla pagina ufficiale per vedere a quali altre porte può accedere).
Per poterla utilizzare, non ho fatto altro che copiare la dll nella cartella “debug” (non è necessario copiarla in System32) e dichiarare ad inizio programma i prototipi di funzione così come indicato sulla pagina ufficiale della libreria:
Private Declare Sub PortOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Byte) Private Declare Sub PortWordOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Integer) Private Declare Sub PortDWordOut Lib "IO.DLL" (ByVal Port As Integer, ByVal Data As Long) Private Declare Function PortIn Lib "IO.DLL" (ByVal Port As Integer) As Byte Private Declare Function PortWordIn Lib "IO.DLL" (ByVal Port As Integer) As Integer Private Declare Function PortDWordIn Lib "IO.DLL" (ByVal Port As Integer) As Long Private Declare Sub SetPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte) Private Declare Sub ClrPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte) Private Declare Sub NotPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte) Private Declare Function GetPortBit Lib "IO.DLL" (ByVal Port As Integer, ByVal Bit As Byte) As Boolean Private Declare Function RightPortShift Lib "IO.DLL" (ByVal Port As Integer, ByVal Val As Boolean) As Boolean Private Declare Function LeftPortShift Lib "IO.DLL" (ByVal Port As Integer, ByVal Val As Boolean) As Boolean Private Declare Function IsDriverInstalled Lib "IO.DLL" As Boolean
L’utilizzo delle funzioni è semplicissimo, indicando con Port l’indirizzo esadecimale della porta (ricordo: 0×378 per la LPT1, che però in Visual Basic.NET andrà scritto come &H0378) e con Data il dato da inviare, le funzioni andranno utilizzate così:
PortOut : invia un byte (8 bit: valori da 0 a 255) alla porta.
Esempio
Per accendere tutti i led col circuito mostrato prima, sulla porta LPT1, scriveremo in Visual Basic:
PortOut(&H378,255)
PortWordOut : stessa cosa di WordOut ma invia un valore di 16Bit
PortDWordOut : stessa cosa di WordOut ma invia un valore di 32bit
PortIn, PortWordIn e PortDWordIn : leggono un valore (rispettivamente di 8,16 e 32 bit) dalla porta
Esempio
Vogliamo leggere il valore del registro Status della porta parallela:
Dim StatusValue As Integer StatusValue = PortIn(&H379)
SetPortBit : setta (ovvero imposta a 1) il bit della porta specificata:
Esempio
Vogliamo accendere il led sulla porta D0, lasciando invariati gli altri bit:
SetPortBit(&H378,0)
SetPortBit : Resetta (ovvero imposta a 0) il bit della porta specificata.
NotPortBit : Inverte lo stato del bit della porta specificata.
GetPortBit : Ottiene il valore del bit della porta specificata
Esempio
Vogliamo ricavare lo stato del led sulla porta D0:
Dim D0Status As Boolean D0Status = GetPortBit(&H378,0)
Nota: In realtà questo metodo a me non funziona, per ricavare lo stato di una singola porta utilizzo la funzione PortIn, converto il risultato ottenuto in binario e infine prelevo il bit che mi interessa.
RightPortShift : Effettua la rotazione a destra dei bit della porta specificata, restituisce il valore del bit meno significativo (il quale “esce” dalla porta), e il valore passato alla funzione diviene il bit più significativo (il bit 7)
Esempio
Abbiamo che il valore attuale della porta è 10010011
Effettuando questa operazione:
RightPortShift(&H378,1)
Il valore della porta diventerà 11001001 (i valori sono stati spostati verso destra, il bit meno significativo è stato perso, e il valore da noi passato (1) diventa il bit più significativo)
LeftPortShift : Effettua la rotazione a sinistra dei bit della porta specificata, restituisce il valore del bit più significativo, e il valore passato alla funzione diviene il bit meno significativo (il bit 0)
IsDriverInstalled : Restituisce un valore diverso da zero se la libreria io.dll è installata e funzionante
Software di esempio
Ho realizzato un piccolo software di esempio che utilizza tale libreria, per accendere/spegnere le uscite sulla porta dati:

Lo stato delle linee viene portato alto o basso cliccando con il mouse sui relativi “led” disegnati sull’interfaccia. Le etichette associate ai led (nominate come D0, D1 ecc nell’immagine), possono anche essere cambiate per dargli dei nomi più significativi (questo se ad esempio facciamo un’interfaccia a transistor/relè/triac per comandare vari utilizzatori in casa):

Lo stato dei led non si aggiorna in maniera “stupida” alla pressione, ma verifica lo stato effettivo della porta. Le etichette, così come la porta parallela alla quale è collegata l’interfaccia, possono essere cambiate dal menù impostazioni. Nella barra di stato sono indicati: la porta LPT in uso e lo stato della linea dati in formato binario, esadecimale e decimale.
Potrebbe verificarsi un errore se è attivo lo spooler di stampa, in questo caso basta terminare il processo “spoolsv.exe” dal task manager (CTRL + ALT + CANC).
Il software per funzionare ha bisogno almeno del .NET Framework 2.0.
Il programma attualmente supporta unicamente la porta dati e il codice sorgente è disponibile previa donazione di supporto a piacere. Nel codice sorgente sono presenti delle semplici funzioni per la conversione nelle varie basi numeriche e dei buoni esempi di spunto su come aggiornare una serie di controlli a runtime.
Ringrazio ancora Fred Bulbak (www.geekhideout.com) per la disponibilità e per aver messo a disposizione questa semplice ed efficace libreria.
Articoli che potrebbero interessarti:






#1 da tom il 14 novembre 2009
L’eseguibile non funziona e non da segni di vita su Xp con framework 3.5 ..
Sarebbe gradito un piccolissimo sorgente in vb o c.
Complimenti comunque all’autore per il sito mlto carino e fatto bene.
Un Cordiale Saluto,
Tom
#2 da Giovanni Bernardo il 14 novembre 2009
Cosa vuol dire non funziona? Se non mi viene detto qual’è l’errore non posso trovare una soluzione. Personalmente il programma l’ho provato su altri pc e non da problemi, parte e funziona.
#3 da tom il 15 novembre 2009
scarico, scomprimo, eseguo l’eseguibile ma non fa nulla.. boo
Comunque pare strano anche a me, credevo fosse per i framework, ma lo ho reinstallato ma nulla..
Non capisco cosa possa essere il problema..
#4 da Giovanni Bernardo il 15 novembre 2009
Mi pare strano… Alla fine il programma è semplicissimo e l’ho compilato per il framework 2.0, quindi funziona anche col 3.5, e io col 3.5 faccio il test, hai modo di provarlo su un altro pc?
#5 da tom il 15 novembre 2009
Si, su un piccolo notebook (senza parallea però) ma mi fa lostesso..
Stavo pensando che magari non vada perchè sul mio home pc la parallela non è 0×378 ma 0xd400 perchè si trova su una scheda di espansione pci..puo essere??
(la mainboard ha solo usb e rs232)
#6 da tom il 15 novembre 2009
Ho anche provato a scrivere un piccolo software in VB dove quando clicco un bottone mando: PortOut(&Hd400,255)
e ovviamente ho dichiarato tutte le “Private Declare Sub…” che gentilmente hai messo in questa pagina..
ma non compila.. uff ..ho perso le speranze hehe
#7 da Giovanni Bernardo il 18 novembre 2009
La parallela non può avere indirizzo 0xD400 (? e poi… 4 cifre?). Controlla bene l’indirizzo della tua porta parallela dal pannello di controllo come ho scritto nell’articolo e fammi sapere che c’è scritto.
#8 da tom il 20 novembre 2009
L’indirizzo esatto della mia parallela è D400 in esadecimale, come dicono le proprietà.. ho provato con le inpout32.dll e funziona, ma con le io.dll non cè verso
#9 da Alessandro il 10 dicembre 2009
Salve, io sono un pivellino per l’elettronica, quindi questa domanda potrebbe essere stupida!perchè nel primo schema elettrico la R è di 470K
mentre nello schema che segue sono di 470 ohm?
Grazie!
#10 da Giovanni Bernardo il 10 dicembre 2009
Nel primo forse intendi quello del transistor e non c’è scritto 470K ma 4700R ovvero 4700 Ohm ovvero 4,7KOhm, serve per pilotare la base del transistor e non è un valore critico, può andar bene pure una 1K.
Quelle da 470Ohm servono per limitare la corrente nei led, si vede pure dagli schemi che le resistenze stanno collegate ad utilizzatori diversi.
#11 da Alessandro il 10 dicembre 2009
Ho sbagliato a scrivere(volevo scrivere 4,7K),non avevo capito stupidamente che quella sotto era un altra configurazione.
Quindi se ho capito :da LPT arrivano 5volts , la resistenza da 4,7K mi fa scorrere una corrente da 1mA che porta in conduzione il transistor e il led
si accende con l’ausilio di una alimentazione esterna.
Grazie mille ,l’impegno che c’è in questo sito è ammirevole!
#12 da Giovanni Bernardo il 10 dicembre 2009
Esatto, la resistenza più grande serve per mandare il transistor in saturazione e quindi farlo funzionare come un interruttore on/off e pilotare quindi i led, da alimentare con altra tensione, quindi avresti bisogno di utilizzare un transistor in quella configurazione per ogni led. In realtà io la prova l’ho fatta senza utilizzare il transistor e mettendo una resistenza un po’ più alta del normale per stare sicuro che non vi sia troppo assorbimento che può portare alla rottura del chip che controlla la parallela. Su un portatile questo problema è ancora più sentito, perchè una volta rotto il chip della parallela, si potrebbe danneggiare l’intera scheda madre e il portatile è da buttare. Per tale motivo consiglio di usare una parallela aggiuntiva su un pc fisso se non si è esperti.
#13 da Alessandro il 22 dicembre 2009
si potrebbe mettere dopo il transistor un relè 5v ?
#14 da Giovanni Bernardo il 22 dicembre 2009
Dopo il transistor puoi mettere ciò che vuoi, compatibilmente con la corrente che può passare tra emettitore e collettore. Il transistor illustrato va bene per pilotare un relè. Dato che i relè a 5 volt non sono facili da trovare e costano qualcosa in più, puoi anche metterne uno da 12 volt , ovviamente al posto del led e resistenza metterai il relè, alimentato a 12 volt, la massa della porta parallela e la massa della fonte di alimentazione a 12 volt andranno messe in comune. Dovrai inoltre mettere un diodo in controfase in parallelo all’alimentazione del relè per scaricare a massa eventuali correnti parassite che genera la bobina.
#15 da nicola dagani il 23 gennaio 2010
Complimenti per la spiegazione di questa pagina..
#16 da daxdaxdax il 27 gennaio 2010
Ciao a tutti,
Chi mi saprebbe dire in che modo riuscirei a fare tutto ciò con la mia porta parallela aggiunta apposta PCI che ha un intervallo EC00 – EC07 ?
Con le porte on board tutto funziona alla grande, complimenti!!