当前位置: 程晨旭的博客 > 代码库>正文

C.Net串口工具源码 串口调试工具 支持16进制发送 可以定时自动发送

软件功能:


使用C#实现PC串口通讯

支持定时发送

支持16进制(hex) ASCII UTF-8 Unicode 四种编码格式

支持配置文件的保存和读取

可以可以显示发送历史

可以统计总的发送字节数和接受字节数

软件界面:


Screen Shot 2018-03-17 at 17.47.04 PM.png


C#源码:

using System;
using System.Collections.Generic;
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;
using System.Threading;
using System.IO;
using System.Xml.Serialization;

namespace 串口调试工具
{
    public partial class Form1 : Form
    {
        private SerialPort sp = new SerialPort();//链接对象
        Config config = new Config();//配置文件

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //获取串口列表
            string[] comList = SerialPort.GetPortNames();
            if (comList.Length == 0)
            {
                MessageBox.Show("无可用串口");
                return;
            }
            foreach (var com in comList)
            {
                cmbComList.Items.Add(com);
            }


            //添加波特率
            int[] baudRate = { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 43000, 56000, 57600, 115200 };
            foreach (var br in baudRate)
            {
                cmbBautRade.Items.Add(br);
            }

            //添加数据位
            int[] dataBits = { 8, 7, 6, 5 };
            foreach (var db in dataBits)
            {
                cmbDataBits.Items.Add(db);
            }

            //添加停止位
            int[] stopBits = { 1, 2, 3 };
            foreach (var sb in stopBits)
            {
                cmbStopBits.Items.Add(sb);
            }

            //添加检验方式
            string[] parity = { "None", "Even", "Mark", "Odd", "Space" };
            foreach (var p in parity)
            {
                cmbParity.Items.Add(p);
            }

            //添加常用编码
            string[] encode = { "ASCII","UTF-8","Unicode","Hex"};
            foreach (var en in encode)
            {
                cmbEncodeSend.Items.Add(en);
                cmbEncodeRec.Items.Add(en);
            }

            //加载配置文件
            LoadConfig();
        }

