串口通讯类:SerialPortDao.cs
using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; namespace LY.FuelStationPOS.Protocol { /// <summary> /// 提供对串口的统一访问 /// </summary> public sealed class SerialPortDao { #region 事件和字段定义 public event PortDataReceivedEventHandle Received; public SerialPort serialPort = null; public bool ReceiveEventFlag = false; //接收事件是否有效 false表示有效 private static readonly SerialPortDao instance = new SerialPortDao(); #endregion #region 属性定义 private string protName; public string PortName { get { return serialPort.PortName; } set { serialPort.PortName = value; protName = value; } } #endregion #region 构造函数 private SerialPortDao() { LoadSerialPort(); } private void LoadSerialPort() { serialPort = new SerialPort(); serialPort.BaudRate = 9600; serialPort.Parity = Parity.Even; serialPort.DataBits = 8; serialPort.StopBits = StopBits.One; serialPort.Handshake = Handshake.None; serialPort.RtsEnable = true; serialPort.ReadTimeout = 2000; serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived); } #endregion #region 串口操作集合 /// <summary> /// 返回串口对象的单个实例 /// </summary> /// <returns></returns> public static SerialPortDao GetSerialPortDao() { return instance; } /// <summary> /// 释放串口资源 /// </summary> ~SerialPortDao() { Close(); } /// <summary> /// 打开串口 /// </summary> public void Open() { try { if (!serialPort.IsOpen) { serialPort.Open(); } } catch (Exception ex) { throw ex; } } /// <summary> /// 关闭串口 /// </summary> public void Close() { if (serialPort.IsOpen) { serialPort.Close(); } } /// <summary> /// 串口是否打开 /// </summary> /// <returns></returns> public bool IsOpen() { return serialPort.IsOpen; } /// <summary> /// 数据发送 /// </summary> /// <param name="data">要发送的数据字节</param> public void SendData(byte[] data) { try { serialPort.DiscardInBuffer(); serialPort.Write(data, 0, data.Length); } catch (Exception ex) { throw ex; } } /// <summary> /// 发送命令 /// </summary> /// <param name="SendData">发送数据</param> /// <param name="ReceiveData">接收数据</param> /// <param name="Overtime">超时时间</param> /// <returns></returns> public int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime) { if (serialPort.IsOpen) { try { ReceiveEventFlag = true; //关闭接收事件 serialPort.DiscardInBuffer(); //清空接收缓冲区 serialPort.Write(SendData, 0, SendData.Length); System.Threading.Thread.Sleep(50); int num = 0, ret = 0; while (num++ < Overtime) { if (serialPort.BytesToRead >= ReceiveData.Length) { break; } System.Threading.Thread.Sleep(50); } 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; } ///<summary> ///数据发送 ///</summary> ///<param name="data">要发送的数据字符串</param> public void SendData(string data) { //禁止接收事件时直接退出 if (ReceiveEventFlag) { return; } if (serialPort.IsOpen) { serialPort.Write(data); } } ///<summary> ///将指定数量的字节写入输出缓冲区中的指定偏移量处。 ///</summary> ///<param name="data">发送的字节数据</param> ///<param name="offset">写入偏移量</param> ///<param name="count">写入的字节数</param> public void SendData(byte[] data, int offset, int count) { //禁止接收事件时直接退出 if (ReceiveEventFlag) { return; } if (serialPort.IsOpen) { serialPort.Write(data, offset, count); } } /// <summary> /// 数据接收 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void DataReceived(object sender, SerialDataReceivedEventArgs e) { //禁止接收事件时直接退出 if (ReceiveEventFlag) { return; } try { byte[] data = new byte[serialPort.BytesToRead]; serialPort.Read(data, 0, data.Length); if (Received != null) { Received(sender, new PortDataReciveEventArgs(data)); } } catch (Exception ex) { //throw ex; } } } }
串口通讯数据类:PortDataReciveEventArgs
重写PortDataReciveEventArgs参数类
using System; using System.Collections.Generic; using System.Text; namespace LY.FuelStationPOS.Protocol { public delegate void PortDataReceivedEventHandle(object sender, PortDataReciveEventArgs e); public class PortDataReciveEventArgs : EventArgs { private byte[] data; public byte[] Data { get { return data; } set { data = value; } } public PortDataReciveEventArgs() { this.data = null; } public PortDataReciveEventArgs(byte[] data) { this.data = data; } } }
//进制转换(串口通讯中比较常用的16进制、byte、压缩BCD码、long、ASCII、Float等之间的转换方法)
//进制转换:ConvertHelper.csusing System; using System.Collections.Generic; using System.Text; using System.IO; namespace LY { /// <summary> /// 进制转换 /// </summary> public static class ConvertHelper { #region 进制转换 /// <summary> /// 整形转化成字节 /// </summary> /// <param name="i"></param> /// <returns></returns> public static byte IntToByte(int i) { return Convert.ToByte(i % 0x100); } /// <summary> /// 16进制转化成BCD /// </summary> /// <param name="b">byte</param> /// <returns>返回BCD码</returns> public static byte HexToBCD(byte b) { int r1 = b % 0x10; // b = 0x12 -> r1 = 0x02 int r2 = b / 0x10; // b = 0x12 -> r2 = 0x01 if (r1 > 9) //r1 = 0x0A -> r1 = 0x00 r1 = 0; if (r2 > 9) //r2 = 0x0A -> r2 = 0x00 r2 = 0; return Convert.ToByte(r1 + 10 * r2); //0x12 -> 12 } /// <summary> /// 16进制转化成BCD /// </summary> /// <param name="i">int</param> /// <returns>返回BCD码</returns> public static byte HexToBCD(int i) { return HexToBCD(IntToByte(i)); } /// <summary> /// Double转换为压缩BCD /// </summary> /// <param name="d">0-100内的双精度浮点数字</param> /// <returns>返回压缩BCD码</returns> public static string DoubleToBCD(double d) { string[] strs = d.ToString("F2").Split('.'); string temp1 = int.Parse(strs[0]).ToString("D2"); string temp2 = int.Parse(strs[1]).ToString("D2"); return string.Format("{0} {1}", temp1, temp2); } /// <summary> /// long转换为BCD /// </summary> /// <param name="val"></param> /// <returns></returns> public static long ToBCD(long val) { long res = 0; int bit = 0; while (val >= 10) { res |= (val % 10 << bit); val /= 10; bit += 4; } res |= val << bit; return res; } /// <summary> /// BCD转换为long /// </summary> /// <param name="vals"></param> /// <returns></returns> public static long FromBCD(long vals) { long c = 1; long b = 0; while (vals > 0) { b += ((vals & 0xf) * c); c *= 10; vals >>= 4; } return b; } /// <summary> /// BCD转化成16进制 /// </summary> /// <param name="b"></param> /// <returns></returns> public static byte BCDToHex(byte b) { int r2 = b % 100; // b = 12 -> r2 = 12 //123 -> r2 = 23 int r1 = r2 % 10; //r2 = 12 -> r1 = 2 r2 = r2 / 10; //r2 = 12 -> r2 =1 return Convert.ToByte(r1 + 0x10 * r2); } /// <summary> /// BCD转化成16进制 /// </summary> /// <param name="i"></param> /// <returns></returns> public static byte BCDToHex(int i) { return BCDToHex(IntToByte(i)); } /// <summary> /// btye转化成16进制字符 /// </summary> /// <param name="b">byte</param> /// <returns></returns> public static string ToHexString(byte b) { return Convert.ToString(b, 16); } /// <summary> /// int转化成16进制字符 /// </summary> /// <param name="num">int</param> /// <returns></returns> public static string ToHexString(int num) { return Convert.ToString(num, 16); } /// <summary> /// 16进制字符串转换成字节数组 /// </summary> /// <param name="s"></param> /// <returns></returns> public static byte[] HexStringToByteArray(string s) { s = s.Replace(" ", ""); byte[] buffer = new byte[s.Length / 2]; for (int i = 0; i < s.Length; i += 2) { buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16); } return buffer; } /// <summary> /// 字节数组转换成16进制字符串 /// </summary> /// <param name="data"></param> /// <returns></returns> public static string ByteArrayToHexString(byte[] data) { StringBuilder sb = new StringBuilder(data.Length * 3); foreach (byte b in data) { sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' ')); } return sb.ToString().Trim().ToUpper(); } /// <summary> /// ASCII转16进制 /// </summary> /// <param name="ascii">ASCII</param> /// <returns></returns> public static string ASCIIToHex(string ascii) { char[] cs = ascii.ToCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < cs.Length; i++) { string hex = ((int)cs[i]).ToString("X"); sb.AppendFormat("{0} ", hex); } return sb.ToString().TrimEnd(' '); } /// <summary> /// HEX to ASCII /// </summary> /// <param name="hex"></param> /// <returns></returns> public static string HexToASCII(string hex) { if (hex.Length % 2 == 0) { int iValue; byte[] bs; string sValue = string.Empty; string result = string.Empty; int length = hex.Length / 2; for (int i = 0; i < length; i++) { iValue = Convert.ToInt32(hex.Substring(i * 2, 2), 16); // 16进制->10进制 bs = System.BitConverter.GetBytes(iValue); //int->byte[] sValue = System.Text.Encoding.ASCII.GetString(bs, 0, 1); //byte[]-> ASCII result += char.Parse(sValue).ToString(); } return result.PadLeft(length, '0'); } return string.Empty; } /// <summary> /// ASCII To Float /// </summary> /// <param name="ascii"></param> /// <returns></returns> public static float ASCIIToFloat(string ascii) { if (ascii.Length == 8) { byte[] arr = new byte[4]; for (int i = 0; i < 4; i++) { arr[i] = Convert.ToByte(ascii.Substring((3 - i) * 2, 2), 16); } float f = BitConverter.ToSingle(arr, 0); return f; } return 0f; } /// <summary> /// Hex to Float /// </summary> /// <param name="hex"></param> /// <returns></returns> public static float HexToFloat(string hex) { string ascii = HexToASCII(hex); float f = ASCIIToFloat(ascii); return f; } #endregion } }
C# 串口通信
最新推荐文章于 2023-12-25 17:03:37 发布