通用串口类

 public class SerialClass
    {
        SerialPort _serialPort = null;

        //定义委托

        public delegate void SerialPortDataReceiveEventArgs(object sender, SerialDataReceivedEventArgs e, byte[] bits);

        //定义接收数据事件

        public event SerialPortDataReceiveEventArgs DataReceived;

        //定义接收错误事件

        //public event SerialErrorReceivedEventHandler Error;

        //接收事件是否有效 false表示有效

        public bool ReceiveEventFlag = false;

        #region 获取串口名

        private string protName="COM4";

        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,速度为19200,没有奇偶校验,8位字节,停止位为1 "COM1", 9600, Parity.None, 8, StopBits.One

        /// </summary>

        public SerialClass()
        {

            _serialPort = new SerialPort(protName);

            _serialPort.BaudRate = 19200;

            _serialPort.Parity = Parity.None;

            _serialPort.DataBits = 8;

            _serialPort.StopBits = StopBits.One;

            _serialPort.Handshake = Handshake.None;

            _serialPort.RtsEnable = true;

            _serialPort.ReadTimeout = 2000;

            setSerialPort();

        }

        #endregion

        #region 构造函数

        /// <summary>

        /// 构造函数,

        /// </summary>

        /// <param name="comPortName"></param>

        public SerialClass(string comPortName)
        {

            _serialPort = new SerialPort(comPortName);

            _serialPort.BaudRate = 19200;

            _serialPort.Parity = Parity.None;

            _serialPort.DataBits = 8;

            _serialPort.StopBits = StopBits.One;

            _serialPort.Handshake = Handshake.None;

            _serialPort.RtsEnable = true;

            _serialPort.ReadTimeout = 2000;

            setSerialPort();

        }

        #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 SerialClass(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>

        ~SerialClass()
        {

            if (_serialPort.IsOpen)

                _serialPort.Close();

        }

        #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 接收串口数据事件

        /// <summary>

        /// 接收串口数据事件

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            //禁止接收事件时直接退出

            if (ReceiveEventFlag)
            {

                return;

            }

            try
            {

                System.Threading.Thread.Sleep(2);

                byte[] _data = new byte[_serialPort.BytesToRead];

                _serialPort.Read(_data, 0, _data.Length);

                if (_data.Length == 0) { return; }

                if (DataReceived != null)
                {

                    DataReceived(sender, e, _data);

                }

                _serialPort.DiscardInBuffer();  //清空接收缓冲区  

            }

            catch (Exception ex)
            {

                //throw ex;

            }

        }

        #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
    }
    #endregion
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSerialPort First Version by Remon Spekreijse on 2000-02-08 http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2483/A-communication-class-for-serial-port.htm Second Version by mrlong on 2007-12-25 https://code.google.com/p/mycom/ 增加 ClosePort 增加 WriteToPort 两个方法 增加 SendData 与 RecvData 方法 by liquanhai on 2011-11-04 http://blog.csdn.net/liquanhai/article/details/4955253 增加 ClosePort 中交出控制权,防止死锁问题 by liquanhai on 2011-11-06 http://blog.csdn.net/liquanhai/article/details/6941574 增加 ReceiveChar 中防止线程死锁 by viruscamp on 2013-12-04 https://github.com/viruscamp/CSerialPort 增加 IsOpen 判断是否打开 修正 InitPort 中 parity Odd Even 参数取值错误 修改 InitPort 中 portnr 取值范围,portnr>9 时特殊处理 取消对 MFC 的依赖,使用 HWND 替代 CWnd,使用 win32 thread 函数而不是 MFC 的 增加用户消息编号自定义,方法来自 CnComm by itas109 on 2014-01-10 http://blog.csdn.net/itas109/article/details/18358297 解决COM10以上端口无法显示的问题 扩展可选择端口,最大值MaxSerialPortNum可以自定义 添加QueryKey()和Hkey2ComboBox两个方法,用于自动查询当前有效的串口号。 by liquanhai on 2014-12-18 增加一些处理措施,主要是对减少CPU占用率 by itas109 on 2016-05-07 http://blog.csdn.net/itas109 修复每次打开串口发送一次,当串口无应答时,需要关闭再打开或者接收完数据才能发送的问题。 解决办法:在m_hEventArray中调整m_hWriteEvent的优先级高于读的优先级。CommThread(LPVOID pParam)函数中读写的位置也调换。 参考:http://zhidao.baidu.com/link?url=RSrbPcfTZRULFFd2ziHZPBwnoXv1iCSu_Nmycb_yEw1mklT8gkoNZAkWpl3UDhk8L35DtRPo5VV5kEGpOx-Gea 修复停止位在头文件中定义成1导致SetCommState报错的问题,应为1对应的停止位是1.5。UINT stopsbits = ONESTOPBIT switch(stopbits)和switch(parity)增加默认情况,增强程序健壮性 by itas109 on 2016-06-22 http://blog.csdn.net/itas109 增加ReceiveStr方法,用于接收字符串(接收缓冲区有多少字符就接收多少字符)。 解决ReceiveChar只能接收单个字符的问题。 by itas109 on 2016-06-29 http://blog.csdn.net/itas109 解决RestartMonitoring方法和StopMonitoring方法命令不准确引起的歧义,根据实际作用。 将RestartMonitoring更改为ResumeMonitoring,将StopMonitoring更改为SuspendMonitoring。 增加IsThreadSuspend方法,用于判断线程是否挂起。 改进ClosePort方法,增加线程挂起判断,解决由于线程挂起导致串口关闭死锁的问题。 增加IsReceiveString宏定义,用于接收时采用单字节接收还是多字节接收 by itas109 on 2016-08-02 http://blog.csdn.net/itas109 https://github.com/itas109 改进IsOpen方法,m_hComm增加INVALID_HANDLE_VALUE的情况,因为CreateFile方法失败返回的是INVALID_HANDLE_VALUE,不是NULL 改进ClosePort方法:增加串口句柄无效的判断(防止关闭死锁);m_hWriteEvent不使用CloseHandle关闭 改进CommThread、ReceiveChar、ReceiveStr和WriteChar方法中异常处理的判断,增加三种判断:串口打开失败(error code:ERROR_INVALID_HANDLE)、连接过程中非法断开(error code:ERROR_BAD_COMMAND)和拒绝访问(error code:ERROR_ACCESS_DENIED) 采用安全函数sprintf_s和strcpy_s函数替换掉sprintf和strcpy 改进QueryKey方法,用于查询注册表的可用串口值,可以搜索到任意的可用串口 改进InitPort方法,串口打开失败,增加提示信息:串口不存在(error code:ERROR_FILE_NOT_FOUND)和串口拒绝访问(error code:ERROR_ACCESS_DENIED) 加入viruscamp 取消对 MFC 的依赖 改进InitPort方法,如果上次串口是打开,再次调用InitPort方法,关闭串口需要做一定的延时,否则有几率导致ERROR_ACCESS_DENIED拒绝访问,也就是串口占用问题 初始化默认波特率修改为9600 修复一些释放的BUG 规范了一些错误信息,参考winerror.h -- error code definitions for the Win32 API functions 删除SendData和RecvData方法 by itas109 on 2016-08-10 http://blog.csdn.net/itas109 https://github.com/itas109 改进ReceiveStr方法,comstat.cbInQue = 0xcccccccc的情况(如串口异常断开),会导致RXBuff初始化失败 by itas109 on 2017-02-14 http://blog.csdn.net/itas109 https://github.com/itas109 兼容ASCII和UNICODE编码 ReceiveStr函数中发送函数SendMessage的第二个参数采用结构体形式,包括portNr串口号和bytesRead读取的字节数,可以处理16进制的时候0x00截断问题 精简不必要的函数SendData和RecvData 尽量的取消对 MFC 的依赖,Hkey2ComboBox函数暂时保留 其他小问题修改 博客:blog.csdn.net/itas109 Email:[email protected]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值