Comunicazione seriale (Seconda parte)
Il primo passo da compiere per la gestione della comunicazione seriale consiste nell'indicare
all'applicazione la porta che si desidera prendere in considerazione (ad esempio COM1, COM2, LPT1 e così via).
Tutti i programmi orientati verso la comunicazione seriale dovrebbero quindi cominciare con
la funzione CreateFile.
Attraverso questa funzione infatti non solo viene aperta la porta di comunicazione indicata,
ma viene restituito il riferimento all'oggetto (porta di comunicazione) che potrà essere poi
utilizzato dalle funzioni successive (nella fattispecie ReadFile e WriteFile che
vedremo nel corso dello speciale).
La dichiarazione della CreateFile è la seguente:
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal
lpFileName As String, ByVal _
dwDesiredAccess As Long, ByVal dwShareMode As Long,
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
ByVal dwCreationDisposition As Long,
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile _
As Long) As Long
|
Come si può notare il valore ritornato dalla funzione è un intero proprio perchè il riferimento
alla porta viene espresso come Long.
Prima di continuare bisogna però specificare che la CreateFile estende il proprio
utilizzo anche a file e directory. Per questo motivo alcuni parametri e costanti assegnabili
a questi sono del tutto inutili allo scopo di gestire una comunicazione seriale e quindi
molti di essi verranno ignorati.
La tabella sottostante spiega nel dettaglio il significato di ogni parametro da associare alla
CreateFile:
lpFileName |
indica il nome della porta
da aprire. Sarà quindi sufficiente indicare un nome come "COM1" (naturalmente racchiuso tra
le virgolette);
|
dwDesiredAccess |
come il nome indica, è il tipo
di accesso all'oggetto porta di comunicazione.
I tipi di accesso da indicare sono espressi sotto forma di costanti:
0 acesso di tipo 'interrogazione della porta'. In pratica
l'applicazione richiede lo stato della porta senza accedervi direttamente
GENERIC_READ accesso in lettura
GENERIC_WRITE accesso in scrittura
mentre gli ultimi due parametri sono associabili (specificando GENERIC_READ Or GENERIC_WRITE
per un accesso sia in lettura che in scrittura), la costante 0 non permette alcun accesso diretto;
|
dwShareMode |
indica, sempre con l'utilizzo di costanti,
se è possibile un accesso multiplo alla porta. In caso positivo, dopo aver aperto la porta
con la funzione CreateFile, è possibile accedervi senza limitazioni. In caso negativo
un ulteriore accesso è possibile soltanto dopo la chiusura della porta oppure sotto alcune
condizioni indicate dalle costanti.
Le costanti sono:
0 non è possibile accedere alla porta se già aperta
FILE_SHARE_READ sono possibili accessi successivi alla porta solo a scopo di lettura
FILE_SHARE_WRITE sono possibili accessi successivi alla porta solo a scopo di scrittura
Anche in questo caso è possibile combinare le costanti limitando l'accesso alla porta a
scopo di lettura-scrittura in questo modo: FILE_SHARE_READ Or FILE_SHARE_WRITE ;
|
lpSecurityAttributes |
è un puntatore ad una struttura del tipo
SECURITY_ATTRIBUTES che indica se il riferimento alla porta è ereditabile da altri sottoprocessi.
E' possibile indicare la non ereditarietà del riferimento e quindi indicare comodamente 0& oppure NULL;
|
dwCreationDisposition |
indica le operazioni che è possibile
compiere sulla porta di comunicazione. L'unica operazione possibile nel caso di comunicazione
seriale è:
OPEN_EXISTING che apre la porta solo se esistente.
In realtà essendo la funzione riferibile anche ai file e alle directory, esistono altre costanti
che rappresentano ulteriori operazioni. Sarebbe però del tutto inutile indicare ad esempio
CREATE_NEW perchè significherebbe chiedere all'applicazione di creare una nuova porta di comunicazione.
|
dwFlagsAndAttributes |
permette di indicare il tipo di comunicazione
alla porta. Come già abbiamo visto è possibile una comunicazione sincrona o asincrona.
Nel primo caso si potrà indicare 0, nel secondo FILE_FLAG_OVERLAPPED. In questa serie di articoli
si tratterà solamente la comunicazione sincrona (non overlapped) quindi si potrà assegnare 0 al parametro;
|
hTemplateFile |
parametro non riferibile alla comunicazione
seriale. Indicare 0.
|
Risulta così piuttosto semplice fare un primo esempio di apertura di una porta di comunicazione
e recupero del riferimento alla stessa.
Dopo aver dichiarato la funzione indichiamo il nome della porta da aprire ad esempio "LPT1" (primo
parametro), poi indichiamo il tipo di accesso ossia come vogliamo operare una volta avuto
accesso alla porta: GENERIC_READ Or GENERIC_WRITE (secondo parametro).
Non c'interessa nè la condivisione della porta nè l'ereditarietà del riferimento
per cui possiamo indicare come terzo parametro 0 e come quarto 0&. Per il quinto parametro
l'unica possibilità è OPEN_EXISTING mentre per il sesto e settimo indichiamo 0 (comunicazione
sincrona e parametro non necessario).
Prima di mostrare il codice per intero è però necessario notare un particolare: nella dichiarazione
della CreateFile è indicata una struttura, la SECURITY_ATTRIBUTES:
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
|
Siccome per la gestione della comunicazione seriale non si fa riferimento a tale struttura
è meglio non indicarla nella dichiarazione della CreateFile cambiando il tipo di dato
rappresentato dal parametro lpSecurityAttributes da SECURITY_ATTRIBUTES a Long.
In conclusione, per utilizzare la CreateFile per la comunicazione seriale utilizzare
la seguente dichiarazione:
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal
lpFileName As String, ByVal _
dwDesiredAccess As Long, ByVal dwShareMode As Long,
lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long,
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile _
As Long) As Long
|
Ecco quindi come aprire LPT1 e come ottenere in una finestra di messaggio il riferimento
alla porta:
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal
lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long,
lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long,
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile _
As Long) As Long
Private Sub Form_Load()
Dim nPorta As Long 'l'intero di riferimento alla porta
nPorta = CreateFile("LPT1", GENERIC_READ Or GENERIC_WRITE, 0, 0&, OPEN_EXISTING, 0, 0)
MsgBox nPorta
End Sub
|
Il risultato ottenuto sarà di questo tipo:
Adesso provare ad avviare nuovamente l'applicazione. La finestra di messaggio visualizzerà
il seguente risultato:
Perchè? Non si deve dimenticare che abbiamo impostato il terzo parametro della funzione ossia
dwShareMode su 0 ossia il blocco di qualsiasi tentativo successivo di accedere ad una
porta già aperta. E questo caso rappresenta un efficace esempio per comprendere il significato
del parametro.
Per evitare problemi del genere è necessario chiudere la porta alla chiusura dell'applicazione,
richiamando la funzione CloseHandle, la cui dichiarazione è la seguente:
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
|
E' facile notare che qui l'unico parametro da associare alla funzione è proprio il riferimento
alla porta aperta con la CreateWindow ossia, nell'esempio rappresentato dal codice sopra,
nPorta.
In questo caso non è necessario assegnare il valore di ritorno della CloseHandle ad una
variabile.
Se quindi integriamo il codice con questa nuova funzione per aprire e chiudere la porta COM2:
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal
lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long,
lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long,
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile _
As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Form_Load()
Dim nPorta As Long 'l'intero di riferimento alla porta
nPorta = CreateFile("COM2", GENERIC_READ Or GENERIC_WRITE, 0, 0&, OPEN_EXISTING, 0, 0)
MsgBox nPorta
CloseHandle nPorta
End Sub
|
Adesso ad ogni apertura dell'applicazione la finestra di messaggio mostrerà lo stesso valore
ossia il riferimento a COM2.
|
Visual
Basic Italia© copyright 2000 - tutti i diritti riservati
E-mail: vbitalia@libero.it
|
|