1、SerialClass
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
namespace AutoMeasureLib.Utils
{
public class SerialClass
{
SerialPort _serialPort = null;
//定義委托
public delegate void SerialPortDataReceiveEventArgs(object sender, SerialDataReceivedEventArgs e, byte[] bits);
//定義接收數(shù)據(jù)事件
public event SerialPortDataReceiveEventArgs DataReceived;
//定義接收錯誤事件
//public event SerialErrorReceivedEventHandler Error;
//接收事件是否有效 false表示有效
public bool ReceiveEventFlag = false;
//獲取串口名
private string protName;
public string PortName
{
get { return _serialPort.PortName; }
set
{
_serialPort.PortName = value;
protName = value;
}
}
//獲取比特率
private int baudRate;
public int BaudRate
{
get { return _serialPort.BaudRate; }
set
{
_serialPort.BaudRate = value;
baudRate = value;
}
}
/// <summary>
/// 默認(rèn)構(gòu)造函數(shù),操作COM1,速度為9600,沒有奇偶校驗,8位字節(jié),停止位為1 "COM1", 9600, Parity.None, 8, StopBits.One
/// </summary>
public SerialClass()
{
_serialPort = new SerialPort();
}
/// <summary>
/// 構(gòu)造函數(shù),
/// </summary>
/// <param name="comPortName"></param>
public SerialClass(string comPortName)
{
_serialPort = new SerialPort(comPortName);
_serialPort.BaudRate = 9600;
_serialPort.Parity = Parity.Even;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
_serialPort.RtsEnable = true;
_serialPort.ReadTimeout = 2000;
setSerialPort();
}
/// <summary>
/// 構(gòu)造函數(shù),可以自定義串口的初始化參數(shù)
/// </summary>
/// <param name="comPortName">需要操作的COM口名稱</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="parity">奇偶校驗位</param>
/// <param name="dataBits">數(shù)據(jù)長度</param>
/// <param name="stopBits">停止位</param>
public SerialClass(string comPortName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_serialPort = new SerialPort(comPortName, baudRate, parity, dataBits, stopBits);
_serialPort.RtsEnable = true; //自動請求
_serialPort.ReadTimeout = 3000;//超時
setSerialPort();
}
/// <summary>
/// 析構(gòu)函數(shù),關(guān)閉串口
/// </summary>
~SerialClass()
{
if (_serialPort.IsOpen)
_serialPort.Close();
}
/// <summary>
/// 設(shè)置串口參數(shù)
/// </summary>
/// <param name="comPortName">需要操作的COM口名稱</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="dataBits">數(shù)據(jù)長度</param>
/// <param name="stopBits">停止位</param>
public void setSerialPort(string comPortName, int baudRate, int dataBits, int stopBits)
{
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.PortName = comPortName;
_serialPort.BaudRate = baudRate;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = dataBits;
_serialPort.StopBits = (StopBits)stopBits;
_serialPort.Handshake = Handshake.None;
_serialPort.RtsEnable = false;
_serialPort.ReadTimeout = 3000;
_serialPort.NewLine = "/r/n";
setSerialPort();
}
/// <summary>
/// 設(shè)置接收函數(shù),設(shè)置串口資源,還需重載多個設(shè)置串口的函數(shù)
/// </summary>
void setSerialPort()
{
if (_serialPort != null)
{
//設(shè)置觸發(fā)DataReceived事件的字節(jié)數(shù)為1
_serialPort.ReceivedBytesThreshold = 1;
//接收到一個字節(jié)時,也會觸發(fā)DataReceived事件
_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
//接收數(shù)據(jù)出錯,觸發(fā)事件
_serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);
//打開串口
//openPort();
}
}
/// <summary>
/// 打開串口資源
/// <returns>返回bool類型</returns>
/// </summary>
public bool openPort()
{
bool ok = false;
//如果串口是打開的,先關(guān)閉
if (_serialPort.IsOpen)
_serialPort.Close();
try
{
//打開串口
_serialPort.Open();
ok = true;
}
catch (Exception Ex)
{
throw Ex;
}
return ok;
}
/// <summary>
/// 關(guān)閉串口資源,操作完成后,一定要關(guān)閉串口
/// </summary>
public void closePort()
{
//如果串口處于打開狀態(tài),則關(guān)閉
if (_serialPort.IsOpen)
_serialPort.Close();
}
/// <summary>
/// 接收串口數(shù)據(jù)事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//禁止接收事件時直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
System.Threading.Thread.Sleep(20);
byte[] _data = new byte[_serialPort.BytesToRead];
_serialPort.Read(_data, 0, _data.Length);
if (_data.Length == 0) { return; }
if (DataReceived != null)
{
DataReceived(sender, e, _data);
}
//_serialPort.DiscardInBuffer(); //清空接收緩沖區(qū)
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 接收數(shù)據(jù)出錯事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
}
/// <summary>
/// 發(fā)送數(shù)據(jù)string類型
/// </summary>
/// <param name="data"></param>
public void SendData(string data)
{
//發(fā)送數(shù)據(jù)
//禁止接收事件時直接退出
if (ReceiveEventFlag)
{
return;
}
if (_serialPort.IsOpen)
{
_serialPort.Write(data);
}
}
/// <summary>
/// 發(fā)送數(shù)據(jù)byte類型
/// </summary>
/// <param name="data">要發(fā)送的數(shù)據(jù)字節(jié)</param>
public void SendData(byte[] data, int offset, int count)
{
//禁止接收事件時直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
if (_serialPort.IsOpen)
{
//_serialPort.DiscardInBuffer();//清空接收緩沖區(qū)
_serialPort.Write(data, offset, count);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 發(fā)送命令
/// </summary>
/// <param name="SendData">發(fā)送數(shù)據(jù)</param>
/// <param name="ReceiveData">接收數(shù)據(jù)</param>
/// <param name="Overtime">超時時間</param>
/// <returns></returns>
public int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime)
{
if (_serialPort.IsOpen)
{
try
{
ReceiveEventFlag = true; //關(guān)閉接收事件
_serialPort.DiscardInBuffer(); //清空接收緩沖區(qū)
_serialPort.Write(SendData, 0, SendData.Length);
int num = 0, ret = 0;
System.Threading.Thread.Sleep(10);
ReceiveEventFlag = false; //打開事件
while (num++ < Overtime)
{
if (_serialPort.BytesToRead >= ReceiveData.Length)
break;
System.Threading.Thread.Sleep(10);
}
if (_serialPort.BytesToRead >= ReceiveData.Length)
{
ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);
}
else
{
ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);
}
ReceiveEventFlag = false; //打開事件
return ret;
}
catch (Exception ex)
{
ReceiveEventFlag = false;
throw ex;
}
}
return -1;
}
public string SendString(string SendData, int Overtime)
{
if (_serialPort.IsOpen)
{
try
{
ReceiveEventFlag = true; //關(guān)閉接收事件
_serialPort.DiscardInBuffer(); //清空接收緩沖區(qū)
_serialPort.Write(SendData);
int num = 0;
string ret = "";
while (num++ < Overtime)
{
if (_serialPort.BytesToRead > 3)
break;
System.Threading.Thread.Sleep(10);
}
if (_serialPort.BytesToRead > 3)
{
byte[] ReceiveData = new byte[SendData.Length * 3];
_serialPort.Read(ReceiveData, 0, SendData.Length * 3);
string HexStr = SerialClass.byteToHexStr(ReceiveData);
ret = SerialClass.HexStringToString(HexStr, Encoding.UTF8);
}
_serialPort.DiscardInBuffer(); //清空接收緩沖區(qū)
System.Threading.Thread.Sleep(10);
ReceiveEventFlag = false; //打開事件
return ret;
}
catch (Exception ex)
{
ReceiveEventFlag = false;
throw ex;
}
}
return null;
}
/// <summary>
/// 獲取串口,獲取所有已連接短信貓設(shè)備的串口
/// </summary>
/// <returns></returns>
public string[] serialsIsConnected()
{
List<string> lists = new List<string>();
string[] seriallist = getSerials();
foreach (string s in seriallist)
{
}
return lists.ToArray();
}
/// <summary>
/// 獲取當(dāng)前全部串口資源,獲得當(dāng)前電腦上的所有串口資源
/// </summary>
/// <returns></returns>
public static string[] getSerials()
{
return SerialPort.GetPortNames();
}
/// <summary>
/// 把字節(jié)型轉(zhuǎn)換成十六進制字符串
/// </summary>
/// <param name="InBytes"></param>
/// <returns></returns>
public static string ByteToString(byte[] InBytes)
{
string StringOut = "";
foreach (byte InByte in InBytes)
{
StringOut = StringOut + String.Format("{0:X2} ", InByte);
}
return StringOut;
}
/// <summary>
/// 把十六進制字符串轉(zhuǎn)換成字節(jié)型(方法1)
/// </summary>
/// <param name="InString"></param>
/// <returns></returns>
public static byte[] StringToByte(string InString)
{
string[] ByteStrings;
ByteStrings = InString.Split(" ".ToCharArray());
byte[] ByteOut;
ByteOut = new byte[ByteStrings.Length];
for (int i = 0; i <= ByteStrings.Length - 1; i++)
{
//ByteOut[i] = System.Text.Encoding.ASCII.GetBytes(ByteStrings[i]);
ByteOut[i] = Byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);
//ByteOut[i] =Convert.ToByte("0x" + ByteStrings[i]);
}
return ByteOut;
}
/// <summary>
/// 字符串轉(zhuǎn)16進制字節(jié)數(shù)組(方法2)
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
public static byte[] strToToHexByte(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0)
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return returnBytes;
}
/// <summary>
/// 字節(jié)數(shù)組轉(zhuǎn)16進制字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string byteToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
/// <summary>
/// 字符串轉(zhuǎn)16進制字符串
/// </summary>
/// <param name="s"></param>
/// <param name="encode"></param>
/// <returns></returns>
public static string StrToHexString(string s, Encoding encode)
{
byte[] b = encode.GetBytes(s);//按照指定編碼將string編程字節(jié)數(shù)組
string result = string.Empty;
for (int i = 0; i < b.Length; i++)//逐字節(jié)變?yōu)?6進制字符,以%隔開
{
result += "%" + Convert.ToString(b[i], 16);
}
return result;
}
/// <summary>
/// 將16進制字符串轉(zhuǎn)為字符串
/// </summary>
/// <param name="hs"></param>
/// <param name="encode"></param>
/// <returns></returns>
public static string HexStringToString(string hs, Encoding encode)
{
string strTemp = "";
byte[] b = new byte[hs.Length / 2];
for (int i = 0; i < hs.Length / 2; i++)
{
strTemp = hs.Substring(i * 2, 2);
b[i] = Convert.ToByte(strTemp, 16);
}
//按照指定編碼將字節(jié)數(shù)組變?yōu)樽址? return encode.GetString(b);
}
}
}
2、連接串口
/// <summary>
/// 連接串口
/// </summary>
private bool ConnectSerialPort()
{
if (SerialPort != null)
{
return true;
}
FrmConnect frmConnect = new FrmConnect();
frmConnect.Owner = this;
if (frmConnect.ConnectSucc)
{
SerialPort = frmConnect.SerialPort;
SerialPort.DataReceived += new SerialClass.SerialPortDataReceiveEventArgs(SerialPort_DataReceived);
return true;
}
else
{
return false;
}
}
3、底層串口數(shù)據(jù)接收
/// <summary>
/// 底層串口數(shù)據(jù)接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <param name="bits"></param>
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e, ModbusMessage modbusMessage)
{
try
{
// SetMsg(modbusMessage.TipMsg);
switch (modbusMessage.Type)
{
case ModbusMsgType.LightScanBegin:
LightScanBeginHandler(modbusMessage);
break;
case ModbusMsgType.LightScanEnd:
LightScanEndHandler(modbusMessage);
break;
case ModbusMsgType.CalWeight:
CalWeightHandler(modbusMessage);
break;
case ModbusMsgType.BottomError:
BottomErrorHandler(modbusMessage);
break;
case ModbusMsgType.Speed:
SpeedHandler(modbusMessage);
break;
default:
break;
}
}catch(Exception ex)
{
LogHelper.logAsync(ex.ToString());
}
}