Le
impostazioni applicabili ad una porta seriale |
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 della 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:
» "Xon/Xoff"
definizione
secondo SearchNetworking.com
|