SerialPort

这是一个关于C#中SerialPort类的实现,用于串口通信。类包括设置串口参数、打开关闭串口、接收发送数据的函数,以及处理数据接收事件。示例展示了如何处理串口数据接收,包括数据校验和错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;


namespace Utility
{
    public class SerialPortUtil
    {
        public static SerialPort _serialPort = null;
        //定义委托
        public delegate void SerialPortDataReceiveEventArgs(object sender, SerialDataReceivedEventArgs e, byte[] bits);


        //定义接收数据事件
        public event SerialPortDataReceiveEventArgs DataReceived;


        //定义委托
        public delegate void SerialPortDataReceiveEventArgss(object sender, SerialDataReceivedEventArgs e, List<byte> buff);


        //定义接收数据事件
        public event SerialPortDataReceiveEventArgss DataReceiveds;


        //定义接收错误事件
        //public event SerialErrorReceivedEventHandler Error;


        //接收事件是否有效 false表示有效
        public bool ReceiveEventFlag = false;


        public static byte[] _data = new byte[12];




        private List<byte> receivedBuffer = new List<byte>();
        public List<byte> trmpListBuffer = new List<byte>();


        /// <summary>
        /// 接收缓冲区
        /// </summary>
        public List<byte> ReceivedBuffer
        {
            get { return receivedBuffer; }
            set { receivedBuffer = value; }
        }


        public struct UpgradeFile
        {
            public int intAddress;
            public List<byte> UpgradeData;
        }


        


        #region 获取串口名


        private string protName;


        public string PortName
        {
            get { return _serialPort.PortName; }
            set
            {
                _serialPort.PortName = value;
                protName = value;
            }
        }
        #endregion


        #region 获取比特率


        private int baudRate;


        public int BaudRate
        {
            get { return _serialPort.BaudRate; }
            set
            {
                _serialPort.BaudRate = value;
                baudRate = value;
            }
        }


        #endregion


        #region 默认构造函数


        /// <summary>
        /// 默认构造函数,操作COM1,速度为9600,没有奇偶校验,8位字节,停止位为1 "COM1", 9600, Parity.None, 8, StopBits.One
        /// </summary>


        public SerialPortUtil()
        {
            //_serialPort = new SerialPort();
        }


         #endregion


        #region 构造函数
        /// <summary>
        /// 构造函数,
        /// </summary>
        /// <param name="comPortName"></param>
        public SerialPortUtil(string comPortName)
        {
            _serialPort = new SerialPort();
            _serialPort.PortName = comPortName;
            _serialPort.BaudRate = 115200;
            _serialPort.DataBits = 8; //每个字节的标准数据位长度
            _serialPort.StopBits = StopBits.One; //设置每个字节的标准停止位数
            _serialPort.Parity = Parity.None; //设置奇偶校验检查协议
            _serialPort.ReadTimeout = 3000; //单位毫秒
            _serialPort.WriteTimeout = 3000; //单位毫秒
            _serialPort.RtsEnable = true;
            _serialPort.Open();
            //_serialPort.ReceivedBytesThreshold = 1;
            _serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
        }
        #endregion


        #region 构造函数,可以自定义串口的初始化参数
        /// <summary>
        /// 构造函数,可以自定义串口的初始化参数
        /// </summary>
        /// <param name="comPortName">需要操作的COM口名称</param>
        /// <param name="baudRate">COM的速度</param>
        /// <param name="parity">奇偶校验位</param>
        /// <param name="dataBits">数据长度</param>
        /// <param name="stopBits">停止位</param>
        public SerialPortUtil(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();
        }


        #endregion


        #region 析构函数
        /// <summary>
        /// 析构函数,关闭串口
        /// </summary>
        ~SerialPortUtil()
        {
            try
            {
                if (_serialPort.IsOpen)
                    _serialPort.Close();
            }
            catch (Exception ex)
            {


            }
        }


        #endregion


        #region 设置串口参数


