当前位置: 首页 > news >正文

C#开发记录如何建立虚拟串口,进行串口通信,以及通信模板

记录时间;2024年4月

记录如何开启虚拟串口以及进行基础串口通信。

建立虚拟串口

使用的软件是vspd,建立虚拟串口之后就可以将他们当成实际物理连接的两个串口进行通信。

之后使用我们之前给出的通信模板,建立一个稍微规矩一点的界面。

界面建立

 

 其中添加对用户输入的检查。

配合之前打开串口的逻辑就可以开始串口应用的调试和开发了。

代码

  public partial class Form1 : Form{//串口参数和串口工具类public System.IO.Ports.SerialPort _serialPort = new System.IO.Ports.SerialPort();string[] baud = { "43000", "56000", "57600", "115200", "128000", "230400", "256000", "460800" };private void displaytext(object sender, EventArgs e){string str = _serialPort.ReadExisting();rtxreceive.AppendText(str);}//串口接收事件private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){//串口接收事件try{//串口接收数据//if(serialPort1.IsOpen){this.Invoke(new EventHandler(displaytext));}}catch (Exception ex){//捕获到异常,创建一个新的对象,之前的不可以再用_serialPort = new System.IO.Ports.SerialPort();//刷新COM口选项comboBox1.Items.Clear();comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());//响铃并显示异常给用户System.Media.SystemSounds.Beep.Play();button4.Text = "打开串口";MessageBox.Show(ex.Message);hintrtx.Text += "\n串口接收失败";comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;}}public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//检测try{string[] ports = SerialPort.GetPortNames();if (ports.Length == 0){MessageBox.Show("没有找到串口");hintrtx.Text += "没有找到串口";return;}comboBox1.Items.Clear();comboBox1.Items.AddRange(ports);comboBox1.SelectedIndex = 0;comboBox2.SelectedIndex = 0;comboBox3.SelectedIndex = 0;comboBox4.SelectedIndex = 0;comboBox5.SelectedIndex = 0;//检测到串口后,使能串口参数设置comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;}catch (Exception ex){MessageBox.Show(ex.Message);}}private void Form1_Load(object sender, EventArgs e){//界面初始化int i;for (i = 300; i <= 38400; i = i * 2){comboBox2.Items.Add(i.ToString());  //添加波特率列表}comboBox2.Items.AddRange(baud);comboBox1.Enabled = false;comboBox2.Enabled = false;comboBox3.Enabled = false;comboBox4.Enabled = false;comboBox5.Enabled = false;hintrtx.Text += "欢迎使用";}private void button4_Click(object sender, EventArgs e){//开启串口try{if (_serialPort.IsOpen){//如果串口已经处于打开状态,则关闭串口_serialPort.Close();button4.Text = "打开串口";hintrtx.Text += "\n串口已经关闭";//关闭串口后,使能串口参数设置comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;//取消串口接收事件注册_serialPort.DataReceived -= new SerialDataReceivedEventHandler(_serialPort_DataReceived);return;}else{//串口已经处于关闭状态,则设置好串口属性后打开comboBox1.Enabled = false;comboBox2.Enabled = false;comboBox3.Enabled = false;comboBox4.Enabled = false;comboBox5.Enabled = false;_serialPort.PortName = comboBox1.Text;_serialPort.BaudRate = Convert.ToInt32(comboBox2.Text);_serialPort.DataBits = Convert.ToInt16(comboBox3.Text);_serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox4.Text);if (comboBox5.Text.Equals("1"))_serialPort.StopBits = System.IO.Ports.StopBits.One;else if (comboBox5.Text.Equals("1.5"))_serialPort.StopBits = System.IO.Ports.StopBits.OnePointFive;else if (comboBox5.Text.Equals("2"))_serialPort.StopBits = System.IO.Ports.StopBits.Two;//_serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBox5.Text);_serialPort.Open();//注册串口接收事件_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);button4.Text = "关闭串口";hintrtx.Text += "\n串口已经打开";}}catch (Exception ex){MessageBox.Show(ex.Message);hintrtx.Text += "\n串口打开失败";}}private void button3_Click(object sender, EventArgs e){//try{//首先判断串口是否开启if (_serialPort.IsOpen){//串口处于开启状态,将发送区文本发送_serialPort.Write(rtx_send.Text);}}catch (Exception ex){//捕获到异常,创建一个新的对象,之前的不可以再用_serialPort = new System.IO.Ports.SerialPort();//刷新COM口选项comboBox1.Items.Clear();comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());//响铃并显示异常给用户System.Media.SystemSounds.Beep.Play();button4.Text = "打开串口";MessageBox.Show(ex.Message);hintrtx.Text += "\n串口发送失败";comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;}}}

代码解释:

扫描串口:

我们使用serialport类进行串口的扫描,能够给到一个串口名称的列表。展示的中间修改页面元素的可用性,允许用户修改串口配置。

private void button1_Click(object sender, EventArgs e){//检测try{string[] ports = SerialPort.GetPortNames();if (ports.Length == 0){MessageBox.Show("没有找到串口");hintrtx.Text += "没有找到串口";return;}comboBox1.Items.Clear();comboBox1.Items.AddRange(ports);comboBox1.SelectedIndex = 0;comboBox2.SelectedIndex = 0;comboBox3.SelectedIndex = 0;comboBox4.SelectedIndex = 0;comboBox5.SelectedIndex = 0;//检测到串口后,使能串口参数设置comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;}catch (Exception ex){MessageBox.Show(ex.Message);}}

打开/关闭串口

逻辑非常简单,判断是否已经打开,如果已经打开就关闭。

打开的逻辑是:

读取用户设置之前先锁定配置,防止调试中用户修改。

接着就是打开串口,注册串口接收事件用于执行接收指定的逻辑。

关闭串口更加简单,重新给予用户修改配置的机会,同时关闭串口,取消事件的注册。

事件机制是串口收发的核心:

C#笔记4 详细解释事件及其原型、匿名方法和委托的关系-CSDN博客

c#笔记5 详解事件的内置类型EventHandler、windows事件在winform中的运用_c# eventhandler用法-CSDN博客

 private void button4_Click(object sender, EventArgs e){//开启串口try{if (_serialPort.IsOpen){//如果串口已经处于打开状态,则关闭串口_serialPort.Close();button4.Text = "打开串口";hintrtx.Text += "\n串口已经关闭";//关闭串口后,使能串口参数设置comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;//取消串口接收事件注册_serialPort.DataReceived -= new SerialDataReceivedEventHandler(_serialPort_DataReceived);return;}else{//串口已经处于关闭状态,则设置好串口属性后打开comboBox1.Enabled = false;comboBox2.Enabled = false;comboBox3.Enabled = false;comboBox4.Enabled = false;comboBox5.Enabled = false;_serialPort.PortName = comboBox1.Text;_serialPort.BaudRate = Convert.ToInt32(comboBox2.Text);_serialPort.DataBits = Convert.ToInt16(comboBox3.Text);_serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox4.Text);if (comboBox5.Text.Equals("1"))_serialPort.StopBits = System.IO.Ports.StopBits.One;else if (comboBox5.Text.Equals("1.5"))_serialPort.StopBits = System.IO.Ports.StopBits.OnePointFive;else if (comboBox5.Text.Equals("2"))_serialPort.StopBits = System.IO.Ports.StopBits.Two;//_serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBox5.Text);_serialPort.Open();//注册串口接收事件_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);button4.Text = "关闭串口";hintrtx.Text += "\n串口已经打开";}}catch (Exception ex){MessageBox.Show(ex.Message);hintrtx.Text += "\n串口打开失败";}}

串口接收事件:

这里主要是做了一个串口的错误处理和调用界面元素显示的方法。从不是创建这个元素的线程调用改变元素的方法需要使用invoke。

//串口接收事件private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){//串口接收事件try{//串口接收数据//if(serialPort1.IsOpen){this.Invoke(new EventHandler(displaytext));}}catch (Exception ex){//捕获到异常,创建一个新的对象,之前的不可以再用_serialPort = new System.IO.Ports.SerialPort();//刷新COM口选项comboBox1.Items.Clear();comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());//响铃并显示异常给用户System.Media.SystemSounds.Beep.Play();button4.Text = "打开串口";MessageBox.Show(ex.Message);hintrtx.Text += "\n串口接收失败";comboBox1.Enabled = true;comboBox2.Enabled = true;comboBox3.Enabled = true;comboBox4.Enabled = true;comboBox5.Enabled = true;}}

display方法 

这里就可以写你自己的方法了。串口的数据经过怎么处理展示到哪里。 

private void displaytext(object sender, EventArgs e){string str = _serialPort.ReadExisting();rtxreceive.AppendText(str);}

相关文章:

C#开发记录如何建立虚拟串口,进行串口通信,以及通信模板

记录时间;2024年4月 记录如何开启虚拟串口以及进行基础串口通信。 建立虚拟串口 使用的软件是vspd&#xff0c;建立虚拟串口之后就可以将他们当成实际物理连接的两个串口进行通信。 之后使用我们之前给出的通信模板&#xff0c;建立一个稍微规矩一点的界面。 界面建立 其中…...

电源设计的艺术:从底层逻辑到工程实践

在电子工程的世界里&#xff0c;电源设计是核心中的核心。它不仅是电子设备的能量源泉&#xff0c;更是整个系统稳定运行的基石。随着科技的不断进步&#xff0c;电源设计的要求也越来越高&#xff0c;从效率、稳定性到体积、成本&#xff0c;每一个维度都是工程师们不断追求的…...

软媒市场新探索:软文媒体自助发布,开启自助发稿新篇章

在繁华喧嚣的软媒市场中,每一个声音都在竭力呼喊,每一个品牌都在奋力展现。而软文,作为一种温柔而坚韧的营销力量,正逐渐崭露头角。特别是软文媒体自助发布平台的出现,更是为企业提供了一个全新的、高效的自助发稿渠道。 软媒市场自助发布平台,正如其名,是一个让企业能够自主发…...

【Kubernetes】常见面试题汇总(二十七)

目录 77.假设公司希望在不同的云基础架构上运行各种工作负载&#xff0c;从裸机到公共云。公司将如何在不同界面的存在下实现这一目标&#xff1f; 78.什么是 Google 容器引擎&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题。 题目 69-1…...

基于单片机巡迹避障智能小车系统

文章目录 前言资料获取设计介绍设计程序具体实现截图设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…...

Python163邮箱发送:提升发送效率的技巧?

python163邮箱发送邮件教程&#xff1f;python怎么使用163邮箱&#xff1f; Python163邮箱发送作为一种自动化邮件发送方式&#xff0c;越来越受到开发者和企业的青睐。AokSend将探讨如何通过多种技巧提升Python163邮箱发送的效率&#xff0c;从而更好地满足用户需求。 Pytho…...

springboot中的异步任务

在springboot项目中可以通过EnableAsyncAsync的方式简化异步操作&#xff0c;下文使用springboot:3.2.1 源码分析 若一个bean中的公共方法上标注了Async&#xff0c;在系统启动时&#xff0c;会给这个类创建一个代理对象&#xff0c;并将该代理对象作为bean注册到spring容器中 …...

Linux学习笔记8 理解Ubuntu网络管理,做自己网络的主人

本文讲解了Ubuntu下网络由什么管理&#xff0c;介绍了临时ip和路由的设置方法&#xff0c;介绍了静态持久化网络配置的方法以及各网络管理软件之间的关系。 来看看Ubuntu网络管理。 序言 原本学习ubuntu网络管理就是为了检查nginx安装过程中使用wget获取压缩包为什么解析不出…...

理解线程的三大特性:原子性、可见性和有序性

在并发编程中&#xff0c;保护线程安全是一个重要课题。要实现线程安全&#xff0c;我们必须理解并掌握三个核心概念&#xff1a;原子性、可见性和有序性。下面将详细介绍这三个特性及其解决方案。 一、原子性 原子性是指一个操作要么全部完成&#xff0c;要么完全不执行。在多…...

英特尔®以太网网络适配器E810-CQDA1 / E810-CQDA2 网卡 规格书 e810 网卡 规格书 Intel100G E810 网卡 白皮书

英特尔以太网800系列网络适配器 英特尔以太网网络适配器E810-CQDA1 / CQDA2 在10到100Gbps的以太网速度下实现高效的工作负载优化性能 关键特性 •单、双端口QSFP28 •应用设备队列(ADQ) •PCI Express (PCIe) 4.0 x16 •动态设备个性化(DDP) •以太网端口配置工具(EPC…...

好用的idea方法分隔符插件

好用的idea方法分隔符插件...

通过 Xshell 无法连接到 Ubuntu

无法通过 Xshell 连接到 Ubuntu 服务器&#xff0c;通常与 SSH 服务、网络连接、主机防火墙设置问题有关。以下是排查并解决这个问题的步骤&#xff1a; 1. 确保 SSH 服务正在运行 在 Ubuntu 上&#xff0c;SSH 服务必须启动才能连接。如果你有虚拟机或物理机的访问权限&…...

Java面试篇基础部分-Synchronized关键字详解

Synchronized关键字用于对Java对象、方法、代码块等提供线程安全操作。Synchronized属于独占式的悲观锁机制,同时也是可重入锁。我们在使用Synchronized关键字的时候,可以保证同一时刻只有一个线程对该对象进行访问;也就是说它在同一个JVM中是线程安全的。   Java中的每个…...

数据结构之线性表——LeetCode:67. 二进制求和,27. 移除元素,26. 删除有序数组中的重复项

67. 二进制求和 题目描述 67. 二进制求和 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 运行代码&#xff08;javaC) class Solution {public String addBinary(String a, String b) {StringBuilder ansnew StringBuilder();int ca0;for(i…...

SQL_HAVING小例子

例一 求众数的sql语句1&#xff1a; select income,count(*) as cnt from graduates group by income having count(*) > all(select count(*) from graduates group by income);这段SQL语句的作用是从一个名为graduates的表中找出income&#xff08;收入&#xff09;字段…...

Avalonia第三方UI库Semi.Avalonia用法详解

文章目录 简介一、安装Semi Avalonia二、基本项目结构三、使用基本控件1 按钮控件2 输入框控件3 选择框控件四、自定义样式和主题五、使用布局控件六、数据绑定七、事件处理八、使用图标和其他资源九、响应式设计十、交互与导航总结简介 Semi是一个基于Avalonia的UI库,旨在提供…...

宠物智能化听诊器的健康管理!

智能听诊器在宠物健康领域的应用正逐渐普及&#xff0c;它通过创新技术为宠物医疗保健带来革新。以下是智能听诊器如何影响宠物健康管理的概述&#xff1a; 数据分析与机器学习 智能听诊器利用深度学习算法&#xff0c;识别宠物心脏和呼吸模式&#xff0c;提供健康分析和诊断建…...

MyBatis-Plus 实体类注解

MyBatis-Plus 实体类注解详解 MyBatis-Plus 是 MyBatis 的增强版&#xff0c;旨在简化开发者的 CRUD 操作。它通过丰富的特性和注解&#xff0c;简化了数据库与 Java 实体类之间的映射。MyBatis-Plus 提供了一系列的实体类注解&#xff0c;帮助开发者更轻松地映射数据库表、字…...

如何写一个自动化Linux脚本去进行等保测试--引言

#我的师兄喜欢给我的休闲实习生活加活&#xff0c;说是让我在实习期间写一个自动化脚本去进行等保测试。呵呵哒。 怎么办呢&#xff0c;师兄的指令得完成&#xff0c;师兄说让我使用Python完成任务。 设想如下&#xff1a; 1、将Linux指令嵌入到python脚本中 2、调试跑通 …...

美团测开OC!

大家好&#xff0c;我是洋子&#xff0c;最近测试社区里面的一个25届同学参加秋招&#xff0c;已经拿到美团测开offer&#xff0c;今天来分享一下他的求职经历&#xff0c;文末附面经 他求职目前的进展如下&#xff1a; 互联网大厂&#xff1a;字节&#xff0c;阿里&#xff…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...