        private void LoadConfig()
        {
            //把配置信息赋值给控件默认值
            cmbComList.SelectedItem = config.PortName;
            if (cmbComList.SelectedIndex == -1) cmbComList.SelectedIndex = 0;
            cmbBautRade.SelectedItem = config.BautRade;
            cmbDataBits.SelectedItem = config.DataBits;
            cmbStopBits.SelectedItem = config.StopBits;
            cmbParity.SelectedItem = config.Parity;
            cmbEncodeRec.SelectedItem = config.EncodeRec;
            cmbEncodeSend.SelectedItem = config.EncodeSend;

            //激活打开按钮
            this.btnOpen.Enabled = true;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (((Button)sender).Text == "打开串口")
            {
                //赋值给串口
                sp.PortName = cmbComList.SelectedItem.ToString();
                sp.Parity=(Parity)Enum.Parse(typeof(Parity),cmbParity.SelectedItem.ToString());
                sp.BaudRate = Convert.ToInt32(cmbBautRade.SelectedItem.ToString());
                sp.StopBits = (StopBits)Convert.ToInt32(cmbStopBits.SelectedItem.ToString());
                sp.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString());

                try
                {
                    sp.Open();

                    //修改控件状态
                    this.btnOpen.Text = "关闭串口";
                    foreach (Control ctr in groupBox1.Controls)
                    {
                        //把下拉框全部禁用
                        ctr.Enabled = false;
                    }

                    //开启新线程,监听收取内容
                    Thread thread = new Thread(receive);
                    thread.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                if (this.btnAutoSend.Text == "停止发送")
                {
                    MessageBox.Show("当前定时发送中,请先停止定时发送任务.");
                    return;
                } 
                sp.Close();

                //修改控件状态
                this.btnOpen.Text = "打开串口";
                foreach (Control ctr in this.groupBox1.Controls)
                {
                    ctr.Enabled = true;
                }
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //窗体关闭时关闭端口
            sp.Close();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Send();
        }

        private void btnAutoSend_Click(object sender, EventArgs e)
        {
            if (this.btnAutoSend.Text == "定时发送")
            {
                //根据打开按钮状态初步检查端口是否已经打开
                if (this.btnOpen.Text == "打开串口") return;

                System.Text.RegularExpressions.Regex reg1 = new System.Text.RegularExpressions.Regex(@"^[0-9]\d*$");
                if (reg1.IsMatch(txtTime.Text.ToString()))
                {
                    //激活Timer定时器
                    this.timer1.Interval = Convert.ToInt32(txtTime.Text.ToString());
                    this.timer1.Start();

                    //修改控件状态
                    this.btnAutoSend.Text = "停止发送";
                    this.btnSend.Enabled = false;

                }
                else
                {
                    MessageBox.Show("发送间隔应为正整数");
                    txtTime.Text = "1000";
                }
            }
            else
            {
                this.btnAutoSend.Text = "定时发送";
                this.btnSend.Enabled = true;
                this.timer1.Stop();
            }
        }

        private void Send()
        {
            if (sp.IsOpen)
            {
                //获取字节
                byte[] buffer = Encode();
                if (buffer.Length == 0) return;

                try
                {
                    sp.Write(buffer, 0, buffer.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

                //添加发送历史
                this.txtHistory.AppendText(string.Format("[{0}] {1} \r\n", DateTime.Now.ToString("HH:mm:ss.ff"), txtSend.Text));
                //统计发送字节
                this.labSendCount.Text = (Convert.ToInt32(labSendCount.Text) + buffer.Length).ToString();
            }
            else
            {
                this.timer1.Stop();
                MessageBox.Show("串口尚未打开");
                this.btnAutoSend.Text = "定时发送";
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //定时发送
            Send();
        }

        //字节反编码
        private byte[] Encode()
        {
            byte[] buffer = null;

            switch (this.cmbEncodeSend.SelectedItem.ToString())
            {
                case "Unicode":
                    buffer = Encoding.Unicode.GetBytes(txtSend.Text); 
                    break;
                case "UTF-8":
                    buffer = Encoding.UTF8.GetBytes(txtSend.Text);
                    break;
                case "ASCII":
                    buffer = Encoding.ASCII.GetBytes(txtSend.Text);
                    break;
                case "Hex":
                    buffer = strToToHexByte(txtSend.Text);
                    break;
            }

            return buffer;
        }
        //编码
        private string UnEncode(byte[] buffer)
        {
            string str = string.Empty;

            switch (this.cmbEncodeSend.SelectedItem.ToString())
            {
                case "Unicode":
                    str = new UnicodeEncoding().GetString(buffer);
                    break;
                case "UTF-8":
                    str = new UTF8Encoding().GetString(buffer);
                    break;
                case "ASCII":
                    str = new ASCIIEncoding().GetString(buffer);
                    break;
                case "Hex":
                    str = byteToHexStr(buffer);
                    break;
            }

            return str;
        }
        /// <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;
        }
        /// <summary>
        /// 字符串转16进制字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private 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;
        }

        private void receive()
        {
            //接收信息 先判断是否为打开状态
            while (sp.IsOpen)
            {
                if (sp.BytesToRead == 0) continue;

                //准备接收
                byte[] buffer = new byte[sp.BytesToRead];
                try
                {
                    //接受动作
                    sp.Read(buffer, 0, buffer.Length);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

                //更新UI信息
                this.Invoke((Action)delegate
                {
                    this.txtRec.AppendText(UnEncode(buffer));
                    //是否自动换行
                    if(cbLine.Checked)
                        this.txtRec.AppendText("\r\n");

                    //接收统计信息
                    this.labRecCount.Text = (Convert.ToInt32(this.labRecCount.Text) + buffer.Length).ToString();
                });
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //清空发送历史
            this.txtHistory.Clear();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //清空接收
            this.txtRec.Clear();
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            //读取xml文件 序列化对象
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "XML(*.xml)|";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string filePath = ofd.FileName;
                if (File.Exists(filePath))
                {
                    try
                    {
                        var mySerializer = new XmlSerializer(typeof(Config));
                        using (var sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)))
                        {
                            config = (Config)mySerializer.Deserialize(sr);
                        }
                        LoadConfig();
                    }
                    catch (Exception ee)
                    {
                        MessageBox.Show(ee.Message);
                    }
                }
                else
                {
                    MessageBox.Show("文件不存在");
                }
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {

            FolderBrowserDialog fbd = new FolderBrowserDialog();            
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                //给对象赋值并序列化保存
                config.PortName = cmbComList.SelectedItem.ToString();
                config.Parity = cmbParity.SelectedItem.ToString();
                config.BautRade = Convert.ToInt32(cmbBautRade.SelectedItem.ToString());
                config.StopBits = Convert.ToInt32(cmbStopBits.SelectedItem.ToString());
                config.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString());

                XmlSerializer xmlFormat=new XmlSerializer(typeof(Config));
                string filePath = fbd.SelectedPath + "\\PortConfig.xml";
                using (Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    xmlFormat.Serialize(stream, config);
                }
                MessageBox.Show("成功保存到路径:"+filePath);
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.chengchenxu.com");  
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 串口调试工具
{
    [Serializable]
    public class Config
    {
        public string PortName { get; set; }
        public int BautRade { get; set; }
        public int DataBits { get; set; }
        public string Parity { get; set; }
        public string EncodeSend { get; set; }
        public string EncodeRec { get; set; }
        public int StopBits { get; set; }
        public Config()
        {
            //默认值
            BautRade = 9600;
            DataBits = 8;
            Parity = "None";
            EncodeSend = "ASCII";
            EncodeRec = "ASCII";
            StopBits = 1;
        }
        
    }
}


软件下载:

串口调试工具.rar


源码工程文件:

串口调试工具.rar


虚拟端口软件下载:

VirtualSerialPortDriver.rar


未实现的功能:

16进制校验功能,即发送16进制格式的时候检查输入值是否为正确的16进制数字

接受文件的完整性校验功能,有时候一条信息会分两次接受完整


本文为博主原创,转载请保留出处:
http://www.chengchenxu.com/Article/30/

‹‹ 上一篇 下一篇 ››

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。