Guide e Tutorials:indexed | ||||||||||||||||||||||||
Comunicazione seriale (Quarta parte) Proprio com'è possibile determinare le impostazioni di una porta seriale attraverso la funzione GetCommState, così le si può assegnare i parametri principali attraverso la funzione SetCommState. Parametri che, come nel caso della prima funzione, non sono altro che i membri della struttura DCB.
dove il primo parametro rappresenta l'intero identificatore della porta (quello che nel codice d'esempio sviluppato nello scorso articolo avevamo chiamato 'nPorta') ed il secondo rappresenta invece la variabile 'Situazione_Porta'. Facciamo già da subito un esempio pratico: se volessimo impostare il numero di volte in cui il segnale della connessione modifica la frequenza nel periodo della trasmissione di un bit (quindi il Baud Rate) a 57600 non dovremo far altro che assegnare tale valore alla variabile di tipo DCB che nell'esempio dello scorso articolo avevamo chiamato 'Situazione_Porta':
in questo modo la porta "COM2" viene impostata per la comunicazione a velocità di trasmissione 9600 La stessa cosa può naturalmente essere fatta per altre proprietà che intervengono nella comunicazione seriale: il numero di bit di parità, d'interruzione e così via. Ad esempio si può impostare il bit di parità sul valore 0 utilizzando il gruppo di costanti visto nello scorso articolo: NOPARITY, EVENPARITY, ODDPARITY, SPACEPARITY, MARKPARITY:
Una volta recuperati i parametri di comunicazione ed eventualmente modificati come abbiamo visto sopra, è necessario ancor prima di avviare la comunicazione, determinare le impostazioni di time-out. Si ha un time-out nella comunicazione seriale quando i tempi di lettura e/o di scrittura dei dati da parte di una periferica superano i limiti di tempo stabiliti, se questi sono stati espressamente indicati. Tali impostazioni incideranno sulla comunicazione tanto quanto quelle legate alla struttura DCB. La struttura che indica le possibili configurazioni è la COMMTIMEOUTS:
Il primo membro, ReadIntervalTimeout indica in millisecondi l'intervallo che intercorre tra l'invio di due caratteri. Nel caso in cui il tempo di trasmissione superi il limite indicato, l'invio dei dati e la lettura vengono interrotti e la lettura dei dati restituirà qualsiasi valore presente nella memoria della periferica ossia i dati fino ad allora accumulati in memoria. Assegnare a tale parametro la costante MAXDWORD e 0 ai parametri successivi significa ritornare in tempo reale i caratteri ricevuti nella trasmissione dei dati anche se la memoria periferica non si è ancora riempita. Il valore 0 per questo parametro significa invece non utilizzare i parametri di time-out e quindi non impostare alcun tempo limite. Il secondo membro, ReadTotalTimeoutMultiplier (WriteTotalTimeoutMultiplier), moltiplicato per il numero totale di byte da leggere (scrivere) e sommato al parametro successivo ritorna in millisecondi il limite massimo di tempo accettabile prima di interrompere la lettura (scrittura) dei dati. ReadTotalTimeoutConstant (WriteTotalTimeoutConstant) indica invece una costante che sommata al numero totale di byte da leggere (scrivere) ed al valore indicato dal parametro precedente, restituisce il limite massimo di tempo accettabile prima di interrompere la lettura (scrittura) dei dati. Impostare il valore 0 per questi due ultimi parametri significa non impostare un limite massimo di attesa nella lettura (scrittura) dei dati. Vista la struttura COMMTIMEOUTS è quindi notevolmente più semplice comprendere la funzione GetCommTimeouts che ottiene le impostazioni di time-out predefiniti per una determinata periferica. La struttura della funzione è la seguente:
che necessita del solito intero ('nPorta' nell'esempio iniziato negli articoli precedenti) che identifica la porta seriale dalla quale recuperare le impostazioni di time-out, come primo parametro e una variabile del tipo COMMTIMEOUTS come secondo. Alla chiamata della funzione GetCommTimeouts tale variabile verranno assegnate le caratteristiche di time-out della porta sotto forma di membri della struttura COMMTIMEOUTS. Andando quindi ad analizzare la variabile si potrà comprendere quali sono le impostazioni predefinite per la porta indicata. Prima però la variabile dev'essere dichiarata nel seguente modo:
Una volta dichiarata la variabile, si richiama la GetCommTimeouts per assegnarle i valori di time-out, in questo modo:
Nel caso in cui la funzione abbia successo il valore ritornato sarà diverso da 0. Ora che la variabile è stata riempita, possiamo analizzarla nel dettaglio:
Il risultato sarà simile al seguente: dove le impostazioni qui visualizzate mostrano una situazione nella quale non viene imposto alcun limite alla lettura ed alla scrittura dei dati. Queste impostazioni predefinite però possono essere modificate a piacimento attraverso una funzione molto simile a quella appena vista, la SetCommTimeouts, la cui dichiarazione corrisponde a:
I parametri richiesti dalla funzione sono gli stessi della GetCommTimeouts con l'unica differenza che questa volta la variabile Tempi_Limite dev'essere riempita prima di passarla alla funzione come secondo parametro. Ed è proprio quello che faremo adesso. Ognuno è in ogni caso libero di impostare i tempi limite a piacimento, comunque per evitare problemi, reimposteremo la situazione classica ossia nessun limite alle operazioni di lettura e scrittura e per ottenere di volta in volta i caratteri trasmessi alla periferica. Questo codice può essere inserito nel listato dell'applicazione per assicurarsi che la porta non sia configurata in modo differente:
Ed ancora prima di iniziare una nuova trasmissione di dati è conveniente introdurre due nuovi concetti: il buffer di ricezione e quello di trasmissione. Quando infatti viene aperta una porta nella memoria del dispositivo vengono create due partizioni, una destinata alla ricezione dei dati dalla periferica ed un'altra destinata alla trasmissione dei dati. Maggiore è la capacità dei buffer, minore è la quantità di memoria disponibile per l'applicazione. Se le dimensioni delle partizioni sono troppo piccole, potrebbe però verificarsi un overflow del buffer. Le dimensioni predefinite per il buffer di trasmissione è 512 mentre per il buffer di ricezione 1024. Prima di cominciare una sessione di trasmissione è conveniente svuotare completamente queste due partizioni attraverso la funzione PurgeComm che ha la seguente sintassi:
dove il primo parametro è rappresentato dall'identificatore della porta ('nPorta' per intenderci) ed il secondo da un valore costante scelto tra i seguenti:
|