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,建立虚拟串口之后就可以将他们当成实际物理连接的两个串口进行通信。 之后使用我们之前给出的通信模板,建立一个稍微规矩一点的界面。 界面建立 其中…...

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

软媒市场新探索:软文媒体自助发布,开启自助发稿新篇章
在繁华喧嚣的软媒市场中,每一个声音都在竭力呼喊,每一个品牌都在奋力展现。而软文,作为一种温柔而坚韧的营销力量,正逐渐崭露头角。特别是软文媒体自助发布平台的出现,更是为企业提供了一个全新的、高效的自助发稿渠道。 软媒市场自助发布平台,正如其名,是一个让企业能够自主发…...
【Kubernetes】常见面试题汇总(二十七)
目录 77.假设公司希望在不同的云基础架构上运行各种工作负载,从裸机到公共云。公司将如何在不同界面的存在下实现这一目标? 78.什么是 Google 容器引擎? 特别说明: 题目 1-68 属于【Kubernetes】的常规概念题。 题目 69-1…...

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

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

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

Linux学习笔记8 理解Ubuntu网络管理,做自己网络的主人
本文讲解了Ubuntu下网络由什么管理,介绍了临时ip和路由的设置方法,介绍了静态持久化网络配置的方法以及各网络管理软件之间的关系。 来看看Ubuntu网络管理。 序言 原本学习ubuntu网络管理就是为了检查nginx安装过程中使用wget获取压缩包为什么解析不出…...
理解线程的三大特性:原子性、可见性和有序性
在并发编程中,保护线程安全是一个重要课题。要实现线程安全,我们必须理解并掌握三个核心概念:原子性、可见性和有序性。下面将详细介绍这三个特性及其解决方案。 一、原子性 原子性是指一个操作要么全部完成,要么完全不执行。在多…...
英特尔®以太网网络适配器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 服务器,通常与 SSH 服务、网络连接、主机防火墙设置问题有关。以下是排查并解决这个问题的步骤: 1. 确保 SSH 服务正在运行 在 Ubuntu 上,SSH 服务必须启动才能连接。如果你有虚拟机或物理机的访问权限&…...

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

数据结构之线性表——LeetCode:67. 二进制求和,27. 移除元素,26. 删除有序数组中的重复项
67. 二进制求和 题目描述 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 运行代码(javaC) class Solution {public String addBinary(String a, String b) {StringBuilder ansnew StringBuilder();int ca0;for(i…...
SQL_HAVING小例子
例一 求众数的sql语句1: select income,count(*) as cnt from graduates group by income having count(*) > all(select count(*) from graduates group by income);这段SQL语句的作用是从一个名为graduates的表中找出income(收入)字段…...
Avalonia第三方UI库Semi.Avalonia用法详解
文章目录 简介一、安装Semi Avalonia二、基本项目结构三、使用基本控件1 按钮控件2 输入框控件3 选择框控件四、自定义样式和主题五、使用布局控件六、数据绑定七、事件处理八、使用图标和其他资源九、响应式设计十、交互与导航总结简介 Semi是一个基于Avalonia的UI库,旨在提供…...
宠物智能化听诊器的健康管理!
智能听诊器在宠物健康领域的应用正逐渐普及,它通过创新技术为宠物医疗保健带来革新。以下是智能听诊器如何影响宠物健康管理的概述: 数据分析与机器学习 智能听诊器利用深度学习算法,识别宠物心脏和呼吸模式,提供健康分析和诊断建…...
MyBatis-Plus 实体类注解
MyBatis-Plus 实体类注解详解 MyBatis-Plus 是 MyBatis 的增强版,旨在简化开发者的 CRUD 操作。它通过丰富的特性和注解,简化了数据库与 Java 实体类之间的映射。MyBatis-Plus 提供了一系列的实体类注解,帮助开发者更轻松地映射数据库表、字…...

如何写一个自动化Linux脚本去进行等保测试--引言
#我的师兄喜欢给我的休闲实习生活加活,说是让我在实习期间写一个自动化脚本去进行等保测试。呵呵哒。 怎么办呢,师兄的指令得完成,师兄说让我使用Python完成任务。 设想如下: 1、将Linux指令嵌入到python脚本中 2、调试跑通 …...
美团测开OC!
大家好,我是洋子,最近测试社区里面的一个25届同学参加秋招,已经拿到美团测开offer,今天来分享一下他的求职经历,文末附面经 他求职目前的进展如下: 互联网大厂:字节,阿里ÿ…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...