シリアルポートクラスについてわかったことをあれこれ書いていきます。
SerialPort SerialPort = new SerialPort();
SerialPort.DataReceived += SerialPortToCalibrationMachine_DataReceived;
SerialPort.PinChanged += SerialPortToCalibrationMachine_PinChanged;
SerialPort.ErrorReceived += SerialPortToCalibrationMachine_ErrorReceived;
SerialPort.BaudRate = 9600;
SerialPort.DataBits = 8;
SerialPort.StopBits = StopBits.One;
SerialPort.Parity = Parity.NONE;
SerialPort.Handshake = Handshake.RequestToSend;
SerialPort.ReadTimeout = 1000;
SerialPort.WriteTimeout = 1000;
SerialPort.RtsEnable = true;
SerialPort.DtrEnable = true;
登録できるイベントは3種類
//データを受信した時に発生するイベントこの中は別スレッドなのでUIを変更するときはInvokeすること
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var serialPort = (SerialPort)sender;
//終端文字が存在するならReadToを使用するのが高速化を図れる
//読み取った値に終端文字は含まれないので注意
//受信した値は文字列型になる
ReceiveString = serialPort.ReadTo("\r\n");
//終端文字がない場合はReadメソッドを使用する
//イベントは最初の文字の受信で発生するため即座にREADを行うとすべてのデータが受信しきっていないのに読み込んでしまう。
//なので数ms待機してから読み込むこと
//受信した値はbyte配列となる
Thread.Sleep(100);
byte[] buffer[] = new buffer[serialPort.BytesToRead];
serialPort.Read(buffer,0,serialPort.BytesToRead);
}
catch (Exception ex)
{
}
}
//RTS CTR CD DSR RIの信号状態が変化した時発生するイベント
private void SerialPort_PinChanged(object sender, SerialPinChangedEventArgs e)
{
var serialPort = (SerialPort)sender;
try
{
//例外処理を追加しておかないと
//USBを接続中に引き抜くとpinチェンジイベントが発生してその時
//POSRTが閉じていると if (serialPort.CtsHolding == false)で例外が発生する
if (e.EventType == SerialPinChange.Break)
{
}
else if (e.EventType == SerialPinChange.CDChanged)
{
}
else if (e.EventType == SerialPinChange.CtsChanged)
{
if (serialPort.CtsHolding == false)
{
LastDisableConnectionDate = DateTime.Now;
}
}
else if (e.EventType == SerialPinChange.DsrChanged)
{
}
else if (e.EventType == SerialPinChange.Ring)
{
}
}
catch (Exception)
{
}
}
private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
if(e.EventType == SerialError.RXOver)
{
}
else if (e.EventType == SerialError.Overrun)
{
}
else if (e.EventType == SerialError.RXParity)
{
}
else if (e.EventType == SerialError.Frame)
{
}
else if (e.EventType == SerialError.TXFull)
{
}
}
信号線の役割
//読み取り専用
var _ = SerialPort.IsOpen;
//読み取り専用 相手機器のキャリア検出信号
//PORTが閉じられている状態でこの値を読み取ろうとすると例外になるため注意
_ = SerialPort.CDHolding;
//読み書き可能 PC側の通信許可信号
_ = SerialPort.DtrEnable;
//読み取り専用 相手機器の通信許可信号
//PORTが閉じられている状態でこの値を読み取ろうとすると例外になるため注意
_ = SerialPort.DsrHolding;
//読み書き可能 PC側の送信許可信号
//これはParityがRequestToSendを選択した場合
//ハードウェアでの制御になるためソフトで値を書き換えようとすると例外になる
_ = SerialPort.RtsEnable;
//読み取り専用 相手機器の送信許可信号
//PORTが閉じられている状態でこの値を読み取ろうとすると例外になるため注意
_ = SerialPort.CtsHolding;
ポートのオープンクローズについて
//ベストプラクティスは、Closeの後数ms待ったのち再度Openを行うことです
if (SerialPort.IsOpen == true)
{
SerialPort.Close();
}
thread.Sleep(100);
if (SerialPort.IsOpen != true)
{
SerialPort.PortName = portCombobox.Text;
SerialPort.Open();
}
接続状態の確認メソッド
//接続されている場合はTRUE
//切断状態はFALSE
private bool ConfirmPortConnectStatus()
{
//IsOpenがOFFの場合は確実に切断
if (SerialPort.IsOpen == false) return false;
//CtsHoldingはPortOpen状態でないと値を取得できない
//つまりCTsHoldingでtrueを受け取れる時は確実にOpen状態かつ物理的につながっている
if(SerialPort.CtsHolding == true) return true;
//送受信の際にはCtsHoldingがOFFになる。それを無視するために連続300MsOFFした場合に物理的に切断されたとみなす。 LastDisableConnectionDateはPinChangedイベントで値を設定
//通信のOFFと区別するため
var timeElapsed = DateTime.Now - LastDisableConnectionDate; // OFFになってからの経過時間
if (timeElapsed.TotalMilliseconds >= 300)
{
return false; // 300ms以上OFFの場合は切断状態と認識
}
return true;
}
ただし、USBシリアル変換器によっては、RTS,CTS信号まで対応していないものが存在する
当方で検証した結果を以下に示す。
対応製品
BSUSRC06
BSUSRC07
非対応製品
ICUSB232FTN
コメント