Nel framework .NET 2.0 e successivi è presente il namespace
System.IO.Ports, nel quale è inserita la classe SerialPort(che rappresenta la risorsa porta seriale), mediante la quale è possibile comunicare in modo semplice e diretto attraverso l’interfaccia seriale.
Quello che segue è il primo di una serie di articoli in cui utilizzerò la classe SerialPort per mostrare il suo impiego sia nelle applicazioni desktop, sia in quelle web. Il codice contenuto in questo articolo è parte di una classe molto più complessa che ho sviluppato in un’applicazione realtime.
E’ possibile eseguire il download della classe ComManager e di una semplice applicazione winform, che mostra il suo utilizzo, dal seguente indirizzo: IdeaCom.zip
Questo articolo è basato su un’applicazione winform denominata
IdeaCom
e una classe il cui nome è
ComManager
. La struttura della classe è la seguente:
public
class
ComManager
{
public
string PortName {get; set;}
public
string BaudRate {get; set;}
public
string ParityCM {get; set;}
public
string StopBits {get; set;}
public
string DataBits {get; set;}
//-------------------------------------------
public
enum
eTxMode {Text, File}
public
eTxMode TxMode {get; set;}
private
string MsgStatus;
private
SerialPort comPort = newSerialPort();
public ComManager() {}
public
void InitCbPortName(ComboBox cb) {}
public
void
InitCbBaudRate
(ComboBox cb) {}
public
void InitCbParity(ComboBox cb) {}
public
void InitCbStopBit(ComboBox cb) {}
public
void InitCbDataBits(ComboBox cb) {}
public
bool OpenPort() {returnfalse;}
public
bool ClosePort() {returnfalse;}
public
bool IsTxBufferEmpty()
{returnfalse;}
public
void TxData(string msgText) {}
public
string RxData() {return"";}
public
string ReadFileStream(string path) {return"";}
public
void WriteFileStream(string path) {}
public
string ReadMsgStatus() {return"";}
}
Le property consentono di memorizzare le informazioni minime necessarie per poter utilizzare la porta seriale. Inoltre è stato definito un tipo enumerativo
eTxMode
il cui fine è di consentire di definire i diversi tipi di proptocolli software necessari per il trasferimento dei dati e quindi una ulteriore property per memorizzare il corrente modo funzionale della classe.
Il membro privato
MsgStatus
consente di memorizzare i messaggi di errore o di stato della classe. La variabile viene azzerata quando l’applicazione legge lo stato mediante il metodo
ReadMsgStatus().
L’oggetto
comPort
è una istanza della classe SerialPort del framework .NET che rappresenta la porta seriale.
Il
costruttore della classe comPort
inizializza l’oggetto, in modo da avere un suo comportamento predicabile. In questo esempio viene inizializzata con valori indefiniti, il che significa che prima del suo utilizzo occorre inizializzare tutte le property. In una reale applicazione potrebbe essere utile definire un ulteriore costruttore che inizializza l’oggetto con dei valori di default.
public ComManager()
{
BaudRate = string.Empty;
ParityCM = string.Empty;
StopBits = string.Empty;
DataBits = string.Empty;
PortName = string.Empty;
TxMode = eTxMode.File;
MsgStatus = string.Empty;
}
La scelta dei parametri necessari per programmare la porta seriale avviene attraverso cinque combo box. L’inizializzazione della lista di questi viene fatta mediante i seguenti cinque metodi della classe comPort:
InitCbPortName
(),
utilizza il seguente metodo
SerialPort
.GetPortNames() mediante il quale è possibile ottenere l’elenco di tutte le porte seriali presenti sul pc (COM1, COM2, ecc.), al fine di poter inizializzare la lista del combo box.
public
void InitCbPortName(ComboBox cb)
{
foreach (string str inSerialPort.GetPortNames())
cb.Items.Add(str);
}
InitCbBaudrate
(),
consente di inizializzare la lista del combo box relativo alla baudrate:
public
void InitCbBaudRate(ComboBox cb)
{
cb.Items.Add("300");
cb.Items.Add("1200");
cb.Items.Add("2400");
cb.Items.Add("4800");
cb.Items.Add("9600");
cb.Items.Add("14400");
cb.Items.Add("28800");
cb.Items.Add("36000");
}
InitCbDataBits
(),
consente di inizializzare la lista del combo box relativo al numero di data bits:
public
void InitCbDataBits(ComboBox cb)
{
cb.Items.Add("7");
cb.Items.Add("8");
cb.Items.Add("9");
}
InitCbParity
(),
la classe SerialPort contiene il tipo enumerativo
Parity
il cui fine è di fornire il tipo di parità che il driver supporta:
public
void InitCbParity(ComboBox cb)
{
foreach (string str inEnum.GetNames(typeof(Parity)))
cb.Items.Add(str);
}
InitCbStopBits
(),
la classe SerialPort contiene il tipo enumerativo
StopBits
il cui fine è di fornire il numero di stop bits:
public
void InitCbStopBit(ComboBox cb)
{
foreach (string str inEnum.GetNames(typeof(StopBits)))
cb.Items.Add(str);
}
I metodi
OpenPort()
e ClosePort()
consentono rispettivamente di aprire e chiudere la porta seriale. La property IsOpen della classe SerialPort consente di verificare se lo stato della porta, mentre i metodi comPort.Open() e comPort.Close() effettuano l’operazione richiesta.
public
bool OpenPort()
{
try {
if (comPort.IsOpen == true)
comPort.Close();
comPort.BaudRate = int.Parse(BaudRate);
comPort.DataBits = int.Parse(DataBits);
comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), StopBits);
comPort.Parity = (Parity)Enum.Parse(typeof(Parity), ParityCM);
comPort.PortName = PortName;
comPort.Open();
MsgStatus = "La Porta " + PortName + " è stata aperta con successo";
}
catch (Exception ex) {
MsgStatus = ex.Message;
return
false;
}
return
true;
}
public
bool ClosePort()
{
try {
if (comPort.IsOpen == true)
comPort.Close();
MsgStatus = "La Porta " + PortName + " è stata chiusa";
}
catch
(Exception ex) {
MsgStatus = ex.Message;
return
false;
}
return
true;
}
IsTxBufferEmpty
(),
consente di verificare se vi sono dati nel buffer di trasmissinoe
public
bool IsTxBufferEmpty()
{
return((comPort.BytesToWrite >0) ? false : true);
}
TxData
(),
consente di inviare i dati attraverso la porta seriale, mediante il metodo Write della classe SerialPort:
public
void TxData(string msgText)
{
if (!(comPort.IsOpen == true))
OpenPort();
if (TxMode == eTxMode.File) {
comPort.Write(msgText);
MsgStatus = "I dati sono stati inviati con successo";
}
}
RxData
(),
consente di ricevere i dati dalla porta seriale, mediante il metodo
ReadExisting
della classe SerialPort:
public
string RxData()
{
string msgText = "";
if (TxMode == eTxMode.File) {
msgText= comPort.ReadExisting(); //Lettura dati dal Buffer
}
return msgText;
}
ReadFileStream
(),
consente di leggere i dati da un file e di memorizzarli in un buffer. Inoltre concatena in una stringa tutti i dati letti dal file.
public
string ReadFileStream(string path)
{
string s = "";
NumTxByte = 0;
using (FileStream fs = File.OpenRead(path)) {
int size= Convert.ToInt32(fs.Length);
TxBuf = newbyte[size];
fs.Read(TxBuf, 0, size);
for (int i=0; i< size; ++i) {
if (Convert.ToChar(TxBuf[i]) != '\r')
s += Convert.ToChar(TxBuf[i]);
}
fs.Close();
NumTxByte= size;
}
return s;
}