串口通讯类: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.cs
using 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
}
}