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 = ;
Port.Parity = Parity.None;
Port.StopBits = StopBits.One;
Port.NewLine = "\r\n";
Port.WriteTimeout = ;
Port.ReadTimeout = ;
Port.Handshake = Handshake.None;
Port.ReceivedBytesThreshold = ;
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) > )
{
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, , 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) > )
{
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 != )
{
while (port.BytesToRead != )
{
byte[] recvBytes = new byte[port.BytesToRead];
int bytes = port.Read(recvBytes, , recvBytes.Length);
if (recvBytes.Length != )
{
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 == -)
temp = "";
else
temp = temp.Remove(, index);
}
if (temp.Length > )
{
int NoDataBagLen = Struct.Head.Length + Struct.Cmd.Length + Struct.Other.Length + Struct.DataLen.Length + Struct.VerifyLen + Struct.EndLen;
int BagDataLen = ;
if (temp.Length > (Struct.DataLen.StartPosition * + Struct.DataLen.Length * ))
{
#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 > && temp.Length / >= NoDataBagLen + BagDataLen)
{
string FullBag = temp.Substring(, (NoDataBagLen + BagDataLen) * );
BagItemContent CurBagItem = new BagItemContent();
CurBagItem.Head = FullBag.Substring(Struct.Head.StartPosition * , Struct.Head.Length * ).Replace(" ", "");
CurBagItem.Cmd = FullBag.Substring(Struct.Cmd.StartPosition * , Struct.Cmd.Length * ).Replace(" ", "");
CurBagItem.Other = FullBag.Substring(Struct.Other.StartPosition * , Struct.Other.Length * ).Replace(" ", "");
CurBagItem.DataLen = FullBag.Substring(Struct.DataLen.StartPosition * , Struct.DataLen.Length * ).Replace(" ", "");
CurBagItem.RealData = FullBag.Substring(Struct.RealDataPos * , BagDataLen * );
CurBagItem.Verify = FullBag.Substring(FullBag.Length - (Struct.VerifyLen + Struct.EndLen) * , Struct.VerifyLen * ).Replace(" ", "");
CurBagItem.End = FullBag.Substring(FullBag.Length - Struct.EndLen * , Struct.EndLen * ).Replace(" ", "");
if (Struct.ByteOrder == )//高字节在后,低字节在前
{
CurBagItem.Head = Struct.Head.Length <= ? CurBagItem.Head : ReverseStr(CurBagItem.Head, );
CurBagItem.Cmd = (Struct.Cmd.Length <= ? CurBagItem.Cmd : ReverseStr(CurBagItem.Cmd, ));
CurBagItem.DataLen = Struct.DataLen.Length <= ? CurBagItem.DataLen : ReverseStr(CurBagItem.DataLen, );
//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 <= ? CurBagItem.Verify : ReverseStr(CurBagItem.Verify, );
CurBagItem.End = Struct.EndLen <= ? CurBagItem.End : ReverseStr(CurBagItem.End, );
}
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(, FullBag.Length);
if (temp.Length <= )
{
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 = ;
string CurDataLen = "";
AllBagData = AllBagData.Replace(" ", "");
string CurDataLenOrg = AllBagData.Substring(Struct.DataLen.StartPosition * , Struct.DataLen.Length * );
if (Struct.ByteOrder == )//高字节在后,低字节在前
{
CurDataLen = ReverseStr(CurDataLenOrg, );
BagDataLen = Convert.ToInt32(CurDataLen, );//16进制 需改成通用
}
else
{
CurDataLen = CurDataLenOrg;
BagDataLen = Convert.ToInt32(CurDataLen, );//华气特殊 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 = ;
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 * , Struct.DataLen.Length * );
if (Struct.ByteOrder == )//高字节在后,低字节在前
{
CurDataLen = ReverseStr(CurDataLenOrg, );
//for (int i = Struct.DataLen.Length; i > 0; i--)
//{
// CurDataLen += CurDataLenOrg.Substring((i - 1) * 2, 2);
//}
RealDataLen = Convert.ToInt32(CurDataLen, );
}
else
{
CurDataLen = CurDataLenOrg;
RealDataLen = Convert.ToInt32(CurDataLen, );//华气特殊
}
CurTotalBagLen += RealDataLen;
if (BagStr.Length / != CurTotalBagLen)
{
IsRight = IsRight && false;
}
}
#endregion return 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 = ; 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 % ) != )
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / ];
for (int i = ; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * , ).Trim(), );
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;
}
} }
转载地址:https://www.cnblogs.com/TBW-Superhero/p/6839545.html
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 = ""; else temp = 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; } } #endregion
return 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; } }}
c# 串口SerialPort的更多相关文章
- C#串口SerialPort常用属性方法
SerialPort(): //属性 .BaudRate;获取或设置波特率 .BytesToRead;得到 接收到数据的字节数 .BytesToWrites;得到送往串口的字节数 .DataBits; ...
- (转)C#串口SerialPort常用属性方法
SerialPort(): //属性 .BaudRate;获取或设置波特率 .BytesToRead;得到 接收到数据的字节数 .BytesToWrites;得到送往串口的字节数 .DataBits; ...
- 使用Java进行串口SerialPort通讯
1.准备工作 在进行串口连接通讯前,必须保证你当前操作电脑上有可用且闲置的串口.因为一般的电脑上只有一个或者两个串口,如COM1或COM2,但大多数情况下,这些串口可能会被其他的程序或者 ...
- C#串口serialPort操作
现在大多数硬件设备均采用串口技术与计算机相连,因此串口的应用程序开发越来越普遍.例如,在计算机没有安装网卡的情况下,将本机上的一些信息数据 传输到另一台计算机上,那么利用串口通信就可以实现.运行本程序 ...
- C# 通过SerialPort简单调用串口
问题 最近比较经常使用串口进行发送以及传输数据,但是笔者在刚开始接触SerialPort类时,对于Write之后去Read数据的时候,由于设备上面还没有返回数据,读取到的只能是空值.然而,再进行下一次 ...
- C# 串口接收数据中serialPort.close()死锁
最近在做一个有关高铁模拟仓显示系统的客户端程序,在这个程序中要运用串口serialPort传输数据,因为每次接收数据结束后要更新UI界面,所以就用到了的Invoke,将更新UI的程序代码封装到一个方法 ...
- Visual studio之C# 串口通讯SerialPort
背景 App需要串口进行通讯,在此做个记录和简要说明. 正文 添加命名空间 using System.IO.Ports; 实例化串口 SerialPort serialPortO = new Seri ...
- C#上位机制作之串口接受数据(利用接受事件)
前面设计好了界面,现在就开始写代码了,首先定义一个串口对象.. SerialPort serialport = new SerialPort();//定义串口对象 添加串口扫描函数,扫描出来所有可用串 ...
- C# 对串口的操作
初始化 串口 SerialPort sp = new SerialPort(); sp.PortName = BasicParameters.IniReadValue(strPath, "C ...
随机推荐
- 使用 Moq 测试.NET Core 应用 - Why Moq?
什么是Mock 当对代码进行测试的时候, 我们经常需要用到一些模拟(mock)技术. 绿色的是需要被测试的类, 黄色是它的依赖项, 灰色的无关的类 在一个项目里, 我们经常需要把某一部分程序独立出来以 ...
- ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...
- .NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.熔断.降级与AOP 1.1 啥是熔断? 在广义的解释中,熔断主要是指为控制股票.期货或其他金融衍生产品的交易风险,为其单日价格波动幅度 ...
- ASP.NET Core中使用GraphQL - 第四章 GraphiQL
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- 阿里云Ubuntu下安装、配置权限和导入本地mongodb
---恢复内容开始--- 第一部分:首先先在Ubuntu下安装好mongodb,步骤如下: 首先我们需要借助远程管理工具链接到阿里云上的ubuntu系统,接着进行如下操作 一.导出软件源的公钥 sud ...
- DotNetCore跨平台~EFCore2.0连接Mysql的烦恼-已解决
回到目录 对于传统的nuget包,我们习惯上用官方或者大型组织的,因为它们比较考靠谱,但就在前两天.net core2.0发布后,我把efcore也升级到2.0了,mysql.EfCore也升级到支持 ...
- .net core +codefirst(.net core 基础入门,适合这方面的小白阅读,本文使用mysql或mssql)
设置为model所在的那一层 前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以.net mvc开发员很容易入手.net core mvc .但是两个又 ...
- Java 数组及数组常用算法
1 数组也是一种类型 Java中要求所有的数组元素具有相同的数据类型.因此在一个数组中,数组元素的类型是唯一的,不能存储多种类型的数据. 一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此 ...
- Java 平台无关性的基石
Java 在刚刚诞生之初就提出过一个非常著名的口号:"一次编写,到处运行", 这句话充分表达了软件开发人员对冲破平台界限的渴望 在竞争激烈的 IT 领域,各种不同的硬件体系结构和不 ...
- Spring MVC(四)文件上传
文件上传步骤 1.写一个文件上传的页面 2.写一个文件上传的控制器 注意: 1.method="post" 2.enctype="multipart/form-data& ...