c# 开发串口调试助手 Visual Studio 2019

一、串口调试工具作用

串口调试助手是用于在开发、测试和调试串口通信应用程序时进行串口数据的监视和交互的工具。它通常具有以下功能:

1. 串口参数设置:允许用户设置串口的波特率、数据位、校验位、停止位等参数。
2. 串口连接管理:允许用户打开、关闭串口连接。
3. 数据发送:允许用户手动输入或从文件中加载数据,并通过串口发送到目标设备。
4. 数据接收:显示从串口接收到的数据,并支持数据的解析和显示。
5. 数据记录:允许用户将接收到的数据保存到文件中以供后续分析和查看。
6. 数据分析:提供数据格式化、解析和显示的功能,便于用户理解和分析串口通信数据。
7. 数据监视:实时监视串口通信数据,包括发送和接收的数据量、速率等信息。
8. 自定义操作:支持用户自定义脚本或命令,以便执行特定的串口操作或测试。

总的来说,串口调试助手是串口通信开发过程中的一个重要辅助工具,能够帮助开发人员进行串口通信的测试、调试和分析。

二、开发工具

语言:C#        开发环境:Visual Studio 2019

三、开发步骤

1. 界面设计
- 使用 Windows Forms 或 WPF 进行界面设计。
- 设计包含串口参数设置、数据发送、数据接收、数据显示等功能的用户界面。

2. 串口通信
- 使用 `System.IO.Ports` 命名空间中的 `SerialPort` 类进行串口通信。
- 实现串口的打开、关闭、参数设置等功能。
- 监听串口数据的接收事件,并进行相应的处理。

3. 数据发送
- 提供文本框或其他输入控件,允许用户手动输入待发送的数据。
- 实现发送按钮点击事件,将数据通过串口发送。

4. 数据接收与显示
- 使用串口的 DataReceived 事件来监听串口数据的接收。
- 将接收到的数据显示在界面上的文本框或数据显示控件中。
- 可以对接收到的数据进行解析、格式化,方便用户阅读。

5. 数据记录与保存
- 提供数据记录功能,允许用户将接收到的数据保存到文件中。
- 实现保存按钮点击事件,将接收到的数据写入到指定的文件中。

6. 其他功能
- 支持设置串口的波特率、数据位、校验位、停止位等参数。
- 提供数据的清除、停止接收、清空接收缓存等功能。
- 支持用户自定义脚本或命令,执行特定的串口操作。

四、开发流程

1.创建工程

2.添加Panel控件

①.添加容器Panel,将页面分为6个页面,分别为串口配置窗口、接收区配置窗口、发送区配置窗口、接收数据显示窗口、发送数据编辑窗口、数据接收发送字节大小窗口。

②.实际运行效果,你会发现并没有边界线,这样后续视觉效果就会很差。

将添加边界线程序加在对应容器函数里面即可,记得修改panelx,x对应的是容器编号。