        /// <summary>
        /// 设置串口参数
        /// </summary>
        /// <param name="comPortName">需要操作的COM口名称</param>
        /// <param name="baudRate">COM的速度</param>
        /// <param name="dataBits">数据长度</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();
        }


        #endregion


        #region 设置接收函数
        /// <summary>
        /// 设置串口资源,还需重载多个设置串口的函数
        /// </summary>
        void setSerialPort()
        {
            if (_serialPort != null)
            {
                //设置触发DataReceived事件的字节数为1
                _serialPort.ReceivedBytesThreshold = 1;
                //接收到一个字节时,也会触发DataReceived事件
                _serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
                //接收数据出错,触发事件
                _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);
                //打开串口
                openPort();
            }
        }


        #endregion


        #region 打开串口资源


        /// <summary>
        /// 打开串口资源
        /// <returns>返回bool类型</returns>
        /// </summary>
        public bool openPort()
        {
            bool ok = false;
            //如果串口是打开的,先关闭
            if (_serialPort.IsOpen)
                _serialPort.Close();
            try
            {
                //打开串口
                _serialPort.Open();
                ok = true;
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            return ok;
        }


        #endregion


        #region 关闭串口


        /// <summary>
        /// 关闭串口资源,操作完成后,一定要关闭串口
        /// </summary>
        public void closePort()
        {
            //如果串口处于打开状态,则关闭
            if (_serialPort.IsOpen)
                _serialPort.Close();
        }


        #endregion


        #region 接收串口数据事件


        byte[] readBuffersss;




        /// <summary>
        /// 接收串口数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            #region 注销
            //Thread.Sleep(200);
            //string str = "";
            //do
            //{
            //    int count = _serialPort.BytesToRead;
            //    if (count <= 0)
            //    {
            //        break;
            //    }
            //    byte[] readBuffer = new byte[count];
            //    System.Windows.Forms.Application.DoEvents();
            //    _serialPort.Read(readBuffer, 0, count);




            //    if (readBuffer.Length == 0) { return; }
            //    if (DataReceived != null)
            //    {
            //        DataReceived(sender, e, readBuffer);
            //    }
            //}
            //while (_serialPort.BytesToRead > 0);




            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


            #endregion


            //Thread.Sleep(1);
            int n = _serialPort.BytesToRead;
            byte[] buf = new byte[n];
            _serialPort.Read(buf, 0, n);
            ReceivedBuffer.AddRange(buf);
            while (ReceivedBuffer.Count > 7)
            {
                //获取长度
                byte[] b = new byte[2];
                b[1] = ReceivedBuffer[2];
                b[0] = ReceivedBuffer[3];
                int data = SerialPortUtil.BytesToInt(b, 0);


                byte[] tempByte = ReceivedBuffer.GetRange(0, data + 4).ToArray();
                byte tempB = tempByte[tempByte.Length-1];
                //todo:这里做事件绑定
                if (tempByte.Length == 0) { return; }
                if (DataReceived != null)
                {
                    if (tempB != GetCheckbit(tempByte, tempByte.Length - 1))
                    {
                        string toHex = SerialPortUtil.ToHexString(tempByte);
                        Console.WriteLine(toHex);
                        //ReceivedBuffer.RemoveRange(0, data + 4);
                        while (true)
                        {


                            byte bb = 0xA1;
                            ReceivedBuffer.RemoveRange(0, 1);
                            if (ReceivedBuffer[0] == bb || ReceivedBuffer.Count == 0)
                            {
                                break;
                            }


                        }
                    }
                    else
                    {
                        DataReceived(sender, e, tempByte);
                        ReceivedBuffer.RemoveRange(0, data + 4);
                    }


                }
            }
        }


        public static List<byte> tempListBuff = new List<byte>();


        #endregion


        #region 接收数据出错事件


        /// <summary>
        /// 接收数据出错事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {


        }


        #endregion


        #region 发送数据string类型


        public void SendData(string data)
        {
            //发送数据
            //禁止接收事件时直接退出
            if (ReceiveEventFlag)
            {
                return;
            }
            if (_serialPort.IsOpen)
            {
                _serialPort.Write(data);
            }
        }


        #endregion


        #region 发送数据byte类型


        /// <summary>
        /// 数据发送
        /// </summary>
        /// <param name="data">要发送的数据字节</param>
        public void SendData(byte[] data, int offset, int count)
        {
            //禁止接收事件时直接退出
            if (ReceiveEventFlag)
            {
                return;
            }
            try
            {
                if (_serialPort.IsOpen)
                {
                    //_serialPort.DiscardInBuffer();//清空接收缓冲区
                    _serialPort.Write(data, offset, count);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #endregion


        #region 发送命令


        /// <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);
                    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;
        }


        #endregion


        #region 获取串口


        /// <summary>
        /// 获取所有已连接短信猫设备的串口
        /// </summary>
        /// <returns></returns>
        public string[] serialsIsConnected()
        {
            List<string> lists = new List<string>();
            string[] seriallist = getSerials();
            foreach (string s in seriallist)
            {


            }
            return lists.ToArray();
        }


        #endregion


        #region 获取当前全部串口资源


        /// <summary>
        /// 获得当前电脑上的所有串口资源
        /// </summary>
        /// <returns></returns>
        public string[] getSerials()
        {
            return SerialPort.GetPortNames();
        }


        #endregion


        #region 字节型转换16


        /// <summary>
        /// 把字节型转换成十六进制字符串
        /// </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;
        }


        #endregion


        #region 十六进制字符串转字节型


        /// <summary>
        /// 把十六进制字符串转换成字节型(方法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;
        }


        #endregion


        #region 十六进制字符串转字节型


        /// <summary>
        /// 字符串转16进制字节数组(方法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;
        }


        #endregion


        #region 字节型转十六进制字符串


        /// <summary>
        /// 字节数组转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;


        }
        #endregion


        #region 求校验位


        /// <summary>
        /// 求校验位
        /// </summary>
        public static byte GetCheckbit(byte[] cmd, int len)
        {
            //计算校验位
            byte Chk = 0;
            int i = 0;
            if (len > cmd.Length)
            {
                len = cmd.Length;
            }
            for (i = 0; i < len; i++)
            {
                Chk ^= cmd[i];
            }
            return Chk;
        }
        #endregion


        #region 字节转十六进制,输出string
        /// <summary>
        /// 字节转十六进制,字符串形式输出
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ToHexString(byte[] bytes)
        {
            string hexString = string.Empty;
            string s = BitConverter.ToString(bytes);
            Console.WriteLine(s);
            return s;
        }
        #endregion


        public static int GetbyteToInt(byte a, byte b)
        {
            int temp = 0;
            temp = (a & 0xFF) << 8 | b;
            return temp;
        }


        /// <summary>
        /// Byte转Int (低位在前,高位在后)
        /// </summary>
        /// <param name="src">byte数组</param>
        /// <param name="offset">从数组的第几位开始</param>
        /// <returns></returns>
        public static int BytesToInt(byte[] src, int offset)
        {
            int value = 0;
            if (src.Length == 2)
            {
                value = (int)((src[offset] & 0xFF)
                | ((src[offset + 1] & 0xFF) << 8));


            }
            if (src.Length == 4)
            {
                value = (int)((src[offset] & 0xFF)
                    | ((src[offset + 1] & 0xFF) << 8)
                    | ((src[offset + 2] & 0xFF) << 16)
                    | ((src[offset + 3] & 0xFF) << 24));


            }
            return value;
        }


        /// <summary>
        /// 字符串转ASCII
        /// </summary>
        /// <param name="character"></param>
        /// <returns></returns>
        public static int StringToAsc(string character)
        {
            if (character.Length == 1)
            {
                System.Text.ASCIIEncoding asciiEncoding = new ASCIIEncoding();
                int intAsciiCode = (int)asciiEncoding.GetBytes(character)[0];
                return intAsciiCode;
            }
            else
            {
                throw new Exception("Character is not valid");
            }
        }


        /// <summary>
        /// ASCII转字符串
        /// </summary>
        /// <param name="asciiCode"></param>
        /// <returns></returns>
        public static string Chr(int asciiCode)
        {
            if (asciiCode >= 0 && asciiCode <= 255)
            {




                System.Text.ASCIIEncoding asciiEncoding = new ASCIIEncoding();
                byte[] byteArray = new byte[] { (byte)asciiCode };
                string strCharacter = asciiEncoding.GetString(byteArray);
                return strCharacter;
            }
            else
            {
                throw new Exception("ASCII Code is not valid");
            }
        }


        public static List<byte> GetByteList(string str)
        {
            int totalCount = 0;
            List<byte> btFileData = new List<byte>();


            UpgradeFile uf = new UpgradeFile();
            List<UpgradeFile> luf = new List<UpgradeFile>();
            int address = 0;


            byte subLbt = 0;
            List<byte> lbt = new List<byte>();
            //str = ds.Tables[0].Rows[i]["plan_code"].ToString();
            string s = str;
            int len = (s.Length + 1) / 3;
            byte[] byteArr2 = new byte[len];
            for (int k = 0; k < len; k++)
            {
                byteArr2[k] = Convert.ToByte(s.Substring(k * 3, 2), 16);
            }
            for (int a = 0; a < byteArr2.Count(); a++)
            {
                subLbt = byteArr2[a];
                lbt.Add(subLbt);
            }
            totalCount = totalCount + lbt.Count;
            uf.intAddress = address;
            address = address + lbt.Count;
            uf.UpgradeData = lbt;
            luf.Add(uf);


            IEnumerable<UpgradeFile> ufList = from u in luf orderby u.intAddress select u;


            //List<byte> btFileData = new List<byte>();
            btFileData.AddRange(new byte[98304]);
            foreach (UpgradeFile u in ufList)
            {
                btFileData.RemoveRange(u.intAddress, u.UpgradeData.Count);
                btFileData.InsertRange(u.intAddress, u.UpgradeData);
            }
            int rmStar = ufList.LastOrDefault().intAddress + ufList.LastOrDefault().UpgradeData.Count;
            int rmBack = (btFileData.Count - rmStar) / 2048;


            btFileData.RemoveRange(rmStar, rmBack * 2048);


            return btFileData;
        }




        public bool Send(List<byte> data, int length)
        {
            try
            {
                bool b;
                //SerialClass s = new SerialClass();
                b = SendCom(data.GetRange(0 * 2048, 2048).ToArray(), length);
                return b;
            }
            catch (Exception ex)
            {
                
            }
            return false;
        }


        /// <summary>
        /// 发送协议
        /// </summary>
        /// <param name="totalCount"></param>
        /// <param name="index"></param>
        /// <param name="area"></param>
        /// <param name="data"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        public bool SendCom(byte[] data, int Length)
        {
            byte[] ReceiveData = new byte[255];
            try
            {
                if (2048 == data.Length)
                {
                    try
                    {
                        byte[] cmd = new byte[Length];
                        for (int i = 0; i <= Length - 1; i++)
                        {
                            cmd[i] = data[i];
                        }
                        SendCommand(cmd, ref ReceiveData, 1000);
                        return true;
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public bool bo = false;




        /// <summary>
        /// 校验有效长度
        /// </summary>
        /// <returns></returns>
        public bool CheckLength_Finite(byte[] data)
        {
            int byteLength = 0;
            int count = data.Length / 32;


            int a = 0; int b = 32;
            byte[] newA = data.Skip(a).Take(b).ToArray();


            for (int j = 0; j < count; j++)
            {
                int sum = 0;
                for (int z = 0; z < newA.Length; z++)
                {
                    sum += newA[z];
                }


                if (sum > 0)
                {
                    byteLength += 32;
                }
                else
                {
                    continue;
                }
            }
            //如果大于16k 1024*16=16384
            if (byteLength >= 1024*16)
            {
                return false;
            }
            return true;
        }




    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值