软件功能:
使用C#实现PC串口通讯
支持定时发送
支持16进制(hex) ASCII UTF-8 Unicode 四种编码格式
支持配置文件的保存和读取
可以可以显示发送历史
可以统计总的发送字节数和接受字节数
软件界面:

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}] 小贝 \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");
- }
- }
- }
复制代码
软件下载:
串口调试工具.rar
源码工程文件:
串口调试工具.rar
虚拟端口软件下载:
VirtualSerialPortDriver.rar
未实现的功能:
16进制校验功能,即发送16进制格式的时候检查输入值是否为正确的16进制数字
接受文件的完整性校验功能,有时候一条信息会分两次接受完整
本文为博主原创,转载请保留出处: http://www.chengchenxu.com/Article/30/ |