c# 串口SerialPort
生活随笔
收集整理的這篇文章主要介紹了
c# 串口SerialPort
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
創建SerialPortFun類
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO.Ports; using System.Threading; using LogSpace;namespace SerialPortSpace {public class SerialPortFun{/// <summary>/// 串口及串口緩存數據/// </summary>public static List<ComPort> LstComPort = new List<ComPort>();/// <summary>/// 是否在進行串口結束操作/// </summary>public static bool PortIsCloseing = false;/// <summary>/// 初始化串口,并返回當前串口的結構/// </summary>/// <param name="Port"></param>/// <param name="PortNo"></param>/// <param name="BaudRate"></param>/// <param name="ReciveData"></param>public static ComPort InitSerialPort(SerialPort Port, string PortNo, int BaudRate, BagStruct CurBagStruct, string StartStr, string EndStr, string PortNameDesc, string PortRemark){Port.PortName = PortNo;Port.BaudRate = BaudRate;Port.DataBits = 8;Port.Parity = Parity.None;Port.StopBits = StopBits.One;Port.NewLine = "\r\n";Port.WriteTimeout = 5000;Port.ReadTimeout = 5000;Port.Handshake = Handshake.None;Port.ReceivedBytesThreshold = 1;Port.RtsEnable = true;Port.DataReceived += Port_DataReceived;//定義接收數據事件ComPort PortItem = new ComPort();PortItem.Port = Port;PortItem.PortRealName = PortNameDesc;PortItem.PortDesc = PortRemark;PortItem.PortIsRcving = false;PortItem.LastRebackTime = DateTime.Now;PortItem.RcvBag = CurBagStruct;PortItem.StartStr = StartStr;PortItem.EndStr = EndStr;PortItem.SendOrder = new List<string>();PortItem.RcvData = string.Empty;PortItem.RcvLst = new List<PortReciveDataItem>();if (LstComPort.Count(c => c.Port == Port) > 0){LstComPort.RemoveAll(c => c.Port == Port);}LstComPort.Add(PortItem);return PortItem;}/// <summary>/// 定義數據包中每項的開始位置及所占字節數/// </summary>/// <param name="StartPosition"></param>/// <param name="Length"></param>/// <returns></returns>public static BagItemPosition SetBagItemPosition(int StartPosition, int Length){BagItemPosition Item = new BagItemPosition();Item.StartPosition = StartPosition;Item.Length = Length;return Item;}/// <summary>/// 定義返回數據包結構/// </summary>/// <param name="ByteOrder">字節順序約定 0--高字節在前,低字節在后,1--高字節在后,低字節在前</param>/// <param name="HeadItem">包頭所占字節數</param>/// <param name="HeadItem">命令所占字節數</param>/// <param name="OthItem">其他位總共占字節數</param>/// <param name="DataLenItem">數據長度位所占字節數</param>/// <param name="VerItem">校驗位所占字節數</param>/// <param name="EndItem">包尾所占字節數</param>/// <returns></returns>public static BagStruct SetBagStruct(int ByteOrder, BagItemPosition HeadItem, BagItemPosition CmdItem, BagItemPosition OthItem, BagItemPosition DataLenItem, int RealDataItem, int VerItem, int EndItem){BagStruct CurRcvBagStruct = new BagStruct();CurRcvBagStruct.ByteOrder = ByteOrder;CurRcvBagStruct.Head = HeadItem;CurRcvBagStruct.Cmd = CmdItem;CurRcvBagStruct.Other = OthItem;CurRcvBagStruct.DataLen = DataLenItem;CurRcvBagStruct.RealDataPos = RealDataItem;CurRcvBagStruct.VerifyLen = VerItem;CurRcvBagStruct.EndLen = EndItem;return CurRcvBagStruct;}/// <summary>/// 打開串口/// </summary>/// <param name="PortName"></param>public static void OpenSerialPort(SerialPort Port){if (!Port.IsOpen){Port.Open();}}/// <summary>/// 發送串口數據/// </summary>/// <param name="Port"></param>/// <param name="Data"></param>public static bool SetPortData(SerialPort Port, string Data){bool CurSendFlag = false;if (Port.IsOpen){byte[] buf = strToHexByte(Data);Port.Write(buf, 0, buf.Length);CurSendFlag = true;}return CurSendFlag;}#region 接收串口應答包/// <summary>/// 接收串口應答包/// </summary>/// <param name="sender"></param>/// <param name="e"></param>public static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e){if (PortIsCloseing){return;}SerialPort port = sender as SerialPort;DateTime CurTime = DateTime.Now;string RcvData = string.Empty;if (LstComPort != null){if (LstComPort.Count(c => c.Port.PortName == port.PortName) > 0){ComPort comPort = LstComPort.Find(c => c.Port.PortName == port.PortName);try{Log.WriteLogToLocal(CurTime + "接收前" + comPort.PortRealName + "數據包臨時數據:\r\n" + comPort.RcvData + "\r\n------------------------\r\n", "Log\\IBO_LOG", comPort.PortDesc + "_Receive");RcvData = comPort.RcvData;comPort.PortIsRcving = true;//正在接收串口數據StringBuilder CurRcvData = new StringBuilder();if (port.IsOpen && port.BytesToRead != 0){while (port.BytesToRead != 0){byte[] recvBytes = new byte[port.BytesToRead];int bytes = port.Read(recvBytes, 0, recvBytes.Length);if (recvBytes.Length != 0){foreach (byte b in recvBytes){CurRcvData.Append(b.ToString("X2") + " ");}}//Thread.Sleep(20);}Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "原始數據:\r\n" + CurRcvData + "\r\n------------------------\r\n", "Log\\IBO_LOG", comPort.PortDesc + "_Receive");RcvData += CurRcvData;CurRcvData.Clear();//接收到的數據進行處理,并存儲在串口對應的接收隊列中//SerialPortFun.DealPortData(comPort, RcvData, CurTime);SerialPortFun.ConcatFullBag(comPort, comPort.RcvBag, RcvData, CurTime);comPort.LastRebackTime = CurTime;}}catch (Exception ex){Log.WriteLogToLocal(CurTime + "接收" + comPort.PortRealName + "串口數據(" + RcvData + ")錯誤:(" + ex.Message+")"+ex.StackTrace + "\r\n", "Log\\IBO_LOG\\ErrorLog", comPort.PortDesc + "_Receive");}finally{comPort.PortIsRcving = false;//接收串口數據完畢}}}}#endregion/// <summary>/// 接收到的數據進行處理,并存儲在串口對應的接收隊列中/// </summary>/// <param name="port"></param>/// <param name="Struct"></param>/// <param name="CurRcvData"></param>/// <param name="CurTime"></param>public static void ConcatFullBag(ComPort port, BagStruct Struct, string CurRcvData, DateTime CurTime){Log.WriteLogToLocal(CurTime + "數據包處理" + port.PortRealName + "原始數據:\r\n" + CurRcvData + "\r\n------------------------\r\n", "Log\\IBO_LOG", port.PortDesc + "_Receive");string temp = CurRcvData;while (true){//校驗包頭,包尾if (!temp.StartsWith(port.StartStr)){int index = temp.IndexOf(port.StartStr);if (index == -1)temp = "";elsetemp = temp.Remove(0, index);}if (temp.Length > 0){int NoDataBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;int BagDataLen = 0;if (temp.Length > (Struct.DataLen.StartPosition * 3 + Struct.DataLen.Length * 3)){#region 獲取數據包的業務數據長度BagDataLen = GetBagDataLen(Struct, temp);//string CurDataLen = "";//string CurDataLenOrg = temp.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3);//if (Struct.ByteOrder == 1)//高字節在后,低字節在前//{// CurDataLen = ReverseStr(CurDataLenOrg, 2);// BagDataLen = Convert.ToInt32(CurDataLen, 16);//16進制//}//else//{// CurDataLen = CurDataLenOrg;// BagDataLen = Convert.ToInt32(CurDataLen, 10);//華氣特殊 10進制//}#endregion}if (BagDataLen > 0 && temp.Length / 3 >= NoDataBagLen + BagDataLen){string FullBag = temp.Substring(0, (NoDataBagLen + BagDataLen) * 3);BagItemContent CurBagItem = new BagItemContent();CurBagItem.Head = FullBag.Substring(Struct.Head.StartPosition * 3, Struct.Head.Length * 3).Replace(" ", "");CurBagItem.Cmd = FullBag.Substring(Struct.Cmd.StartPosition * 3, Struct.Cmd.Length * 3).Replace(" ", "");CurBagItem.Other = FullBag.Substring(Struct.Other.StartPosition * 3, Struct.Other.Length * 3).Replace(" ", "");CurBagItem.DataLen = FullBag.Substring(Struct.DataLen.StartPosition * 3, Struct.DataLen.Length * 3).Replace(" ", "");CurBagItem.RealData = FullBag.Substring(Struct.RealDataPos * 3, BagDataLen * 3);CurBagItem.Verify = FullBag.Substring(FullBag.Length - (Struct.VerifyLen + Struct.EndLen) * 3, Struct.VerifyLen * 3).Replace(" ", "");CurBagItem.End = FullBag.Substring(FullBag.Length - Struct.EndLen * 3, Struct.EndLen * 3).Replace(" ", "");if (Struct.ByteOrder == 1)//高字節在后,低字節在前{CurBagItem.Head = Struct.Head.Length <= 1 ? CurBagItem.Head : ReverseStr(CurBagItem.Head, 2);CurBagItem.Cmd = (Struct.Cmd.Length <= 1 ? CurBagItem.Cmd : ReverseStr(CurBagItem.Cmd, 2));CurBagItem.DataLen = Struct.DataLen.Length <= 1 ? CurBagItem.DataLen : ReverseStr(CurBagItem.DataLen, 2);//CurBagItem.RealData,CurBagItem.Other需根據具體情況解析暫不反轉//CurBagItem.RealData = RealDataLen <= 1 ? CurBagItem.RealData : ReverseStr(CurBagItem.RealData, 2);//CurBagItem.Other = Struct.Other.Length <= 1 ? CurBagItem.Other : ReverseStr(CurBagItem.Other, 2);CurBagItem.Verify = Struct.VerifyLen <= 1 ? CurBagItem.Verify : ReverseStr(CurBagItem.Verify, 2);CurBagItem.End = Struct.EndLen <= 1 ? CurBagItem.End : ReverseStr(CurBagItem.End, 2);}PortReciveDataItem NewItem = new PortReciveDataItem();NewItem.ReciveTime = CurTime;NewItem.ReciveDataItem = CurBagItem;NewItem.ReciveDataStr = FullBag;port.RcvLst.Add(NewItem);Log.WriteLogToLocal(CurTime + "加入" + port.PortRealName + "完整數據包:\r\n" + FullBag + "\r\n------------------------\r\n", "Log\\IBO_LOG", port.PortDesc + "_Receive");temp = temp.Remove(0, FullBag.Length);if (temp.Length <= 0){port.RcvData = "";break;}// port.RcvData = temp.Substring((NoDataBagLen + BagDataLen) * 3);//剩余字符放入下個數據包}else{port.RcvData = CurRcvData;//不是完整包,等待完整數據break;}}else{//丟棄不符合的串口數據port.RcvData = "";Log.WriteLogToLocal(CurTime + "丟棄" + port.PortRealName + "原始數據:\r\n" + CurRcvData + "\r\n------------------------\r\n", "Log\\IBO_LOG", port.PortDesc + "_Receive");break;}}}/// <summary>/// 獲取包長度/// </summary>/// <param name="Struct"></param>/// <param name="AllBagData"></param>/// <returns></returns>public static int GetBagDataLen(BagStruct Struct, string AllBagData){int BagDataLen = 0;string CurDataLen = "";AllBagData = AllBagData.Replace(" ", "");string CurDataLenOrg = AllBagData.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);if (Struct.ByteOrder == 1)//高字節在后,低字節在前{CurDataLen = ReverseStr(CurDataLenOrg, 2);BagDataLen = Convert.ToInt32(CurDataLen, 16);//16進制 需改成通用}else{CurDataLen = CurDataLenOrg;BagDataLen = Convert.ToInt32(CurDataLen, 10);//華氣特殊 10進制}return BagDataLen;}/// <summary>/// 校驗數據包/// </summary>/// <param name="BagStr"></param>/// <returns></returns>public static bool CheckBag(string BagHead, string BagEnd, BagStruct Struct, string BagStr, out int RealDataLen){bool IsRight = true;RealDataLen = 0;BagStr = BagStr.Replace(" ", "");//校驗包頭,包尾if (!(BagStr.StartsWith(BagHead) && BagStr.EndsWith(BagEnd))){IsRight = IsRight && false;}#region 校驗包總長度int CurTotalBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;if (BagStr.Length < Struct.DataLen.StartPosition + Struct.DataLen.Length){IsRight = IsRight && false;}else{string CurDataLen = "";string CurDataLenOrg = BagStr.Substring(Struct.DataLen.StartPosition * 2, Struct.DataLen.Length * 2);if (Struct.ByteOrder == 1)//高字節在后,低字節在前{CurDataLen = ReverseStr(CurDataLenOrg, 2);//for (int i = Struct.DataLen.Length; i > 0; i--)//{// CurDataLen += CurDataLenOrg.Substring((i - 1) * 2, 2);//}RealDataLen = Convert.ToInt32(CurDataLen, 16);}else{CurDataLen = CurDataLenOrg;RealDataLen = Convert.ToInt32(CurDataLen, 10);//華氣特殊}CurTotalBagLen += RealDataLen;if (BagStr.Length / 2 != CurTotalBagLen){IsRight = IsRight && false;}}#endregionreturn IsRight;}/// <summary>/// 反轉字符串/// </summary>/// <param name="Str"></param>/// <param name="Len"></param>/// <returns></returns>public static string ReverseStr(string Str, int Len){Str = Str.Replace(" ", "");string NewStr = "";List<string> ls = new List<string>();for (int i = 0; i < Str.Length; i += Len){ls.Add(Str.Substring(i, Len)); // 兩兩截取}ls.Reverse();// 兩兩反轉foreach (string item in ls){NewStr += item;}return NewStr;}/// <summary> /// 16進制字符串轉字節數組 /// </summary> /// <param name="hexString"></param> /// <returns></returns> public static byte[] strToHexByte(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).Trim(), 16);return returnBytes;}} }創建數據接收
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO.Ports;namespace SerialPortSpace {/// <summary>/// 接收數據類/// </summary>public class PortReciveDataItem{public BagItemContent ReciveDataItem { get; set; }public DateTime ReciveTime { get; set; }public string ReciveDataStr { get; set; }}/// <summary>/// 串口緩存數據/// </summary>public class ComPort{/// <summary>/// 串口/// </summary>public SerialPort Port{set;get;}/// <summary>/// 當前串口名稱/// </summary>public string PortRealName{set;get;}/// <summary>/// 當前串口描述/// </summary>public string PortDesc{set;get;}/// <summary>/// 當前串口是否正在接收數據---關閉串口判斷/// </summary>public bool PortIsRcving{set;get;}/// <summary>/// 最近返回數據時間/// </summary>public DateTime LastRebackTime{get;set;}/// <summary>/// 定義接收包結構/// </summary>public BagStruct RcvBag{get;set;}/// <summary>/// 開始字符/// </summary>public string StartStr{set;get;}/// <summary>/// 結束字符/// </summary>public string EndStr{set;get;}/// <summary>/// 串口發送是指令集合/// </summary>public List<string> SendOrder{set;get;}/// <summary>/// 存儲不完整包 臨時數據/// </summary>public string RcvData{set;get;}/// <summary>/// 接收到的串口數據--完整包,臨時存放/// </summary>public List<PortReciveDataItem> RcvLst{set;get;}}/// <summary>/// 接收包的結構定義/// </summary>public class BagStruct{/// <summary>/// 字節順序約定 0--高字節在前,低字節在后,1--高字節在后,低字節在前/// </summary>public int ByteOrder{set;get;}/// <summary>/// 包頭所占字節數/// </summary>public BagItemPosition Head{set;get;}/// <summary>/// 命令字段所占字節數/// </summary>public BagItemPosition Cmd{set;get;}/// <summary>/// 除實際數據包中數據長度及實際數據以外的其他數據項所占字節數/// </summary>public BagItemPosition Other{set;get;}/// <summary>/// 數據字段長度項所占字節數/// </summary>public BagItemPosition DataLen{set;get;}/// <summary>/// 實際數據所占字節數---可變的,可以根據實際數據包由DataLen計算所得/// </summary>public int RealDataPos//開始位置{set;get;}/// <summary>/// 校驗位所占字節數/// </summary>public int VerifyLen{set;get;}/// <summary>/// 包尾所占字節數/// </summary>public int EndLen{set;get;}}/// <summary>/// 定義數據包中每項的開始位置及所占字節數/// </summary>public class BagItemPosition{/// <summary>/// 開始位置/// </summary>public int StartPosition{set;get;}/// <summary>/// 所占字節數/// </summary>public int Length{set;get;}}/// <summary>/// 接收包的結構內容/// </summary>public class BagItemContent{/// <summary>/// 包頭/// </summary>public string Head{set;get;}/// <summary>/// 命令字段/// </summary>public string Cmd{set;get;}/// <summary>/// 除實際數據包中數據長度及實際數據以外的其他數據項/// </summary>public string Other{set;get;}/// <summary>/// 數據字段長度項/// </summary>public string DataLen{set;get;}/// <summary>/// 實際數據/// </summary>public string RealData{set;get;}/// <summary>/// 校驗位/// </summary>public string Verify{set;get;}/// <summary>/// 包尾/// </summary>public string End{set;get;}} }總結
以上是生活随笔為你收集整理的c# 串口SerialPort的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小户型适不适合装中央空调如何判断房子适不
- 下一篇: 饿了么和口碑什么时候合并的