RS232串口专题

启动串口调试助手

项目运行截图

基础类封装

数据类型转换类

using System;
using System.Text;

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
    }
}

窗体后台代码

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using System.IO.Ports;


namespace SerialPortHelperDemo
{
    public partial class FrmHelper : Form
    {
        //创建串口操作助手对象
        private SerialPortHelper serialPortHelper = new SerialPortHelper();

        #region  系统初始化
        public FrmHelper()
        {
            InitializeComponent();

            //串口基本参数初始化
            this.cboBaudRrate.SelectedIndex = 5;   //波特率默认9600
            this.cboCheckBit.SelectedIndex = 0;      //校验位默认NONE
            this.cboDataBit.SelectedIndex = 2;         //数据位默认8
            this.cboStopBit.SelectedIndex = 0;         //停止位默认1

            //获取当前计算机的端口
            if (this.serialPortHelper.PortNames.Length == 0)
            {
                MessageBox.Show("当前计算机上没有找到可用的端口!", "警告信息");
                this.btnOperatePort.Enabled = false;//禁用打开端口按钮
            }
            else
            {
                //将端口添加到下拉框
                this.cboCOMList.Items.AddRange(this.serialPortHelper.PortNames);
                this.cboCOMList.SelectedIndex = 0;
            }

            //串口对象委托和串口接收数据事件关联
            this.serialPortHelper.SerialPortObject.DataReceived +=
                new SerialDataReceivedEventHandler(this.SerialPort_DataReceived);
        }

        #endregion

        #region 串口参数设置

        //波特率的设置
        private void cboBaudRrate_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.serialPortHelper.SerialPortObject.BaudRate = Convert.ToInt32(this.cboBaudRrate.Text);
        }
        //设置奇偶校验
        private void cboCheckBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboCheckBit.Text == "EVEN")
                serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.Even;
            else if (cboCheckBit.Text == "NONE")
                serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.None;
            else if (cboCheckBit.Text == "0DD")
                serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.Odd;
        }
        //设置数据位
        private void cboDataBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.serialPortHelper.SerialPortObject.DataBits = Convert.ToInt32(cboDataBit.Text);
        }
        //设置停止位
        private void cboStopBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboStopBit.Text == "1")
                serialPortHelper.SerialPortObject.StopBits = System.IO.Ports.StopBits.One;
            else if (cboStopBit.Text == "2")
                serialPortHelper.SerialPortObject.StopBits = System.IO.Ports.StopBits.Two;
        }

        #endregion

        #region 打开与关闭端口

        private void btnOperatePort_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.btnOperatePort.Text.Trim() == "打开端口")
                {
                    this.serialPortHelper.OpenSerialPort(this.cboCOMList.Text.Trim(), 1);
                    this.lblSerialPortStatus.Text = "端口已打开";
                    this.lblStatusShow.BackColor = Color.Green;
                    this.btnOperatePort.Text = "关闭端口";
                    this.btnOperatePort.Image = this.imageList.Images[0];
                }
                else
                {
                    this.serialPortHelper.OpenSerialPort(this.cboCOMList.Text.Trim(), 0);
                    this.lblSerialPortStatus.Text = "端口未打开";
                    this.lblStatusShow.BackColor = Color.Red;
                    this.btnOperatePort.Text = "打开端口";
                    this.btnOperatePort.Image = this.imageList.Images[1];
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("端口操作异常:" + ex.Message);
            }
        }

        #endregion

        #region 发送数据

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (this.txtSender.Text.Trim().Length == 0)
            {
                MessageBox.Show("发送内容不能为空!", "提示信息");
            }
            else
            {
                //开始发送
                SendData(this.txtSender.Text.Trim());
            }
        }

        //这个方法独立出来,是为了后面扩展自动定时发送数据的时候调用
        private void SendData(string data)
        {
            try
            {
                if (this.ckb16Send.Checked)//发送十六进制数据
                {
                    this.serialPortHelper.SendData(data, SendFormat.Hex);
                }
                else  //发送字符串
                {
                    this.serialPortHelper.SendData(data, SendFormat.String);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("发送数据出现错误:" + ex.Message, "错误提示!");
            }
        }

        #endregion

        #region 串口接收数据的事件

        /// <summary>
        /// 串口接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                ReceiveData(this.serialPortHelper.ReceiveData());
            }
            catch (Exception ex)
            {
                MessageBox.Show("接收数据出现错误:" + ex.Message);
            }
        }
        /// <summary>
        /// 接收数据的具体实现过程
        /// </summary>
        /// <param name="byteData"></param>
        private void ReceiveData(byte[] byteData)
        {
            string data = string.Empty;
            if (this.ckb16Receive.Checked)//十六机制接收
            {
                data = this.serialPortHelper.AlgorithmHelperObject.BytesTo16(byteData, Enum16Hex.Blank);
                //在这里编写具体的数据处理过程。。。可以保存到数据库,或其他文件...
            }
            else
            {
                data = this.serialPortHelper.AlgorithmHelperObject.BytesToString(byteData, Enum16Hex.None);
            }

            //显示到当年文本框中
            //因为接收数据的事件是一个独立显存,所有必须通过跨线程访问可视化控件的方法来完成展示
            //Invoke()方法的第一个参数必须是返回值为void的委托,第二个参数是给委托对应方法传递的参数
            this.txtReceiver.Invoke(new Action<string>(s => { this.txtReceiver.Text += "   " + s; }), data);
            //屏蔽跨线程访问可视化空间引发的异常(不建议使用这种方式)
            //  Control.CheckForIllegalCrossThreadCalls = false;
        }

        #endregion

        //请空数据按钮
        private void btnClear_Click(object sender, EventArgs e)
        {
            this.txtReceiver.Clear();
            this.txtSender.Clear();
        }
    }
}

 

posted @ 2023-08-27 18:14  竹林听雨行  阅读(167)  评论(0编辑  收藏  举报