前言

这是我在大三的时候写的一个串口助手,觉得挺好用的就分享给大家。如果有什么bug的话,希望大家多多包涵,毕竟对于C#语言我只是新手。

制作串口助手

串口助手选用Visual C#开发语言和Visual Studio 2012开发平台进行开发,实现的主要功能如下:

  1. 需要用户名和密码才能登录软件——可以保障用户的隐私
  2. 可用串口扫描——精确且快速的找到可以打开的串口号
  3. 保存和读取数据——可以对数据进行保存和读取,方便后期查看
  4. 显示接收数据的时间——用户可以知道数据到来的时间
  5. 定时发送——用户可以设定在几秒甚至几小时后发送控制命令

成品图如下

登陆界面的源码如下

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;namespace SerialCommunicate
{public partial class login : Form{public login(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){if (textBox1.Text == "刘小纯" && textBox2.Text == "3118003167"){MessageBox.Show("欢迎登录系统!", "提示");this.Hide();Form1 form1 = new Form1();form1.Show();}else if(textBox1.Text == "刘小纯" && textBox2.Text != "3118003167"){MessageBox.Show("密码错误!", "提示");}else if (textBox1.Text != "刘小纯"){MessageBox.Show("该用户不存在!", "提示");}}private void label3_Click(object sender, EventArgs e){}}
}

