美文网首页
基于OOP方法编写串口助手类

基于OOP方法编写串口助手类

作者: 漠漠彡 | 来源:发表于2019-09-16 11:21 被阅读0次

    串口知识回顾:

    1常见的串口

    (1)RS-232接口:通常适合于数据传输频率在0~20000bps范围的通信。在PC机上通常都是COM串口。

    不足:抗干扰能力差,通信距离短,速率低。

    (2)RS-422/485接口:传输速度和通信距离变得非常远(1200m),并且在一条平衡总线上连接最多10个接收器。

    2串行通信的基本参数

    (1)波特率:是指串行通信中每1秒所传送的数据位数,单位是bps。也就是传输速度。

    比如发送一个字符需要8位,如果波特率是4800bps传输,则每秒可以传输600个字符。

    (2)起始位:起始位表示字符传输的开始。在通信线上,没有数据传输时处于逻辑“1”状态。当发送一个字符数据时,首先发出一个“0”信号,这个逻辑低电平就是起始位。接收设备检测到低电平后,就准备开始接收。

    (3)数据位:当接收设备收到起始位后,紧挨着的就是数据位,数据位的个数可以是5、6、7、8位。在字符串数据传送的过程中,数据位从最低有效位开始传输。

    (4)奇偶校验位:数据位发送完以后,就可以发送奇偶校验位,用于有限差错的检查。通信双方需要约定一致的奇偶校验方式。

    (5)停止位:在奇偶校验位或者数据位(无奇偶校验位时)之后是停止位,它可以是1位,1.5位或者2位,停止位是数据结束的标志。

    3异步传输中的一帧数据组成

    【发送端】->停止位(1-2)->奇偶校验位(1位)->数据位(7-8个)->起始位(0)【接收端】

    串口助手类的设计

    准备工作:准备一个进制转换类助手,能够完成十进制、16进制、汉字、英文、byte[]之间的转换。

    新建一个HelpClass文件夹,并新建一个进制转换类:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Windows;

    namespace SerialPortHelperDemo

    {

        /// <summary>

        /// 16进制使用的隔离符枚举

        /// </summary>

        public enum Enum16Hex

        {

            None,//无

            Blank,//空格

            OX,  //OX

            Ox   //Ox

        }

        /// <summary>

        ///计算进制类助手

        /// </summary>

        public class AlgorithmHelper

        {

            #region十进制转十六进制

            public string From10To16(int d)

            {

                string hex = "";

                if (d < 16)

                {

                    hex = BeginChange(d);

                }

                else

                {

                    int c;

                    int s = 0;

                    int n = d;

                    int temp = d;

                    while (n >= 16)

                    {

                        s++;

                        n = n / 16;

                    }

                    string[] m = new string[s];

                    int i = 0;

                    do

                    {

                        c = d / 16;

                        m[i++] = BeginChange(d % 16);//判断是否大于10,如果大于10,则转换为A~F的格式

                        d = c;

                    } while (c >= 16);

                    hex = BeginChange(d);

                    for (int j = m.Length - 1; j >= 0; j--)

                    {

                        hex += m[j];

                    }

                }

                return hex;

            }

            //判断是否为10~15之间的数,如果是则进行转换

            public string BeginChange(int d)

            {

                string hex = "";

                switch (d)

                {

                    case 10:

                        hex = "A";

                        break;

                    case 11:

                        hex = "B";

                        break;

                    case 12:

                        hex = "C";

                        break;

                    case 13:

                        hex = "D";

                        break;

                    case 14:

                        hex = "E";

                        break;

                    case 15:

                        hex = "F";

                        break;

                    default:

                        hex = d.ToString();

                        break;

                }

                return hex;

            }

            #endregion

            #region其他函数【16进制中的隔离符处理】

            /// <summary>

            ///把16进制隔离符转换成实际的字符串

            /// </summary>

            /// <param name="enum16">16进制隔离符枚举</param>

            /// <returns></returns>

            private string AddSplitString(Enum16Hex enum16)

            {

                switch (enum16)

                {

                    case Enum16Hex.None:

                        return "";

                    case Enum16Hex.Ox:

                        return "0x";

                    case Enum16Hex.OX:

                        return "0X";

                    case Enum16Hex.Blank:

                        return " ";

                    default:

                        return "";

                }

            }

            /// <summary>

            ///去掉16进制字符串中的隔离符【 如:" ", "0x", "0X"】

            /// </summary>

            /// <param name="inString">需要转换的字符串数据</param>

            /// <returns></returns>

            private string DeleteSplitString(string inString)

            {

                string outString = string.Empty;

                string[] delArray = { " ", "0x", "0X" };

                if (inString.Contains(" ") || inString.Contains("0x") || inString.Contains("0X"))//存在隔离符

                {

                    string[] str = inString.Split(delArray,

                        System.StringSplitOptions.RemoveEmptyEntries);//以隔离符进行转换数组,去掉隔离符,去掉空格。

                    for (int i = 0; i < str.Length; i++)

                    {

                        outString += str[i].ToString();

                    }

                    return outString;

                }

                else//不存在隔离符就直接返回

                {

                    return inString;

                }

            }

            #endregion

            #region汉字、英文、纯16进制数、byte[]之间的各种转换方法

            /// <summary>

            ///字符串转换成16进制

            /// </summary>

            /// <param name="inSting"></param>

            /// <param name="enum16"></param>

            /// <returns></returns>

            public string StringTo16(string inSting, Enum16Hex enum16)

            {

                string outString = "";

                byte[] bytes = Encoding.Default.GetBytes(inSting);

                for (int i = 0; i < bytes.Length; i++)

                {

                    int strInt = Convert.ToInt16(bytes[i] - '\0');

                    string s = strInt.ToString("X");

                    if (s.Length == 1)

                    {

                        s = "0" + s;

                    }

                    s = s + AddSplitString(enum16);

                    outString += s;

                }

                return outString;

            }

            /// <summary>

            ///字符串转换成byte[]

            /// </summary>

            /// <param name="inSting"></param>

            /// <returns></returns>

            public byte[] StringToBtyes(string inSting)

            {

                inSting = StringTo16(inSting, Enum16Hex.None);//把字符串转换成16进制数

                return From16ToBtyes(inSting);//把16进制数转换成byte[]

            }

            /// <summary>

            ///把16进制字符串转换成byte[]

            /// </summary>

            /// <param name="inSting"></param>

            /// <returns></returns>

            public byte[] From16ToBtyes(string inSting)

            {

                inSting = DeleteSplitString(inSting);//去掉16进制中的隔离符

                byte[] stringByte = new byte[inSting.Length / 2];

                for (int a = 0, b = 0; a < inSting.Length; a = a + 2, b++)

                {

                    try

                    {

                        string str = inSting.Substring(a, 2);

                        stringByte[b] = (byte)Convert.ToInt16(str, 16);

                    }

                    catch (Exception ex)

                    {

                        throw new Exception("输入的数据不是纯16进制数!  参考错误信息:" + ex.Message);

                    }

                }

                return stringByte;

            }

            /// <summary>

            ///把16进制字符串转换成英文数字和汉字混合格式

            /// </summary>

            /// <param name="inSting">需要转换的16进制字符串</param>

            /// <returns></returns>

            public string From16ToString(string inSting)

            {

                inSting = DeleteSplitString(inSting);

                return Encoding.Default.GetString(From16ToBtyes(inSting));

            }

            /// <summary>

            ///把byte[]转换成String

            /// </summary>

            /// <param name="bytes">需要转换的byte[]</param>

            /// <param name="enum16">隔离符</param>

            /// <returns></returns>

            public string BytesToString(byte[] bytes, Enum16Hex enum16)

            {

                return From16ToString(BytesTo16(bytes, enum16));

            }

            /// <summary>

            /// byte[]转换成16进制字符串

            /// </summary>

            /// <param name="bytes">需要转换的byte[]</param>

            /// <param name="enum16"></param>

            /// <returns></returns>

            public string BytesTo16(byte[] bytes, Enum16Hex enum16)

            {

                string outString = "";

                for (int i = 0; i < bytes.Length; i++)

                {

                    if (bytes[i].ToString("X").Length < 2)//16进制数为一位时前面填充0

                    {

                        outString += "0" + bytes[i].ToString("X") + AddSplitString(enum16);//转成16进制数据

                    }

                    else

                    {

                        outString += bytes[i].ToString("X") + AddSplitString(enum16);//转成16进制数据

                    }

                }

                return outString;

            }

            /// <summary>

            ///把byte[]直接转换成字符串,直接以2进制形式显示出来。

            /// </summary>

            /// <param name="bytes"></param>

            /// <returns></returns>

            public string BytesTo2String(byte[] bytes, Enum16Hex enum16)

            {

                string outString = "";

                for (int i = 0; i < bytes.Length; i++)

                {

                    string tempString = Convert.ToString(bytes[i], 2);

                    if (tempString.Length != 8)

                    {

                        string add0 = "";

                        for (int j = 0; j < 8 - tempString.Length; j++)

                        {

                            add0 += "0";

                        }

                        outString += add0 + tempString + AddSplitString(enum16);

                    }

                    else

                    {

                        outString += tempString + AddSplitString(enum16);

                    }

                }

                return outString;

            }

            /// <summary>

            ///把字符串传进来,输出一个byte数组【可以把此byte数组直接发送到串口中】

            /// </summary>

            /// <param name="inString">要转换的字符串</param>

            /// <param name="is16">是否已经是16进制数据,true时已经是(已经转换好的数据),false时不是(需要内部转换)</param>

            /// <returns>输出一个byte数组</returns>

            public byte[] StringToBytes(string inString, bool is16)

            {

                if (is16)

                {

                    return From16ToBtyes(inString);

                }

                else

                {

                    return StringToBtyes(inString);

                }

            }

            #endregion

        }

    }

    1、新建一个串口类SerialPortHelper.cs

    namespace SerialPortHelper

    {

        /// <summary>

        ///串口助手通用类

        /// </summary>

        public class SerialPortHelper

        {

        }

    }

    2、引入串口所使用的命名空间

    using System.IO.Ports;

    3.设置相关的属性

    (1)属性:串口操作对象。

    /// <summary>

            ///创建一个串口操作对象

            /// </summary>

            private SerialPort serialPort = null;

            public SerialPort SerialPortObject

            {

                get { return serialPort; }//只读

            }

    (2)属性:获取计算机串口列表。

    /// <summary>

            ///获取当前计算机上可用的端口列表【只读】

            /// </summary>

            public string[] PortNames

            {

                get { return System.IO.Ports.SerialPort.GetPortNames(); }

            }

    (3)属性:进制转换对象。

            /// <summary>

            ///进制转换对象属性

            /// </summary>

            private AlgorithmHelper algorithmHelper = null;

            public AlgorithmHelper AlgorithmHelperObject

            {

                get { return algorithmHelper; }

            }

    (4)构造方法:完成属性初始化和串口参数默认值。

            /// <summary>

            ///构造方法中初始化相关数据

            /// </summary>

            public SerialPortHelper()

            {

                this.serialPort = new SerialPort();//创建串口实例

                this.algorithmHelper = new AlgorithmHelper();//创建进制转换对象

                //串口基本参数初始化

                this.serialPort.BaudRate = 9600;

                this.serialPort.Parity = System.IO.Ports.Parity.None;//校验位默认NONE

                this.serialPort.DataBits = 8;//数据位默认8位

                this.serialPort.StopBits = System.IO.Ports.StopBits.One;//停止位默认1位

            }

    4.设置相关的方法

    (1)打开或关闭串口(端口)。

           #region打开或关闭串口

            /// <summary>

            ///根据端口名称打开端口或关闭端口

            /// </summary>

            /// <param name="portName">端口名称</param>

            /// <param name="status">操作状态:1表示打开,0表示关闭</param>

            /// <returns>返回当前端口的打开状态true或false</returns>

            public bool OpenSerialPort(string portName, int status)

            {

                if (status == 1)

                {

                    this.serialPort.PortName = portName;//只有在端口没有打开的时候,才能设置名称。

                    this.serialPort.Open();

                }

                else

                {

                    this.serialPort.Close();

                }

                return this.serialPort.IsOpen;//返回串口打开的状态

            }

     #endregion

    (2)枚举限制格式

       #region发送格式选择枚举

        /// <summary>

        ///发送格式选择

        /// </summary>

        public enum SendFormat

        {

            Hex,//十六进制

            String

        }

        #endregion

    (3)编写发送数据的方法。

            #region发送数据

            /// <summary>

            ///判断十六进制字符串hex是否正确

            /// </summary>

            /// <param name="hex">十六进制字符串</param>

            /// <returns>true:正确,false:不正确<returns>

            private bool IsIIlegalHex(string hex)

            {

                return System.Text.RegularExpressions.Regex.IsMatch(hex, @"([^A-Fa-f0-9]|\s+?)+");

            }

            /// <summary>

            ///发送数据(可以是16进制,也可以是字符串)

            /// </summary>

            /// <param name="data">要发送的数据</param>

            /// <param name="format">发送的数据格式</param>

            public void SendData(string data, SendFormat format)

            {

                if (!this.serialPort.IsOpen)

                {

                    throw new Exception("端口未打开!请打开相关端口!");//让调用者处理

                }

                else

                {

                    byte[] byteData;

                    if (format == SendFormat.Hex)//如果是16进制

                    {

                        if (this.IsIIlegalHex(data))

                        {

                            byteData = algorithmHelper.From16ToBtyes(data);//将16进制转换成byte[]数组

                        }

                        else

                        {

                            throw new Exception("数据不是16进制格式!");

                        }

                    }

                    else  //发送字符串

                    {

                        byteData = algorithmHelper.StringToBytes(data, false);

                    }

                    this.serialPort.Write(byteData, 0, byteData.Length);//发送数据(数据,从0开始,结束位置)

                }

            }

            #endregion

    (4)编写接收数据的方法。

           #region接收数据

            /// <summary>

            ///串口接收数据

            /// </summary>

            /// <returns></returns>

            public byte[] ReceiveData()

            {

                //定义一个接收数组,获取接收缓冲区数据的字节数

                byte[] byteData = new byte[this.serialPort.BytesToRead];

                //读取数据(存储区,起始位置,终点位置)

                this.serialPort.Read(byteData, 0, serialPort.BytesToRead);

                return byteData;

            }

            #endregion

    5.串口助手UI设计和任务编写

    相关文章

      网友评论

          本文标题:基于OOP方法编写串口助手类

          本文链接:https://www.haomeiwen.com/subject/ofpwyctx.html