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

news2024/9/21 11:58:40

记录时间;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);
        }

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

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

相关文章

三种不同交联方式的水凝胶:有啥特性?用途有哪些?

大家好&#xff0c;今天我们来了解一篇水凝胶文章——《Dual-Temperature/pH-Sensitive Hydrogels with Excellent Strength and Toughness Crosslinked Using Three Crosslinking Methods》发表于《Gels》。水凝胶在生物医药领域应用广泛&#xff0c;它能存储药物、控制药物释…

全志A133 android10 适配EC20 4G模块

一&#xff0c;移植适配 1. 驱动移植 代码路径&#xff1a;longan/kernel/linux-4.9/drivers/usb/serial/option.c diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9f96dd2..2f25466 100644 --- a/drivers/usb/serial/option.cb/drivers/us…

Python和C++及R相关系数数学统计学可视化和神经模型及评估指标

&#x1f3af;要点 较少统计样本显著性评估和变量关系梳理功能磁共振成像一致性分析检测非单调关联性结构随机变量动力学相关性热图和矩阵图基因疫苗非线性变量相关性 Python相关矩阵 相关矩阵 n n n 个随机变量 X 1 , … , X n X_1, \ldots, X_n X1​,…,Xn​ 的相关矩阵…

【Text2SQL】PET-SQL:在Spider基准测试中取得了SOTA

解读&#xff1a;PET-SQL: A Prompt-enhanced Two-stage Text-to-SQL Framework with Cross-consistency 这篇论文介绍了一个名为 PET-SQL 的文本到 SQL&#xff08;Text-to-SQL&#xff09;框架&#xff0c;旨在通过增强提示&#xff08;prompt&#xff09;和利用不同大型语言…

【计算机网络篇】电路交换,报文交换,分组交换

本文主要介绍计算机网络中的电路交换&#xff0c;报文交换&#xff0c;分组交换&#xff0c;文中的内容是我认为的重点内容&#xff0c;并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 目录 &#x1f3af;一.划分…

科研绘图系列:R语言误差连线图(errobar linechart)

文章目录 介绍加载R包导入数据数据预处理画图系统信息介绍 误差连线图是一种在数据可视化中常用的图表,它通过在数据点处添加线段(误差线)来表示数据的变异性或不确定性。这些误差线可以基于不同的统计度量,如标准差(Standard Deviation)、标准误差(Standard Error)或…

Redis 执行 Lua,能保证原子性吗?

前言 小张目前在使用分布式锁 Redisson 实现一个需求。那我在想我能否自己手撸一个能用于分布式环境的锁呢&#xff1f;于是果然尝试。 历经一天后&#xff0c;小张手撸的锁终于写出来了&#xff0c;再次给各位看看&#xff0c;看给位有没有什么优化的建议&#xff1a; // 加…

任务管理与守护进程【Linux】

文章目录 进程组前台进程&后台进程守护进程daemon 进程组 组长是多个进程的第一个&#xff0c;组长进程的标识是&#xff0c;其进程组ID等于其进程ID 前台进程&后台进程 前台进程&#xff1a;能获取键盘输入&#xff0c;即拥有键盘文件 后台进程&#xff1a;不能获取…

淘宝商品评论电商API接口全方位解析

随着电子商务的蓬勃发展&#xff0c;API接口在电商领域扮演着越来越重要的角色。淘宝作为国内最大的电商平台之一&#xff0c;其商品评论电商API接口为开发者提供了获取商品评论信息、进行数据分析等重要功能。本文将对淘宝商品评论电商API接口进行全方位解析&#xff0c;帮助开…

商品出库单打印怎么设置打印格式 佳易王商品批发出库单打印票据管理系统操作教程

一、前言 商品出库单打印怎么设置打印格式 佳易王商品批发出库单打印票据管理系统操作教程 佳易王商品出库打印纸张建议使用 241*140 &#xff0c;可根据需要更改或定制 二、软件程序图文说明 1、软件已经内置数据库&#xff0c;解压即可。 2、出库单可以打印两联或三联单或…

