VB.NET串口通信例子--我的回忆录

2023-05-16

这是我3年前的一个例子,最近翻出来回忆一下。

串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口,现在配电脑好像只有一个。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。串口通信在工控领域用途很广。

串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。

典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配:
a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。
b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

串口通信还有一个参数是单工、半双工和双工。

如果在通信过程的任意时刻,信息只能由一方A传到另一方B,则称为单工。

如果在任意时刻,信息既可由A传到B,又能由B传A,但只能由一个方向上的传输存在,称为半双工传输。

如果在任意时刻,线路上存在A到B和B到A的双向信号传输,则称为全双工。

电话线就是二线全双工信道。 由于采用了回波抵消技术,双向的传输信号不致混淆不清。双工信道有时也将收、发信道分开,采用分离的线路或频带传输相反方向的信号,如回线传输。

在调试时可以用串口助手和windows的超级终端,不要带电插拔串口,容易烧毁。

在VB.NET中提供了IO.Ports类,是我们的编程变得很简单,下面是我的例子:

Form1.vb

Imports System.IO.Ports

Public Class Form1

    Dim WithEvents RS232 As SerialPort
    Delegate Sub SetTextCallback(ByVal InputString As String)       '声明一个代理

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each sp As String In SerialPort.GetPortNames()
            cmbCom.Items.Add(sp)
        Next
        cmbCom.Sorted = True
        cmbCom.SelectedIndex = 0
    End Sub

    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
        Dim mBaudRate As Integer
        Dim mParity As IO.Ports.Parity
        Dim mDataBit As Integer
        Dim mStopBit As IO.Ports.StopBits
        Dim mPortName As String

        mPortName = cmbCom.SelectedItem.ToString
        mBaudRate = 9600
        mParity = Parity.None
        mDataBit = 8
        mStopBit = StopBits.One

        RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopBit)

        If Not RS232.IsOpen Then
            RS232.Open()
            btnSend.Enabled = True
            RS232.ReceivedBytesThreshold = 1        '设置引发事件的门限值
        Else
            MsgBox("通讯端口打开错误!", MsgBoxStyle.Critical)
        End If
    End Sub


    Private Sub RS232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles RS232.DataReceived
        Dim InByte() As Byte, ReadCount As Integer, strRead As String
        If RS232.BytesToRead <= 0 Then Exit Sub
        ReDim InByte(RS232.BytesToRead - 1)
        ReadCount = RS232.Read(InByte, 0, RS232.BytesToRead)
        strRead = ""
        If ReadCount = 0 Then
            Exit Sub
        Else
            For Each bData As Byte In InByte
                strRead += bData.ToString & vbCrLf     '若有数据则加到接收文本框
                DisplayText(strRead)
            Next
        End If


    End Sub
    '*************************************************
    '代理子程序
    '处理上述通信端口的接收事件
    '由于欲将数据显示到接收文本框中,因此必须检查
    '是否由另外得Thread所调用的,若是,则必须先
    '建立代理对象
    'Invoke用于在拥有控件基础窗口控制代码的线程上
    '运行代理
    '*************************************************
    Private Sub DisplayText(ByVal comData As String)
        '如果调用txtReceive的另外的线程,返回true
        If Me.txtReceive.InvokeRequired Then
            '利用代理类型建立对象,并指定代理的函数
            Dim d As New SetTextCallback(AddressOf DisplayText)
            Me.Invoke(d, New Object() {comData})    '以指定的自变量列表调用函数
        Else '相同的线程
            'showstring(comData)     '将收到的数据填入接收文本框中
            Me.txtReceive.Text += comData
        End If
    End Sub

    Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
        If RS232 Is Nothing OrElse Not RS232.IsOpen Then   '尚未打开
            MsgBox("通讯端口尚未打开", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
        Else
            RS232.Close()
            btnStart.Enabled = False
            btnClose.Enabled = False
            RS232 = Nothing
        End If
    End Sub

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        If Not RS232 Is Nothing Then
            If RS232.IsOpen Then RS232.Close()
        End If
        End
    End Sub

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        Dim bDataOut(0) As Byte
        Try
            bDataOut(0) = CType(Me.txtSend.Text, Byte)        '将类型转换为字节
            RS232.Write(bDataOut, 0, 1)
        Catch ex As Exception
            MessageBox.Show("输入数值错误:" + ex.ToString, "错误通知:", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

    Private Sub cmbCom_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCom.KeyPress
        e.KeyChar = ChrW(0)             '禁止用户在其中输入任何文字
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.Hide()
        Form2.Show()
    End Sub
End Class
Form2.vb

'**************************************************************
'时间:2008-11-08
'作者:lincyang
'实际应用中,串行通信的数据可能一次发送大量的数据,
'发送之前就必须将数据先编码,
'将其编成我们需要的字节数组数据,
'才能将这些数据以字节的方式发送出去
'目前操作系统使用的字符数据是Unicode:所有的字符均使用
'两个字节来表示一个字符
'**************************************************************

Imports System.IO.Ports
Imports System.Text
Public Class Form2
    Dim RS232 As SerialPort
    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each sp As String In SerialPort.GetPortNames()
            cmbCom.Items.Add(sp)
        Next
        cmbCom.Sorted = True
        cmbCom.SelectedIndex = 0
    End Sub

    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
        Dim mBaudRate As Integer
        Dim mParity As IO.Ports.Parity
        Dim mDataBit As Integer
        Dim mStopBit As IO.Ports.StopBits
        Dim mPortName As String

        mPortName = cmbCom.SelectedItem.ToString
        mBaudRate = 9600
        mParity = Parity.None
        mDataBit = 8
        mStopBit = StopBits.One

        RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopBit)

        If Not RS232.IsOpen Then
            RS232.Open()
            btnSend.Enabled = True
            Timer1.Interval = 100
            Timer1.Enabled = True
        Else
            MsgBox("通讯端口打开错误!", MsgBoxStyle.Critical)
        End If
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim InByte() As Byte, ReadCount As Integer
        If RS232.BytesToRead <= 0 Then Exit Sub
        ReDim InByte(RS232.BytesToRead - 1)
        ReadCount = RS232.Read(InByte, 0, RS232.BytesToRead)

        If ReadCount = 0 Then
            Exit Sub
        Else
            For Each bData As Byte In InByte
                Me.txtReceive.Text += bData.ToString & vbCrLf     '若有数据则加到接收文本框

            Next
        End If
    End Sub

    Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
        If RS232 Is Nothing OrElse Not RS232.IsOpen Then   '尚未打开
            MsgBox("通讯端口尚未打开", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
        Else
            RS232.Close()
            btnStart.Enabled = False
            btnClose.Enabled = False
            Timer1.Enabled = False
            RS232 = Nothing
        End If
    End Sub

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        Dim bDataOut() As Byte, Buf As String
        Dim iSentCount As Integer
        Dim Encode1 As Encoding = Encoding.ASCII         '声明编码对象,使用ASCII

        Try
            Buf = txtSend.Text.Trim()
            bDataOut = Encode1.GetBytes(Buf)      '将字符串转换为字节数组
            iSentCount = bDataOut.GetLength(0)     '发送总字节数
            '显示出总字节数
            lblSentCount.Text = "总传输量:" & iSentCount.ToString & "字节"
            RS232.Write(bDataOut, 0, iSentCount)
        Catch ex As Exception
            MessageBox.Show("输入数值错误:" + ex.ToString, "错误通知", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        If Not RS232 Is Nothing Then
            If RS232.IsOpen Then RS232.Close()
        End If
        End
    End Sub

    Private Sub cmbCom_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCom.KeyPress
        e.KeyChar = ChrW(0)             '禁止用户在其中输入任何文字
    End Sub
End Class

开发环境是VB2008,源码下载 猛击这里!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VB.NET串口通信例子--我的回忆录 的相关文章

  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • Windows 窗体中的标准 Windows 菜单栏

    我注意到添加了一个MenuStrip 来自工具箱 我的表单设计不会产生像许多本机 Windows 应用程序中那样的菜单栏 相反 我得到了一个像 Visual Studio 自己的菜单栏 没有任何样式设置MenuStrip似乎模仿了更常见的本
  • 页面中某些超链接控件上的本地化资源未发生变化

    上面是正在开发中的网站的屏幕截图 我们有一个 DropdownList 控件 并在其 SelectedIndexChanged 上进行回发 然后我们更改站点区域性 然后加载相应的资源文件 DropDownList ASP NET 代码
  • WPF画布性能-children.add调用多次

    我在长画布上绘制了很多线条 想想条形图 并对其性能进行了相当好的调整 使用低级几何类并冻结它们等 这极大地提高了性能 但仍然需要几秒钟将几千个项目加载到画布中 我对应用程序进行了性能分析 看起来每次调用都花费了很大一部分时间canvas c
  • 在 C# 中的同一套接字上发送+接收数据

    我试图使用套接字 System Net Socket 甚至尝试过 TcpListener Client Etc 来在等待或已经发送数据时侦听数据 我做了以下事情 public byte bytesIn public byte bytesOu
  • LINQ to Entities 区分大小写的比较

    这不是 LINQ to Entities 中区分大小写的比较 Thingies First t gt t Name ThingamaBob 如何使用 LINQ to Entities 实现区分大小写的比较 那是因为你正在使用LINQ 实体最
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • SqlCommand.Dispose() 在 SqlTransaction.Commit() 之前?

    在提交事务之前处理分配给事务的命令是否有效 我自己测试了以下代码 它似乎工作得很好 但这是一个相当小的例子 所以我正在寻找是否有人确实知道的确认 internal static void TestTransaction try Progra
  • WCF服务健康状况监控

    我刚刚实现了 WCF 服务 目前正在研究服务监控选项 我们的服务器团队目前仅托管 java 服务 希望我们的实例始终运行 因此它可以在该实例的生命周期内收集数据 他们表示将使用我们的 webmon 操作之一来获取统计信息 但我们正在使用每次
  • 我的 .NET 库列表中缺少 System.Windows.Data

    您好 我想使用 System Windows Data IValueConverter 但是当我尝试在 VS2010 中添加对 System Windows Data 的引用时 我只看到 System Windows Forms 和 Sys
  • Powershell - 在不安装 Excel 的情况下将 CSV 转换为 XLS

    我有一台自动生成报告的服务器 报告采用 CSV 格式 我需要能够直接加密文件 无需第三方压缩 无 WinZIP 或 WinRAR 我认为最好的想法是将 CSV 转换为 XLS 然后通过 Powershell 密码保护 XLS 文件 不幸的是
  • 如何将 Razor 视图转换为字符串?

    我想使用我的 Razor 视图作为某种发送电子邮件的模板 所以我想将我的模板 保存 在视图中 将其作为字符串读入控制器 进行一些必要的替换 然后发送它 我有有效的解决方案 我的模板作为 HTML 页面托管在某处 但我想将其放入我的应用程序中
  • 在 C# 中将 ANSI (Windows 1252) 转换为 UTF8

    I ve 之前问过这个 https stackoverflow com q 4351985 398713之前在 Stack Overflow 上以一种迂回的方式 这次想把它做好 如何将 ANSI 代码页 1252 转换为 UTF 8 同时保
  • 如何在VS2017中从.net项目引用netstandard项目?

    我有一个 netstandard2 0 项目 用于与第三方 Web 服务交互 我需要在同一解决方案中引用旧的 net 4 6 2 项目中的该项目 但是当我这样做时 我会收到一堆关于需要引用我定义的类型的错误 例如 我将调用 netstand
  • 限制 LDAP 查询中返回的属性

    如何限制通过 System DirectoryServices 在 LDAP 查询中返回的属性 我一直在使用 DirectorySearcher 并将我想要的属性添加到 DirectorySearcher PropertiesToLoad
  • 如何判断应用程序是否是Web应用程序

    在 Windows 服务和 Web 应用程序中运行的核心程序集中 我需要存储每个用户会话的信息 该服务将具有单个用户会话 并且 Web 应用程序使用 HttpContext Current 我想配置在核心程序集中使用哪种方法 约定优于配置
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 是否可以有一个 out ParameterExpression?

    我想定义一个 Lambda 表达式out范围 有可能做到吗 下面是我尝试过的 C Net 4 0 控制台应用程序的代码片段 正如您在 procedure25 中看到的 我可以使用 lambda 表达式来定义具有输出参数的委托 但是 当我想使

随机推荐

  • PID调试软件(C#、模拟、仿真)

    突然想起要玩下PID xff0c 于是又想到强大的C xff0c 好吧 xff0c 搞个小软件玩下 首先花点时间学习PID xff0c 用的都是网上资料 xff0c 开始是先看http www amobbs com thread 50433
  • [docker报错] 用docker build构建python项目镜像时,执行到RUN pip install报错

    问题描述 用docker build构建python项目镜像 xff0c 执行到RUN pip install后 xff0c 长时间没有响应后报错 xff0c 原本以为是网速太慢导致下载失败 后来看到这篇 xff08 docker buil
  • 软件测试面试中项目介绍宝典

    面对 面试造飞机 xff0c 工作拧螺丝 的杯具 xff0c 我们必须做好准备工作 xff1a 打有准备的仗 测试的面试相对于开发的面试来说 xff0c 对于技术的询问其实相对来说较少的 xff0c 技术这一块主要针对以下几个方面 测试理论
  • 详解超声波测距模块HC-SR04的使用

    1 模块简介 HC SR04超声波模块常用于机器人避障 物体测距 液位检测 公共安防 停车场检测等场所 HC SR04超声波模块主要是由两个通用的压电陶瓷超声传感器 xff0c 并加外围信号处理电路构成的 如图 xff1a 两个压电陶瓷超声
  • Docker安装图形界面Shipyard

    Shipyard xff08 github xff09 是建立在docker集群管理工具Citadel之上的可以管理容器 主机等资源的web图形化工具 包括core和extension两个版本 xff0c core即shipyard主要是把
  • # 转载chmod+X与chmod777

    chmod 43 X与chmod777 原文 xff1a https blog csdn net qq 42982742 article details 103690119 chmod 43 x 是将文件状态改为可执行 xff0c 而chm
  • C++几个适合的OJ刷题网站

    RQNOJ VIJOS 这两个还比较基本 xff0c 题目也是中文的 对于准备NOI或者省选的话 xff0c BZOJ是不错的 ACM什么的 xff0c 最好就做POJ xff0c SGU xff0c Codeforces等题库 xff0c
  • Android系统深度游

    项目原因 xff0c 让我们必须深入探索Android系统 xff0c 完成对之前的我们来说比较艰巨的任务 这样 xff0c 我们开启了Android深度游 Android这个系统 xff0c 应用层开发还是比较舒服的 xff0c Goog
  • IT痴汉的工作现状56-耳鸣

    自从这个项目启动 xff0c 与客户方的沟通就逐渐多了起来 xff0c 沟通的方式是语音会议 也不知从什么时候起 xff0c 每天的会议时间变得很长很长 尤其是定位复杂问题时 xff0c 一个会议就要4个小时 张伟是从项目开始买的耳机 xf
  • 我的2020---熬过去

    恰逢周末 xff0c 本人自认为过了一个美好的圣诞节之后 xff0c 在深圳图书馆开始思考我的第十一个年终总结了 提笔之前 xff0c 我翻看了去年的总结 xff0c 想到了我还有一套书没有读完 xff0c 那就是 大败局 2020结束还有
  • 我的2022-工程师文化的思考

    没有想到 xff0c 今年大环境的变化可谓是大开大合 xff0c 超出想象 各行各业都遭到强大的挑战 xff0c 是泯灭还是苟活 xff0c 亦或是再创辉煌 xff0c 时也命也 在此情况下的个人 xff0c 最好的选择是跟公司抱团取暖 x
  • 我的2013---全速前行

    一晃 xff0c 自己也步入了而立之年 在IT这个行业 xff0c 而立 xff0c 意味着很多事情 现实的骨感不得不让自己想得更多 xff0c 但是到头来发现自己能做的仍只有继续好好工作 其实年龄是IT行业永恒的话题 xff0c 但我还是
  • 用户名 不在 sudoers文件中,此事将被报告。

    继续昨天的故事 话说昨天新建了一个帐号linc xff0c 今天在执行sudo时回显一个很吓人的信息 xff1a sudo password for linc linc 不在 sudoers 文件中 此事将被报告 这是要去哪儿报告呢 xff
  • Git冲突:commit your changes or stash them before you can merge.

    今天用git pull来更新代码 xff0c 遇到了下面的问题 xff1a error Your local changes to the following files would be overwritten by merge xxx
  • Android问题集锦之二十八:You need to use a Theme.AppCompat theme (or descendant) with this activity.

    错误描述为 xff1a java lang IllegalStateException You need to use a Theme AppCompat theme or descendant with this activity 起因
  • Docker实践6:Cannot connect to the Docker daemon.

    正在免费适用着Aliyun主机 xff0c 当然要用docker来部署我的服务器啦 但是今天碰到了题目的问题 xff0c 细节如下 xff1a span class hljs comment docker info span FATA sp
  • 一个简单的自定义通信协议(socket)

    转自 xff1a http vtrtbb javaeye com blog 849336 这是转自javaeye的一篇文章 xff0c 作者是vtrtbb 按照网络通信的传统 xff0c 我们都会自定义协议 xff0c 这有很多好处 xff
  • ImageView 设置图片

    android doc中是这样描述的 xff1a public void setImageResource int resId 这是其中的一个方法 xff0c 参数resld是这样 xff1a ImageView setImageResou
  • Android问题集锦之八:调用其他程序中的activity和Permission Denial: starting Intent 错误解决办法

    今天想调试多个task中栈的情况 xff0c 在测试程序中调用另一个程序的activity xff0c 代码片段如下 xff1a btnStartX 61 Button findViewById R id btnStartX btnStar
  • VB.NET串口通信例子--我的回忆录

    这是我3年前的一个例子 xff0c 最近翻出来回忆一下 串口是计算机上一种非常通用设备通信的协议 大多数计算机包含两个基于RS232的串口 xff0c 现在配电脑好像只有一个 串口同时也是仪器仪表设备通用的通信协议 xff1b 很多GPIB