Comunicazione seriale (Terza parte)
Il processo di inizializzazione di una porta seriale non termina con la sua apertura: è infatti
necessario recuperarne le impostazioni di default ed eventualmente apportare le modifiche
necessarie ai parametri di cui si è discusso nel primo articolo: BaudRate, ByteSize, bit di parità,
bit di interruzione e così via.
Ma prima di analizzare tali operazioni è necessario prendere in considerazione
l'ipotesi in cui non sia possibile interagire con la porta seriale o perchè il numero di porta
indicato (COM1, COM2...) è inesistente o perchè si tenta una connessione ad una porta che
è già correntemente utilizzata (nel caso in cui se ne sia inibito l'accesso a tale condizione
impostando il parametro dwShareMode della funzione CreateFile su 0).
In tutte queste ipotesi la funzione CreateFile infatti fallisce e ritorna
-1.
Risulta così semplice gestire l'errore nel caso in cui si ottenga tale valore: il blocco di
codice che segue ne rappresenta un esempio:
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)
If nPorta = -1 Then
Msgbox "Impossibile accedere alla porta seriale"
Exit Sub
End If
CloseHandle nPorta
End Sub
|
Terminata questa parentesi il primo passo da compiere consiste nella determinazione dello stato attuale della
porta seriale, un'operazione possibile grazie alla funzione GetCommState, la cui dichiarazione
corrisponde a:
Declare Function GetCommState Lib "kernel32" (ByVal nCid As Long, lpDCB As DCB) As Long
|
Di tale funzione si notano i due parametri ossia nCid che rappresenta l'identificatore
della porta seriale (ossia il valore nPorta ottenuto richiamando la funzione CreateFile)
e lpDCB che non è altro che un puntatore alla struttura DCB che contiene tutti
i parametri d'impostazioni delle porte seriali.
Quindi, prima di vedere l'utilizzo di tale funzione è necessario analizzare la struttura
DCB (acronimo di Device-Control Block) :
Type DCB
DCBlength As Long
BaudRate As Long
fBitFields As Long
wReserved As Integer
XonLim As Integer
XoffLim As Integer
ByteSize As Byte
Parity As Byte
StopBits As Byte
XonChar As Byte
XoffChar As Byte
ErrorChar As Byte
EofChar As Byte
EvtChar As Byte
wReserved1 As Integer
End Type
|
Prima di vedere nel dettaglio la struttura è necessario sapere che
la periferica alla quale ci si riferisce nella comunicazione seriale (es: il modem) è dotata di un buffer ossia
di una memoria proprio come il computer. Soltanto che mentre la memoria del PC è
molto vasta e quindi solo una piccola partizione viene utilizzata per la comunicazione
seriale, quella della periferica è piuttosto limitata e viene utilizzata solo allo scopo
di comunicare col computer.
Quando la memoria della periferica è piena di dati ricevuti dal computer, invia un carattere
definito Xon ed espresso simbolicamente col carattere ASCII 17 per comunicare al PC
di non inviare più dati fino allo svuotamento della memoria della periferica.
Una volta svuotata la memoria fino ad un certo limite (impostabile come vedremo dopo
attraverso la struttura DCB), la periferica invia un secondo carattere
definito Xon espresso col simbolo ASCII 19 che indica al computer di riprendere
l'invio dei dati.
Per questo motivo questa procedura è anche definita flusso Xon/Xoff oppure Software flow control:
La seguente tabella mostra il significato dei membri di tale struttura:
DCBlength |
indica la lunghezza
espressa in byte della struttura;
|
BaudRate |
è riferito al concetto analizzato
nel primo articolo ("bd ossia baud rate corrisponde al numero di volte in cui il segnale
della connessione modifica la frequenza nel periodo della trasmissione di un bit").
La frequenza può essere indicata da uno tra i seguenti valori numerici:
19200
38400
56000
57600
115200
128000
256000
Questa unità di misura è nata grazie allo studio di Jean-Maurice-Emile Baudot
che ha originariamente creato un sistema di rappresentazione di caratteri a 5 bit che
negli inizi del '900 ha sorpassato il codice Morse.
Non di rado comunque, come già visto, il bd può essere usato erroneamente per indicare
il bps (bits per second) in quanto, nel caso in cui il segnale cambi ad ogni bit,
allora il baud rate coincide proprio con il bps.
|
fBitFields |
membro che dev'essere obbligatoriamente
TRUE;
|
wReserved |
è un membro non realmente
utilizzato che dev'essere impostato su 0;
|
XonLim |
indica in termini di byte
il livello minimo della memoria della periferica prima di inviare il carattere Xon,
ossia quanto la memoria dev'essere svuotata prima di riprendere la trasmissione dei dati;
|
XoffLim |
indica in termini di byte
il livello massimo della memoria della periferica prima di inviare il carattere Xoff,
ossia quanti dati la memoria può contenere al massimo prima di interrompere la
trasmissione dei dati;
|
ByteSize |
indica il
numero di bits nei bytes trasmessi e ricevuti;
|
Parity |
indica il
quale regola utilizzare con riferimento al bit di parità.
E' possibile impostare le regole di parità nel seguente modo:
EVENPARITY: specifica che il totale della somme degli 1 binari che formano un singolo carattere è un numero pari. In questo caso il bit di parità sarà impostato su 0, in caso contrario su 1.
Una volta impostato il bit di parità se desiderato (in quanto bit opzionale) può essere inviato
subito dopo i bit dei dati.
Ad esempio nell'invio del carattere 'a' (codice binario 1100001), il totale degli 1 è il numero dispari 3. Il bit di parità sarà quindi impostato su 1. Se invece si invia il carattere 'A' (codice binario 1000001), il bit di parità sarà impostato su 0.
ODDPARITY: simile a even solo che questa volta il bit di parità assume valore 0 se la somma degli 1 binari è dispari e 1 se è pari.
SPACEPARITY: indica che il bit di parità sarà in ogni caso 0. Questo può essere utile in caso di controllo di errori: se il bit di parità è diverso da 0 allora si è verificato un errore.
MARKPARITY: simile a SPACEPARITY solo che questa volta il bit di parità assume il valore predefinito 1.
NOPARITY: indica che la connessione seriale non utilizza il bit di parità per i dati trasmessi e che quindi il sistema ricevente non controllerà la parità per i dati ricevuti.
|
StopBits |
dopo la completa trasmissione dei
dati viene inviato un bit di valore 1 che indica il termine del trasferimento.
Tale bit viene riconosciuto in base alla sua durata in termini di trasferimento. Se infatti
è noto il tempo unitario di trasferimento di un bit (bps) che possiamo indicare con 1, allora il tempo di trasferimento
di un bit d'interruzione può essere 1, 1.5 oppure 2.
C'è inoltre una corrispondenza tra il numero di bit d'interruzione ed il numero di bit
precedentemente inviati, mostrata dai valori seguenti:
# bit di dati - - # bit d'interruzione
8 ------------------> 1 o 2
7 ------------------> 1 o 2
6 ------------------> 1 o 2
5 ------------------> 1 o 1.5
ed i valori indicabili in questo membro della struttura possono infatti essere:
ONESTOPBIT: 1 bit d'interruzione
ONE5STOPBITS: 1.5 bit d'interruzione
TWOSTOPBITS: 2 bit d'interruzione
|
XonChar |
indica il valore ASCII da utilizzare come carattere Xon (generalmente ASCII 17)
|
XoffChar |
indica il valore ASCII da utilizzare come carattere Xoff (generalmente ASCII 19)
|
ErrorChar |
indica il valore ASCII da utilizzare come carattere che indica un errore di parità;
|
EofChar |
indica il valore ASCII da utilizzare come carattere che indica il termine dei dati
da trasmettere (dal pc alla periferica o viceversa);
|
EvtChar |
indica il valore ASCII da utilizzare come carattere che indica che si è verificato
un evento specifico. Più in là questo concetto risulterà più chiaro ;
|
wReserved1 |
membro non utilizzato;
|
Adesso che la struttura è stata analizzata in profondità e sono stati introdotti
concetti nuovi possiamo finalmente fare uso della funzione GetCommState per
determinare dello stato attuale della porta seriale.
Indichiamo innanzitutto una variabile che punta alla struttura DCB, una variabile quindi
che conterrà tutte le impostazioni della porta seriale indicate dai membri della struttura.
Si potrebbe in alternativa utilizzare un numero di variabili pari al numero di membri della
struttura ma così il codice risulterebbe molto meno agevole:
Dim Situazione_Porta As DCB
|
Ora si può richiamare la GetCommState indicando come primo parametro
il riferimento alla porta ossia nPorta e come secondo la variabile Situazione_Porta:
GetCommState nPorta, Situazione_Porta
|
Avviando l'applicazione non succederà niente. Questo perchè non abbiamo ancora provveduto
a ricevere tutti i parametri sullo stato della porta seriale.
Operazione che si può compiere visualizzando lo stato in una finestra di messaggio. Se infatti
dichiariamo la variabile testuale Situazione che conterrà il testo complessivo della finestra
mi messaggio possiamo assegnarle il valore del baud rate:
Dim Situazione As String
situazione = "Baud Rate: " & Situazione_Porta.BaudRate & vbCrLf & _
|
e aggiungere il valore byte size:
Dim Situazione As String
situazione = "Baud Rate: " & Situazione_Porta.BaudRate & vbCrLf & _
"Byte Size: " & Situazione_Porta.ByteSize & vbCrLf & "--------------------------" & vbCrLf
|
poi verificare il tipo di parità:
Dim Situazione As String
situazione = "Baud Rate: " & Situazione_Porta.BaudRate & vbCrLf & _
"Byte Size: " & Situazione_Porta.ByteSize & vbCrLf & "--------------------------" & vbCrLf
Select Case Situazione_Porta.Parity
Case NOPARITY: situazione = situazione & "Parity: No Parity" & vbCrLf
Case ODDPARITY: situazione = situazione & "Parity: Odd" & vbCrLf
Case EVENPARITY: situazione = situazione & "Parity: Even" & vbCrLf
Case MARKPARITY: situazione = situazione & "Parity: Mark" & vbCrLf
Case SPACEPARITY: situazione = situazione & "Parity: Space" & vbCrLf
End Select
|
ed infine il numero di bit d'interruzione:
Dim Situazione As String
situazione = "Baud Rate: " & Situazione_Porta.BaudRate & vbCrLf & _
"Byte Size: " & Situazione_Porta.ByteSize & vbCrLf & "--------------------------" & vbCrLf
Select Case Situazione_Porta.Parity
Case NOPARITY: situazione = situazione & "Parity: No Parity" & vbCrLf
Case ODDPARITY: situazione = situazione & "Parity: Odd" & vbCrLf
Case EVENPARITY: situazione = situazione & "Parity: Even" & vbCrLf
Case MARKPARITY: situazione = situazione & "Parity: Mark" & vbCrLf
Case SPACEPARITY: situazione = situazione & "Parity: Space" & vbCrLf
End Select
Select Case Situazione_Porta.StopBits
Case ONESTOPBIT: situazione = situazione & "Stop Bits: 1" & vbCrLf
Case ONE5STOPBITS: situazione = situazione & "Stop Bits 1 1/2" & vbCrLf
Case TWOSTOPBITS: situazione = situazione & "Stop Bits: 2" & vbCrLf
End Select
|
se al termine di questo codice si visualizza la variabile situazione si avrà un'idea
dello stato della porta:
cioè ad esempio:
|
Visual
Basic Italia© copyright 2000 - tutti i diritti riservati
E-mail: vbitalia@libero.it
|
|