ControlPaint.DrawBorder(e.Graphics, panel1.ClientRectangle,Color.Black, 1, ButtonBorderStyle.Solid, //左边Color.Black, 1, ButtonBorderStyle.Solid, //上边Color.Black, 1, ButtonBorderStyle.Solid, //右边Color.Black, 1, ButtonBorderStyle.Solid);//底边

加上边界线程序效果如下: 

3.添加控件label和comboBox

添加下拉数据:

同理在数据位下拉列表里面添加5、6、7、8;在校验位下拉列表里面添加无、奇校验、偶校验;在停止位下拉列表里面添加1、1.5、2;

4.添加初始化程序

双击窗口,在Form2_Load函数里面添加初始化程序

private void Form2_Load(object sender, EventArgs e){string[] ports = System.IO.Ports.SerialPort.GetPortNames();//获取电脑上可用串口号comboBox1.Items.AddRange(ports);//给comboBox1添加数据comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//如果里面有数据,显示第0个comboBox2.Text = "115200";/*默认波特率:115200*/comboBox3.Text = "1";/*默认停止位:1*/comboBox4.Text = "8";/*默认数据位:8*/comboBox5.Text = "无";/*默认奇偶校验位:无*/}
5.添加串口控件

6.添加打开串口控件程序

双击打开串口按键,添加程序

private void button1_Click(object sender, EventArgs e){if (button1.Text == "打开串口"){//如果按钮显示的是打开串口try{//防止意外错误serialPort1.PortName = comboBox1.Text;//获取comboBox1要打开的串口号serialPort1.BaudRate = int.Parse(comboBox2.Text);//获取comboBox2选择的波特率serialPort1.DataBits = int.Parse(comboBox4.Text);//设置数据位/*设置停止位*/if (comboBox3.Text == "1") { serialPort1.StopBits = StopBits.One; }else if (comboBox3.Text == "1.5") { serialPort1.StopBits = StopBits.OnePointFive; }else if (comboBox3.Text == "2") { serialPort1.StopBits = StopBits.Two; }/*设置奇偶校验*/if (comboBox5.Text == "无") { serialPort1.Parity = Parity.None; }else if (comboBox5.Text == "奇校验") { serialPort1.Parity = Parity.Odd; }else if (comboBox5.Text == "偶校验") { serialPort1.Parity = Parity.Even; }serialPort1.Open();//打开串口button1.BackColor = Color.FromArgb(194, 178, 128);button1.Text = "关闭串口";//按钮显示关闭串口}catch (Exception err){MessageBox.Show("打开失败" + err.ToString(), "提示!");//对话框显示打开失败}}else{//要关闭串口try{//防止意外错误serialPort1.Close();//关闭串口}catch (Exception) { }button1.Text = "打开串口";//按钮显示打开button1.BackColor = Color.Transparent;}}

运行效果如下图

6.添加接收区控件textBox,勾选MultiLine,勾选后,拖拽为合适的大小

 7.选择serialPort1 -> 选择事件 -> 双击DataReceived

在函数serialPort1_DataReceived添加接收数据程序

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e){int len = serialPort1.BytesToRead;//获取可以读取的字节数byte[] buff = new byte[len];//创建缓存数据数组serialPort1.Read(buff, 0, len);//把数据读取到buff数组string str = Encoding.Default.GetString(buff);//Byte值根据ASCII码表转为 StringInvoke((new Action(() => //C# 3.0以后代替委托的新方法{textBox1.AppendText(str);//对话框追加显示数据})));}

 接下来就可以测试一下,我这里是通过虚拟串口工具(Virtual Serial Port Driver)添加了两个虚拟串口,我这里是添加的COM9和COM10;测试效果如下

但是会发现发送HEX数据会出现乱码的现象

出现乱码是因为这里接收的是ASCII,ASCII码表中显示的字符是乱码 ,所以这里需要加一个将字节转换为HEX函数

public static string byteToHexStr(byte[] bytes){string returnStr = "";try{if (bytes != null){for (int i = 0; i < bytes.Length; i++){returnStr += bytes[i].ToString("X2");returnStr += " ";//两个16进制用空格隔开,方便看数据}}return returnStr;}catch (Exception){return returnStr;}}
8.添加ASCII和HEX接收选择控件radioButton

将ASCII控件默认勾选Checked->true

添加获取时间程序

private DateTime current_time = new DateTime();

在serialPort1_DataReceived函数中添加选择ASCII和HEX控件和显示数据接收时间程序

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e){int len = serialPort1.BytesToRead;//获取可以读取的字节数byte[] buff = new byte[len];//创建缓存数据数组serialPort1.Read(buff, 0, len);//把数据读取到buff数组string str = Encoding.Default.GetString(buff);//Byte值根据ASCII码表转为 StringInvoke((new Action(() => //C# 3.0以后代替委托的新方法{current_time = System.DateTime.Now;if (radioButton2.Checked){if (checkBox1.Checked){textBox1.AppendText("[" + current_time.ToString("yyyy-MM-dd HH:mm:ss") + "]收→" + byteToHexStr(buff) + "\r\n");//对话框追加显示数据}else{textBox1.AppendText(byteToHexStr(buff) + "\r\n");}}else if (radioButton1.Checked){if (checkBox1.Checked){textBox1.AppendText("[" + current_time.ToString("yyyy-MM-dd HH:mm:ss") + "]收→" + Encoding.Default.GetString(buff));}else{textBox1.AppendText(Encoding.Default.GetString(buff));}}})));}

测试效果如下图

9.添加清除接收程序

双击清除接收控件

private void button3_Click(object sender, EventArgs e){textBox1.Clear();}

10.添加发送控件

双击发送控件,添加发送函数

private void button2_Click(object sender, EventArgs e){String Str = textBox2.Text.ToString();//获取发送文本框里面的数据try{if (Str.Length > 0){serialPort1.Write(Str);//串口发送数据}}catch (Exception) { }}

测试效果如下图

但是发送HEX还是会出现乱码的现象,现在添加一个将字符串转为HEX程序

private static byte[] strToToHexByte(String hexString){int i;hexString = hexString.Replace(" ", "");//清除空格if ((hexString.Length % 2) != 0)//奇数个{byte[] returnBytes = new byte[(hexString.Length + 1) / 2];try{for (i = 0; i < (hexString.Length - 1) / 2; i++){returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);}returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);}catch{MessageBox.Show("含有非16进制字符", "提示");return null;}return returnBytes;}else{byte[] returnBytes = new byte[(hexString.Length) / 2];try{for (i = 0; i < returnBytes.Length; i++){returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);}}catch{MessageBox.Show("含有非16进制字符", "提示");return null;}return returnBytes;}}

添加选择发送ASCII、HEX、发送新行控件程序

private void button2_Click(object sender, EventArgs e){String Str = textBox2.Text.ToString();//获取发送文本框里面的数据try{if (Str.Length > 0){if (radioButton3.Checked){serialPort1.Write(Str);//串口发送数据textBox1.AppendText("发→" + Str + "\r\n");}else if (radioButton4.Checked){byte[] byt = strToToHexByte(Str);serialPort1.Write(byt, 0, byt.Length);string hexString = BitConverter.ToString(byt).Replace("-", " ");textBox1.AppendText("发→" + hexString + Environment.NewLine);}}}catch (Exception) { }}

测试效果如下图

9.添加串口状态栏显示、接收字节个数和发送字节个数,添加控件label,并修改文本默认内容

定义接收和发送字节个数变量

private long receive_count = 0, send_count = 0;//接收字节数

在接收数据函数加水接收字节个数程序

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e){int len = serialPort1.BytesToRead;//获取可以读取的字节数byte[] buff = new byte[len];//创建缓存数据数组receive_count += len;serialPort1.Read(buff, 0, len);//把数据读取到buff数组Invoke((new Action(() => //C# 3.0以后代替委托的新方法{current_time = System.DateTime.Now;if(radioButton2.Checked){if (checkBox1.Checked){textBox1.AppendText("[" + current_time.ToString("yyyy-MM-dd HH:mm:ss") + "]收→" + byteToHexStr(buff) + "\r\n");//对话框追加显示数据}else{textBox1.AppendText(byteToHexStr(buff) + "\r\n");}}else if(radioButton1.Checked){if(checkBox1.Checked){textBox1.AppendText("[" + current_time.ToString("yyyy-MM-dd HH:mm:ss") + "]收→" + Encoding.Default.GetString(buff));}else{textBox1.AppendText(Encoding.Default.GetString(buff));}}label6.Text = "Rx:" + receive_count.ToString() + "Bytes";})));}

 在发送函数添加发送字节个数显示程序

private void button2_Click(object sender, EventArgs e){String Str = textBox2.Text.ToString();//获取发送文本框里面的数据send_count += Str.Length;try{if (Str.Length > 0){if(radioButton3.Checked){serialPort1.Write(Str);//串口发送数据textBox1.AppendText("发→" + Str + "\r\n");}else if (radioButton4.Checked){byte[] byt = strToToHexByte(Str);serialPort1.Write(byt, 0, byt.Length);string hexString = BitConverter.ToString(byt).Replace("-", " ");textBox1.AppendText("发→" + hexString + Environment.NewLine);}label7.Text = "Tx:" + send_count.ToString() + "Bytes";}}catch (Exception) { }}

测试效果如下图

10.添加定时发送功能(定时控件)

 

双击自动发送控件checkBox3,添加定时函数,首先获取控件numericUpDown1设置的时间数据(单位ms)

private void checkBox3_CheckedChanged(object sender, EventArgs e){if (checkBox3.Checked){if(flag == 1){//自动发送功能选中,开始自动发送numericUpDown1.Enabled = false;     //失能时间选择timer1.Interval = (int)numericUpDown1.Value;     //定时器赋初值timer1.Start();     //启动定时器label8.Text = "串口已打开" + " 自动发送中...";label8.ForeColor = Color.Red; // 设置文本颜色为红色}else{checkBox3.Checked = false;MessageBox.Show("未打开串口!");}}else{//自动发送功能未选中,停止自动发送numericUpDown1.Enabled = true;     //使能时间选择timer1.Stop();     //停止定时器if(flag == 0){label8.Text = "串口未打开";}else{label8.Text = "串口已打开";}      label8.ForeColor = SystemColors.ControlText;}}

双击定时器控件,调用发送数据函数

private void timer1_Tick(object sender, EventArgs e){//定时时间到button2_Click(button2, new EventArgs());    //调用发送按钮回调函数}

测试效果如下图

11.清空按键添加清空接收和发送字节个数
private void button3_Click(object sender, EventArgs e){textBox1.Clear();receive_count = 0;send_count = 0;label6.Text = "Rx:" + receive_count.ToString() + "Bytes";label7.Text = "Tx:" + send_count.ToString() + "Bytes";}

五、开发总结

首先是开发这个工具,会帮助我们对C#上位机开发流程进一步熟悉,其次就是让我们可以深入了解串口通信的原理、常见问题和解决方案,实践数据解析与处理和锻炼问题排查与调试能力等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/879659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CAD中的spline详解

从dxf文件中提取点、直线、圆、弧等元素比较简单&#xff0c;但是Spline的处理比较麻烦。经过一段时间探索总结一下成果。 一、基本公式 1.有理样条曲线 查阅一些资料&#xff0c;认为CAD中使用的Spline 是非均匀有理样条曲线。实测CAD中每个控制点权重都是-1&#xff0c;所以…

物联网行业中小型嵌入式文件系统详解以及使用

一 概述 在嵌入式系统使用过程中&#xff0c;为了方便数据的存储&#xff0c;我们加入了串行的外部Flash(SPI通信)。在使用存储的时候&#xff0c;如需要记录一个字符串“奇迹物联Bloom OS”&#xff0c;我们可以把这些文字转化成 ASCII 码&#xff0c;存储在数组中&#xff0c…

WPF DataGrid 列表中,DataGrid.Columns 列根据不同的值显示不同内容

需求&#xff1a;在WPF DataGrid 控件中&#xff0c;有以下列&#xff0c;绑定了一个LogType&#xff0c;值分别是0,1,2&#xff0c;根据不同的值&#xff0c;显示不同的内容以及背景 <DataGrid ItemsSource"{Binding EventLog}"><DataGrid.Columns><…

Vue路由二(嵌套多级路由、路由query传参、路由命名、路由params传参、props配置、<router-link>的replace属性)

目录 1. 嵌套(多级)路由2. 路由query传参3. 路由命名4. 路由params传参5. props配置6. <router-link>的replace属性 1. 嵌套(多级)路由 pages/Car.vue <template><ul><li>car1</li><li>car2</li><li>car3</li></ul…

postgresql-patroni高可用安装部署

简介 patronietcd,算是目前比较主流的PG高可用搭配了。 patroni都出4.0版本了,一直没时间&#xff0c;断断续续写了好久&#xff0c;最近有人问到&#xff0c;那就当作一个笔记发表吧&#xff0c;自行搭建一个测试库做测试吧。来来回回改了好几遍。文中可能不妨地方没有同步修…

Linux使用Clash,clash-for-linux

文件下载 clash-for-linuxhttps://link.zhihu.com/?targethttps%3A//zywang.lanzn.com/ijE2a1m7h6mb&#xff08;百度和阿里云盘都不支持这个文件分享&#xff09;。 使用须知 - 此项目不提供任何订阅信息&#xff0c;请自行准备Clash订阅地址。 - 运行前请手动更改.env文件…

掌握ChatGPT:高效利用AI助手

2023 年 3 月 15 日&#xff0c;ChatGPT-4 的诞生标志着人类进入了一个全新的 人机协作时代。这个时代就像一个混沌初开的新世界&#xff0c;而 ChatGPT 则是这个新世界里诞生的一个新物种。 这个新物种的心智如同一个四五岁的小孩&#xff0c;在与它频繁互动中&#xff0c;人…

BFS 解决边权为1的最短路问题

文章目录 边权为1的最短路问题1926. 迷宫中离入口最近的出口题目解析算法原理代码实现 433. 最小基因变化题目解析算法原理代码实现 127. 单词接龙题目解析算法原理代码实现 675. 为高尔夫比赛砍树题目解析算法原理代码实现 边权为1的最短路问题 最短路问题&#xff1a; 比如…

Effective C++笔记之二十三:非void函数不写return

一.main函数 Qt Creator查看汇编的步骤如下 上图是g编译器下的汇编 eax就是main()函数的返回值 如果删掉return 0&#xff1b; 可以发现编译器还是把eax的值设为了0&#xff0c;由此可见&#xff0c;即使在main函数中不写return 0&#xff0c;编译器还是会默认添加个return 0。…

R语言统计分析——散点图2(散点图矩阵、高密度散点图)

参考资料&#xff1a;R语言实战【第2版】 1、散点图矩阵 pairs()函数可以创建基础的散点图矩阵。下面代码用于绘制一个散点图矩阵&#xff0c;包含mtcars数据集中的mpg、disp、drat和wt四个变量&#xff1a; pairs(~mpgdispdratwt,datamtcars,main"Basic Scatter Plot M…

太阳能光伏板航拍红外图像缺陷分类数据集

太阳能光伏板航拍红外图像缺陷分类数据集。 数据集共包含11种不同的缺陷分类&#xff0c; 总共20000张图片&#xff0c; 可用来做基于深度学习的缺陷分类 近红外&#xff0c;黑白图像&#xff0c;图示经过可视化处理。 数据集名称 太阳能光伏板缺陷分类数据集&#xff08;Sola…

三相可控整流电路 (三相半波,三相桥式)

目录 1. 三相半波整流电路 2. 三相桥式全控整流电路 三相可控整流电路利用三相交流电源&#xff0c;通过可控硅&#xff08;晶闸管&#xff09;将交流电整流为直流电。主要有两种常见类型&#xff1a;三相半波整流电路和三相桥式全控整流电路。 1. 三相半波整流电路 三相半波…

《沈阳体育学院学报》

《沈阳体育学院学报》创刊于1982年&#xff0c;是由沈阳体育学院主办&#xff0c;面向国内外公开发行的体育类学术期刊&#xff1b;国际标准刊号为ISSN 1004-0560&#xff0c;国内刊号为CN 21-1081/G8&#xff1b;双月刊&#xff0c;单月中旬出版。 《沈阳体育学院学报》是中文…

宝塔部署python项目

宝塔部署-python项目文章浏览阅读559次&#xff0c;点赞11次&#xff0c;收藏9次。在添加项目后&#xff0c;选择项目所在的路径&#xff0c;然后命令行启动主py文件。具体先看项目日志&#xff0c;根据日志在环境管理处下载包。首先下载项目需要的python版本。_宝塔部署python…

LabVIEW提高开发效率技巧----VI服务器和动态调用

VI服务器&#xff08;VI Server&#xff09;和动态调用是LabVIEW中的两个重要功能&#xff0c;可以有效提升程序的灵活性、模块化和可扩展性。通过这两者的结合&#xff0c;开发者可以在运行时动态加载和调用VI&#xff08;虚拟仪器&#xff09;&#xff0c;实现更为复杂的应用…

C++和OpenGL实现3D游戏编程【目录】

欢迎来到zhooyu的专栏。 个人主页&#xff1a;【zhooyu】 文章专栏&#xff1a;【OpenGL实现3D游戏编程】 贝塞尔曲面演示&#xff1a; 贝塞尔曲面演示zhooyu 本专栏内容&#xff1a; 我们从游戏的角度出发&#xff0c;用C去了解一下游戏中的功能都是怎么实现的。这一切还是要…

基于yolov8的无人机检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的无人机检测系统是一项前沿技术&#xff0c;结合了YOLOv8深度学习模型的强大目标检测能力与无人机的灵活性。YOLOv8作为YOLO系列的最新版本&#xff0c;在检测精度和速度上均有显著提升&#xff0c;特别适用于复杂和高动态的场景。 该系统通过捕获实…

论文笔记:基于LLM和多轮学习的漫画零样本角色识别与说话人预测

整理了ACM MM2024 Zero-Shot Character Identification and Speaker Prediction in Comics via Iterative Multimodal Fusion&#xff09;论文的阅读笔记 背景模型框架实现细节 实验数据集实验可视化消融实验 背景 最近读到一篇新文章&#xff0c;主要是做漫画中的零样本角色识…

pikachu下

CSRF(跨站请求伪造) CSRF(get) url变成了这样了&#xff0c;我们就可以新开个页面直接拿url去修改密码 http://pikachu-master/vul/csrf/csrfget/csrf_get_login.php?username1&password2&submitLogin CSRF(post&#xff09; 这里只是请求的方式不同&#xff0c;…

HC-SR04超声波传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 ultrasonic.h文件 ultrasonic.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 HC-SR04超声波传感器是通过发送和接收超声波&#xff0c;利用时间差和声音传播速度…