Android Kotlin 中的 `groupBy` 方法详解

在 Kotlin 中&#xff0c;groupBy 是一个非常有用的集合操作函数。我们可以使用它按照某个标准&#xff0c;将集合中的元素分组&#xff0c;形成一个 Map&#xff0c;其中 key 是我们分组的标准&#xff0c;value 是符合这个标准的元素列表。本文将通过几个实际例子&#xff0c…

微服务架构中的负载均衡与服务注册中心(Nacos)

1. 负载均衡&#xff1a;解决实际业务问题 1.1 业务场景思考 想象一个电子商务平台的微服务架构。我们有一个订单服务和多个用户服务实例。当订单服务需要调用用户服务时&#xff0c;它如何选择具体调用哪一台用户服务器&#xff1f;这就是负载均衡要解决的核心问题。 1.2 常…

【CAPL实战】system variables系统变量的基础与应用

基础 在CANoe系统中&#xff0c;变量可以用来对内部参数进行建模。系统变量既不描述节点的外部输入/输出信号&#xff0c;也不用于真实节点间的信号通信。系统变量用于开发和测试&#xff0c;提供改变和分析内部变量和参数的机会。通过还可以表示未在数据库中定义的IO信号。&a…

MUR6060PT-ASEMI高压快恢复二极管MUR6060PT

编辑&#xff1a;ll MUR6060PT-ASEMI高压快恢复二极管MUR6060PT 型号&#xff1a;MUR6060PT 品牌&#xff1a;ASEMI 封装&#xff1a;TO-247 安装方式&#xff1a;插件 批号&#xff1a;最新 恢复时间&#xff1a;35ns 最大平均正向电流&#xff08;IF&#xff09;&…

构建高效心理辅导平台:Spring Boot实践

1绪 论 1.1研究背景 随着计算机和网络技术的不断发展&#xff0c;计算机网络已经逐渐深入人们的生活&#xff0c;网络已经能够覆盖我们生活的每一个角落&#xff0c;给用户的网上交流和学习提供了巨大的方便。 当今社会处在一个高速发展的信息时代&#xff0c;计算机网络的发展…

昇思量子计算系列教程-Grover搜索算法

基于MindSpore Quantum的Grover搜索算法 概述 如果你听过量子计算&#xff0c;那么你一定听说过Grover搜索算法。1996年&#xff0c;Lov Grover [1] 提出了Grover搜索算法&#xff0c;它是一种利用量子状态的叠加性进行并行计算并实现加速的算法。Grover搜索算法被公认为是继…

快手店铺多开甜羊浏览器

甜羊浏览器是一款专为电商从业者设计的专业浏览器&#xff0c;其最大的特色在于支持多开功能和具备智能的自动回复系统&#xff0c;尤其适合快手店铺等电商平台的多店铺管理及自动化客服需求。 **多开功能**&#xff1a;甜羊浏览器的多开功能允许用户在同一界面上登录和操作多…

电脑ip地址怎么换地区:操作步骤与利弊分析

在当今全球化的信息时代&#xff0c;人们经常需要访问不同地区的网络资源。然而&#xff0c;由于地理位置的限制&#xff0c;某些内容或服务可能只对特定地区的用户开放。这时&#xff0c;更换电脑IP地址的地区就成为了一个实用的解决方案。本文将详细介绍两种更换电脑IP地址地…

DataGrip在Windows和MacOS平台上的快捷键

0. 背景信息 No.说明1测试DataGrip版本号 : 2024.2.2 1. Windows下快捷键 2. MacOS下快捷键

麒麟银河桌面版,成功安装cuda12.6,mysql

一、 要卸载并禁用 nouveau 驱动程序&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确认 nouveau 驱动的当前状态&#xff1a; 首先&#xff0c;你可以使用以下命令查看 nouveau 驱动是否正在运行&#xff1a; lsmod | grep nouveau如果有输出&#xff0c;说明 nouveau …