C#编写串口助手
借鉴了很大部分下面文章的内容,我也修改了很多,最后完善成了一个完整的串口助手。
C#编写串口助手
1.UI设置
①创建Windows窗口应用程序。
文件—新建—项目,选择Visual C#,选择Windows窗体应用程序,名称:项目名称"调试串口助手",位置:保存项目的路径,解决方案:创建新的解决方案(添加到解决方案),解决方案名称:自动生成与项目名称相同,框架:.NET Framework 4.7,默认勾选为解决方案创建目录,点击确定。
创建新项目后可以看到Form1.cs[设计],这是自动生成的窗体应用,在这个页面利用左边工具栏和对应UI的属性可以设计UI。
找到解决中的Form1.cs,右键->查看代码,可以代码文件。
②创建窗体的界面。
Form1窗体添加三个GroupBox控件,Text分别设置为:串口设置、接收数据、发送数据。
Form1窗体添加五个Lable控件,Text分别设置为:串口号:、波特率:、停止位:、奇偶校验:、数据位:。
Form1窗体添加五个ComoBox控件,Name分别设置为:cbxCOMPort、cbxBaudRate、cbxStopBits、cbxParity、cbxDataBits。
Form1窗体添加两个RadioButton控件,Text分别设置为:字符显示、HEX显示,Name分别设置为:rbnChar、rbnHex,
Checked分别为:True、False。
Form1窗体添加八个Button控件,Text分别设置为:检测串口、打开串口、清空数据、发送数据、AT、ATI8、选择文件、发送文件。
注:笔者截图里发送AT命令远不止两个按钮是因为此类命令代码非常相似,于是就只写了两个。
Name分别设置为:btnCheckCom、btnOpenCom、btnClearData、btnSendData。
Form1窗体添加三个TextBox控件,Name分别设置为:tbxRecvData、tbxSendData、filename_test_box,filename_test_box、tbxRecvData和的ReadOnly属性设置为True。
Fomr1窗体的AcceptButton属性设置为btnSendData,在窗体上回车关联到发送数据按钮。
③代码编写。
代码+注释如下:
//新手可以下载一个vspn创建虚拟串口搭配使用:)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;namespace 调试串口工具
{public partial class Form1 : Form{bool isHex = false;//十六进制显示标志位bool isOpen = false;//打开串口标志位bool isSetProperty = false;//属性设置标志位bool isfiletranfers = false;//文件传输标志位SerialPort serialportcom = null;public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){//设置窗口大小this.MaximizeBox = true; //影藏最大化按钮this.MaximumSize = this.Size; //固定窗口尺寸最大为当前尺寸this.MinimumSize = this.Size; //固定窗口尺寸最小为当前尺寸//Form1.refresh();//设置波特率cbxBaudRate.Items.Add("1200");cbxBaudRate.Items.Add("2400");cbxBaudRate.Items.Add("4800");cbxBaudRate.Items.Add("9600");cbxBaudRate.Items.Add("19200");cbxBaudRate.Items.Add("38400");cbxBaudRate.Items.Add("115200");cbxBaudRate.SelectedIndex = 3;//列出停止位cbxStopBits.Items.Add("0");cbxStopBits.Items.Add("1");cbxStopBits.Items.Add("1.5");cbxStopBits.Items.Add("2");cbxStopBits.SelectedIndex = 1;//列出数据位cbxDataBits.Items.Add("8");cbxDataBits.Items.Add("7");cbxDataBits.Items.Add("6");cbxDataBits.Items.Add("5");cbxDataBits.SelectedIndex = 0;//列出奇偶检验cbxParity.Items.Add("无");cbxParity.Items.Add("奇校验");cbxParity.Items.Add("偶校验");cbxParity.SelectedIndex = 0;//默认接受到的数据用字符显示rbnChar.Checked = true;}private void btnCheckCom_Click(object sender, EventArgs e){bool comExistence = false;//有可用串口标志位cbxCOMPort.Items.Clear();//将读取到的串口号写入选项框foreach (string sPortName in SerialPort.GetPortNames()){try{cbxCOMPort.Items.Add(sPortName);comExistence = true;}catch (Exception){continue;}}if (comExistence){cbxCOMPort.SelectedIndex = 0;}else{MessageBox.Show("没有找到可用的串口!", "错误提示");}}private bool checkPortSetting()//检测串口设置{if (cbxCOMPort.Text.Trim() == "") return false;if (cbxBaudRate.Text.Trim() == "") return false;if (cbxDataBits.Text.Trim() == "") return false;if (cbxParity.Text.Trim() == "") return false;if (cbxStopBits.Text.Trim() == "") return false;return true;}private bool CheckSendData()//检测发送数据是否输入{if (tbxSendData.Text.Trim() == "") return false;return true;}private bool CheckFileSendData(){if (filename_test_box.Text.Trim() == "") return false;return true;}private void SetPortProperty()//设置串口的属性{//创建串口serialportcom = new SerialPort();//设置串口名serialportcom.PortName = cbxCOMPort.Text.Trim();//设置串口波特率serialportcom.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim());//设置串口数据位serialportcom.DataBits = Convert.ToInt32(cbxDataBits.Text.Trim());//设置串口停止位if (cbxStopBits.Text.Trim() == "0"){serialportcom.StopBits = StopBits.None;}if (cbxStopBits.Text.Trim() == "1"){serialportcom.StopBits = StopBits.One;}if (cbxStopBits.Text.Trim() == "1.5"){serialportcom.StopBits = StopBits.OnePointFive;}if (cbxStopBits.Text.Trim() == "2"){serialportcom.StopBits = StopBits.Two;}//设置校验if (cbxParity.Text.Trim() == "无"){serialportcom.Parity = Parity.None;}if (cbxParity.Text.Trim() == "奇校验"){serialportcom.Parity = Parity.Odd;}if (cbxParity.Text.Trim() == "偶校验"){serialportcom.Parity = Parity.Even;}serialportcom.ReadTimeout = 100000;//设置超时读取时间serialportcom.RtsEnable = true;serialportcom.DataReceived += new SerialDataReceivedEventHandler(serialportcom_DataReceived);//接受数据事件监听if (rbnHex.Checked){isHex = true;}else{isHex = false;}}private void btnOpenCom_Click(object sender, EventArgs e){if (isOpen == false){if (!checkPortSetting())//检测串口设置{MessageBox.Show("串口未设置", "错误提示");return;}if (!isSetProperty){SetPortProperty();isSetProperty = true;}try{serialportcom.Open();isOpen = true;btnOpenCom.Text = "关闭串口";//串口打开后,相关的串口设置按钮不再可用cbxCOMPort.Enabled = false;cbxBaudRate.Enabled = false;cbxDataBits.Enabled = false;cbxStopBits.Enabled = false;cbxParity.Enabled = false;rbnChar.Enabled = false;rbnHex.Enabled = false;btnCheckCom.Enabled = false;}catch (Exception){isSetProperty = false;//串口设置标志位设置为falseisOpen = false; //串口打开标志位设置为falseMessageBox.Show("串口无效或被占用", "错误提示");//打开失败提示消息框}}else//之前串口是打开的,则执行else语句块{try{serialportcom.Close();//关闭串口isOpen = false; //串口打开标志位设置为falsebtnOpenCom.Text = "打开串口"; //btnOpenCom的文本设置为“打开串口”cbxCOMPort.Enabled = true; //串口号使能cbxBaudRate.Enabled = true; //波特率cbxDataBits.Enabled = true; //数据位cbxStopBits.Enabled = true; //停止位cbxParity.Enabled = true; //校验rbnChar.Enabled = true; //字符型rbnHex.Enabled = true; //Hex型btnCheckCom.Enabled = true;//检测串口}catch (Exception){MessageBox.Show("关闭串口时发生错误", "错误提示"); //关闭失败提示消息框}}}private void button2_Click(object sender, EventArgs e)//选择文件时间监听{//新建一个文件对话框OpenFileDialog pOpen = new OpenFileDialog();//创建文件变量//设置对话框标题pOpen.Title = "打开想要传输的文件";//设置打开文件类型pOpen.Filter = "所有文件(*.*)|*.*";//监测文件是否存在pOpen.CheckFileExists = true;//文件打开后执行以下程序if (pOpen.ShowDialog() == DialogResult.OK){filename_test_box.Text = pOpen.FileName;isfiletranfers = true;}}private void button1_Click(object sender, EventArgs e)//发送文件{if (isOpen){try{string filenameee = filename_test_box.Text;//获取文件名FileStream fs = File.OpenRead(@filenameee);//新建文件流byte[] filedata = new byte[fs.Length];//创建文件内容大小的字节空间fs.Read(filedata, 0, filedata.Length);//将文件内容写入字节空间string writest = Encoding.Default.GetString(filedata);filedata = Encoding.Default.GetBytes(writest);serialportcom.Write(filedata, 0, filedata.Length);//传输字节数组//判断文件传输完毕,文件传输标志位变为falseif (serialportcom.BytesToRead == 0){isfiletranfers = false;}}catch{MessageBox.Show("发送数据时发生错误!", "错误提示");return;}}else{MessageBox.Show("串口未打开", "错误提示");}if (!CheckFileSendData()){MessageBox.Show("请输入要发送的数据", "错误提示");}}private void btnSendData_Click(object sender, EventArgs e){if (isOpen) //串口打开状态{try{Encoding sendData = System.Text.Encoding.GetEncoding(936);//使用合适字符编码,936表示GB2312byte[] bytesSD = Encoding.Default.GetBytes(tbxSendData.Text+"\r\n");//创建字节空间,并写入待传输数据tbxRecvData.Text += tbxSendData.Text + "\r\n";serialportcom.Write(bytesSD, 0, bytesSD.Length); //串口发送数据tbxRecvData.Text += "发送成功" + "\r\n";}catch{MessageBox.Show("发送数据时发生错误!", "错误提示");return;}}else{MessageBox.Show("串口未打开", "错误提示");}if (!CheckSendData()){MessageBox.Show("请输入要发送的数据", "错误提示");}}private void serialportcom_DataReceived(object sender, SerialDataReceivedEventArgs e){System.Threading.Thread.Sleep(100); //延时100ms,等待接收完数据//MessageBox.Show("收到数据");this.Invoke((EventHandler)(delegate //this.Invoke是跨线程访问ui的方法,也是文本的范例{try{if (isHex == false){tbxRecvData.Text += "正在接收数据...." + "\r\n";byte[] a = new byte[serialportcom.BytesToRead];//创建一个缓冲区数据大小的字节空间serialportcom.Read(a, 0, a.Length); //读取缓冲区的数据,并将其写入a的空间中string recvstring = Encoding.Default.GetString(a);//解码出a中的字符信息tbxRecvData.Text += recvstring + "\r\n";}else{Byte[] ReceivedData = new Byte[serialportcom.BytesToRead]; //定义并初始化字符数组,sp.ByteToRead串口读字符串长度serialportcom.Read(ReceivedData, 0, ReceivedData.Length); //字符数组读取串口数据String RecvDataText = null; //定义字符串for (int i = 0; i < ReceivedData.Length; i++){RecvDataText += ("0X" + ReceivedData[i].ToString("X2") + " "); //串口接收字符数组,字符依次转换为字符串,0XxxRecvDataText +="\r\n"; //X2:X是十六进制,2是两位。(A X2--0X0A,A X---0XA)}tbxRecvData.Text += RecvDataText; //转换后的字符串显示到tbxRecvData上面}}catch (Exception){MessageBox.Show("数据接受失败");}serialportcom.DiscardInBuffer(); //清除串口接收缓冲区数据}));}private void btnClearData_Click_1(object sender, EventArgs e)//清空数据{tbxRecvData.Text = "";tbxSendData.Text = "";filename_test_box.Text = "";}private void btnAT1_Click(object sender, EventArgs e){Encoding sendData = System.Text.Encoding.GetEncoding(936);//使用合适字符编码,936表示GB2312byte[] bytesSD = Encoding.Default.GetBytes("AT" + "\r\n");//创建字节空间,并写入待传输数据tbxRecvData.Text += btnAT1.Text + "\r\n";serialportcom.Write(bytesSD, 0, bytesSD.Length); //串口发送数据tbxRecvData.Text += "发送成功" + "\r\n";}private void btnAT2_Click(object sender, EventArgs e){Encoding sendData = System.Text.Encoding.GetEncoding(936);//使用合适字符编码,936表示GB2312byte[] bytesSD = Encoding.Default.GetBytes("ATI8" + "\r\n");//创建字节空间,并写入待传输数据tbxRecvData.Text += btnAT2.Text + "\r\n";serialportcom.Write(bytesSD, 0, bytesSD.Length); //串口发送数据tbxRecvData.Text += "发送成功" + "\r\n";}}
}