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

串口知识回顾:

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设计和任务编写

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容