主页面源码如下

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.Ports;  //导入串口的命名空间
using System.IO;
//using System.Text.RegularExpressions;
//using System.Threading.Tasks;
//using System.Collections;namespace SerialCommunicate
{public partial class Form1 : Form{public Form1(){InitializeComponent();serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);      //串口数据接收事件serialPort1.Encoding = Encoding.GetEncoding("GB2312");                                  //串口接收编码System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;                   //}//List<byte> receivedDatas = new List<byte>();  //接收数据泛型数据/*窗体创建初始化函数*/private void Form1_Load(object sender, EventArgs e)   //窗口弹出触发{ovalShape1.FillColor = Color.Gray;    //小圆圈状态为灰色SearchAndAddSerialToComboBox(serialPort1, comboBox1);  //可用串口扫描comboBox2.Text = "115200";//默认波特率选择    comboBox4.Text = "8";//默认数据位comboBox5.Text = "无";//默认校验位comboBox3.Text = "1";//默认停止位}/*点击打开串口按键触发*/private void button1_Click(object sender, EventArgs e)      {try{serialPort1.PortName = comboBox1.Text;                 //端口号           serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);//波特率 serialPort1.DataBits = Convert.ToInt32(comboBox4.Text.Trim()); //设置数据位,默认为8switch (comboBox5.Text.Trim())  //设置奇偶校验位,默认为无{case "无":serialPort1.Parity = Parity.None; break;case "奇校验":serialPort1.Parity = Parity.Odd; break;case "偶校验":serialPort1.Parity = Parity.Even; break;default:serialPort1.Parity = Parity.None; break;}switch(comboBox3.Text .Trim () )                       //设置停止位,默认为1{case "1":serialPort1.StopBits = StopBits .One ;break ;                   case "1.5":serialPort1.StopBits = StopBits .OnePointFive ;break ;case "2":serialPort1.StopBits  = StopBits .Two ;  break;                  default:serialPort1.StopBits  = StopBits .None ; break;   }serialPort1.ReadTimeout = 5000;   //设置超时时间为5SControl.CheckForIllegalCrossThreadCalls = false;// 这个类中我们不检查跨线程的调用是否合法//定义.DataReceived事件的委托,当串口收到数据后触发事件,//serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); //加了会使自动换行和显示时间出BugserialPort1.Open();                //打开串口button1.Enabled = false;           //打开串口的按键不能使用button2.Enabled = true;            //关闭串口的按键可以使用ovalShape1.FillColor = Color.Red;   //串口状态指示灯为红色}catch                                  //出错处理{MessageBox.Show("串口打开错误或波特率设置有误", "小纯提示");  //弹出系统提示框}}/*点击关闭串口触发*/private void button2_Click(object sender, EventArgs e)   {try{serialPort1.Close();             //关闭串口        button1.Enabled = true;         //打开串口按键可用button2.Enabled = false;        //关闭串口按键不可用ovalShape1.FillColor = Color.Gray;  //串口状态指示灯变为灰色comboBox2.DropDownStyle = ComboBoxStyle.DropDownList;  //当点击关闭串口时,将波特率下拉列表设置为不可编辑}catch{MessageBox.Show("关闭串口错误!", "小纯提示");}}/*定义一个扫描可用串口的函数*/private void SearchAndAddSerialToComboBox(SerialPort MyPort, ComboBox MyBox){                                                               //将可用端口号添加到ComboBoxstring Buffer;                                              //缓存MyBox.Items.Clear();                                        //清空ComboBox内容for (int i = 1; i < 20; i++)                                //循环{try                                      //核心原理是依靠try和catch完成遍历,即是从COM1到COM19逐个打开试试,//如果能打开,就把这个串口号添加到串口的下拉列表中,后关闭串口,让用户打开{Buffer = "COM" + i.ToString();MyPort.PortName = Buffer;MyPort.Open();                                      //如果失败,后面的代码不会执行MyBox.Items.Add(Buffer);                            //打开成功,添加至下拉列表MyPort.Close();                                     //关闭串口}catch{//不添加出错处理,因为这个程序就是为了试错}}}/*串口接收事件*/private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)         {if (!radioButton3.Checked)     //接收模式为ASCII(字符){if (checkBox3.Checked)    //显示时间的校验框被选中{textBox1.AppendText(System.DateTime.Now.ToString("HH:mm:ss")+"\r\n");  //在接收数据的前面一行追加显示时间}textBox1.AppendText(serialPort1.ReadExisting());   //串口类会自动处理汉字,所以不需要特别转换,textBox1是输出框if (checkBox2.Checked)     //自动换行的校验框被选中try{textBox1.AppendText(Environment.NewLine);  //接收自动换行}catch {}}else      //接收模式为Hex(数值){byte[] data = new byte[serialPort1.BytesToRead];    //定义缓冲区,大小为:serialPort1.BytesToRead,因为串口事件触发时有可能收到不止一个字节serialPort1.Read(data, 0, data.Length);           //从串口中读取数据/*函数原型:foreach(Type t in arry);  Type:需要遍历每一的对象的类型,t:每一个对象,arry:需要遍历的数组*/foreach (byte Member in data)                      //遍历用法{string str = Convert.ToString(Member, 16).ToUpper();  //将Member这个数转化为字符串,并且大写textBox1.AppendText("0x" + (str.Length == 1 ? "0" + str : str) + " ");//如果str的长度为1的就在其前面添加0如0x0A}if (checkBox3.Checked)   //显示时间的校验框被选中{textBox1.AppendText("\r\n"+System.DateTime.Now.ToString("HH:mm:ss"));}if (checkBox2.Checked)     //自动换行的校验框被选中try{textBox1.AppendText(Environment.NewLine);}catch { }}}/*发送按键触发*/private void button3_Click(object sender, EventArgs e){byte[] Data = new byte[1];      //定义一个单字节的数组,用来发数据     if (serialPort1.IsOpen)        //判断串口是否打开{if (textBox2.Text != "")    //判断输入框的内容是否为空{if (!radioButton1.Checked)   //发送模式为ASCII(字符){try{serialPort1.Write(textBox2.Text);   //将指定的字符串写入串口//serialPort1.WriteLine();       //字符串写入}catch{MessageBox.Show("串口数据写入错误", "小纯提示");}}else                        //发送模式为HEX(数值){try                  //如果此时用户输入字符串中含有非法字符(字母,汉字,符号等等,try,catch块可以捕捉并提示){/*将用户输入的数字比如1234,转化为0x12,0x34*/for (int i = 0; i < (textBox2.Text.Length - textBox2.Text.Length % 2) / 2; i++)//转换偶数个{Data[0] = Convert.ToByte(textBox2.Text.Substring(i * 2, 2), 16);   //转换(一次处理两个数字?)serialPort1.Write(Data, 0, 1);      //将转化好的一个字节写入串口}if (textBox2.Text.Length % 2 != 0)  //如果数据的长度为奇数,需要单独处理最后一位{Data[0] = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length - 1, 1), 16);//单独处理最后一个字符serialPort1.Write(Data, 0, 1);         //写入}  }catch{MessageBox.Show("数据转换错误,请输入数字。", "小纯提示");}}}}}/*扫描按键触发*/private void button5_Click(object sender, EventArgs e){SearchAndAddSerialToComboBox(serialPort1, comboBox1);       //扫描并将可用串口添加至下拉列表}/*清空按键触发*/private void button4_Click(object sender, EventArgs e){textBox1.Text = "";}/*定时发送校验框被选中*/private void checkBox1_CheckedChanged(object sender, EventArgs e){if (checkBox1.Checked)   //定时发送校验框被选中{try{//选择自动发送numericUpDown1.Enabled = false;     //启动定时发送后不能修改定时时间timer1.Interval = (int)numericUpDown1.Value;// * 1000;  //设置定时器中断时间,*1000将单位转化为秒timer1.Start();                     //启动定时器}catch { }}else        //定时发送校验框不被选中{try{//选择不自动发送numericUpDown1.Enabled = true;   //  //停止定时发送后能修改定时时间timer1.Stop();                 //停止定时}catch{timer1.Stop();           //出错的话再次停止定时MessageBox.Show("停止自动发送错误", "小纯提示");}}}/*定时时间到,定时发送数据*/private void timer1_Tick(object sender, EventArgs e){button3_Click(button3, new EventArgs());  //调用发送按钮的回调函数}/*清空发送框*/private void button6_Click_1(object sender, EventArgs e)  {textBox2.Clear();}/*点击波特率设置下列表*/private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) {if (comboBox2.Text.Equals("custom"))      //当选择custom项时列表属性发生改变{try{// comboBox2.DropDownStyle = ComboBoxStyle.DropDown;comboBox2.DropDownStyle = ComboBoxStyle.Simple;     //将属性更改为可以编辑}catch{MessageBox.Show("设置波特率时错误!", "小纯提示");}}}/*点击保存数据按钮*/private void button7_Click(object sender, EventArgs e) {/*saveFileDialog1 为保存文件的对话框,StreamWriter是专门用来处理文本文化的类,可以方便的向文本文件中写入字符串*/saveFileDialog1 = new SaveFileDialog();                 //初始化此类的新实例saveFileDialog1.Filter = "(*.txt)|*.txt";               //只允许保存为TXT文本// try//  {if (saveFileDialog1.ShowDialog() == DialogResult.OK)    //页面弹出判断框是否点击确定按钮{StreamWriter streamWriter = new StreamWriter(saveFileDialog1.FileName, false);streamWriter.Write(this.textBox1.Text);//将输出框的字符串写入TXT文本streamWriter.Close(); //关闭流}// }// catch { MessageBox.Show("先打开串口!", "小纯提示"); }}/*点击读入文件按钮*/private void button8_Click(object sender, EventArgs e)  {OpenFileDialog openFileDialog1 = new OpenFileDialog();openFileDialog1.Filter = "All files(*.*)|*.*|txt file (*.txt)|*.txt";if (openFileDialog1.ShowDialog() == DialogResult.OK){string logpath = openFileDialog1.FileName;using (StreamReader sr = new StreamReader(logpath, Encoding.GetEncoding("gb2312"))){string oneLineInfo = string.Empty;  //读取到的每行内容while (sr.EndOfStream != true){oneLineInfo = oneLineInfo + "\r\n" + sr.ReadLine();//按行读取}sr.Close();textBox1.Text = oneLineInfo;}} }}
}

登陆界面与主页面的切换

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;namespace SerialCommunicate
{static class Program{/// <summary>/// 应用程序的主入口点。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);//Application.Run(new Form1());   Application.Run(new login());  //若不需要登陆界面就把这个注释掉,取消上面的注释}}
}

上位机软件-串口助手-带登陆界面相关推荐

  1. 从零开始编写一个上位机(串口助手)QT Creator + Python

    提示:本博客作为学习笔记,有错误的地方希望指正,此文可能会比较长,作为学习笔记的积累,希望对来着有帮助.   绪论:笔者这里使用的是QTCreator和Python来实现一个简单的串口上位机的开发的简 ...

  2. Java串口助手 带UI界面 Java串口调试工具 FPV

    Java串口助手 带UI界面 Java串口调试工具 FPV 效果图 随便讲点 依赖jar包 代码 测试用代码 效果图 随便讲点 这个说是串口调试工具有点尴尬, 因为最开始是为了用电脑在自己做的小车上玩 ...

  3. Qt上位机软件串口通讯

    录了一个串口讲解的视频,分别放在了抖音和B站,大家可以看看,主要讲了一下原理, B站我的主页:laorenshen的个人空间_哔哩哔哩_Bilibili 视频源码下载免费:Qt上位机软件串口通讯,视频 ...

  4. 从零开始编写一个上位机(串口助手)QT Creator + C++

    提示:本博客作为学习笔记,有错误的地方希望指正,此文可能会比较长,作为学习笔记的积累,希望对来着有帮助.   绪论:笔者这里使用的是QTCreator和C++来实现一个简单的串口上位机的开发的简单过程 ...

  5. C#上位机软件串口数据接收用Invoke(同步)和BeginInvoke(异步)的区别

    在串口接收很多数据且速度很快时,用Invoke后,关闭串口会导致界面卡死,如果改用BeginInvoke则关闭串口时,可以关闭串口且界面不会卡死. this.Invoke((EventHandler) ...

  6. 【科普】干货!带你从0了解移动机器人(三) ——自主导航系统及上位机软件设计与实现

    随着机器人技术的不断发展,我们可以在许多简单重复,危险的岗位上看到机器人的身影,移动机器人凭借其在复杂环境下工作,具有自行感知.自行规划.自我决策功能的能力,它可以在不同的环境中移动并执行任务,在人类 ...

  7. 使用C#进行串口通信开发上位机软件

    因为工作需要 曾使用C#开发一款上位机软件,当时工期很赶,开发联调测试交付后就转向其他工作.一直念叨着要记录一下,这次五一终于如愿. 软件开发环境:操作系统windows64位,开发工具:VisioS ...

  8. 如何调试上位机软件与串口进行通信

    为了在没有下位机连接的情况下调试上位机软件,看上位机软件是否能通过串口和下位机通信,以及通信的具体内容,下面给出解决方法: 1.下载"vspd虚拟串口" vspd虚拟串口软件是用来 ...

  9. VC++6.0上实现PC机与单片机串口通信的PC端上位机软件

    1.简介 我做这个的主要原因是选了一个PC和单片机的全双工串口通信作为课设题目,单片机端是用汇编语言编程且要预先下载到板子里,关于这个这里我就不多说,主要说说怎么实现PC端的上位机软件.早知道要写软件 ...

最新文章

  1. mysql在linux下的安装
  2. PHP日期格式转时间戳
  3. EOS 核心功能 (2) nodeos
  4. HihoCoder - 1829 Tomb Raider(暴力)
  5. P1372 又是毕业季I
  6. 156 - Ananagrams
  7. CSS3 多列布局的跨列
  8. python内置对象的实现_Python面向对象——内置对象的功能扩展
  9. python可视化网页设计_python可视化工具
  10. 集合竞价选股(附源码)
  11. uniapp h5 微信分享
  12. SpringBoot 一文搞懂Spring JPA
  13. 高德地图开放平台概览
  14. [转][darkbaby]任天堂传——失落的泰坦王朝(中)
  15. 推荐8个相见恨晚的学习类app,每一个都诚意满满
  16. 火车头采集翻页内容_火车头采集器教程:使用分页采集有分页的数据
  17. firefox 下载文件时处理此文件的方法
  18. java微信支付v3系列——8.微信支付之退款成功回调
  19. 一文读懂md5,md5有什么用,什么是md5加盐
  20. 量化交易——传统技术分析相对强弱指数RSI的原理及实现

热门文章

  1. Arduino UNO R3开发板+MQ-2烟雾浓度传感器+火焰传感器+舵机+无源蜂鸣器+风扇+步进电机+WIFI模块+RGB三色LED灯+SIM900A所构成的室内安全报警模块
  2. 解决Ubuntu系统无限登录或者是桌面一片空白问题。
  3. corba核心规范(转)
  4. PowerDesigner16.5导出SQL语句时如何将name列复制到comment注释里面
  5. python获取元素在array中的下标
  6. 史上最节省施工费用的防水材料,
  7. python中的方法什么意思_什么是Python中的“方法”?
  8. 小程序直播带货app源码直播组件接入指引
  9. python---面向对象,class参数、__init__方法、与函数区别
  10. C语言解决 加油站问题