VB.NET串口通信例子

尊重原创:http://blog.csdn.net/lincyang/article/details/6966324#comments


这是我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

  1. Imports System.IO.Ports  
  2.   
  3. Public Class Form1  
  4.   
  5.     Dim WithEvents RS232 As SerialPort  
  6.     Delegate Sub SetTextCallback(ByVal InputString As String)       '声明一个代理  
  7.   
  8.     Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load  
  9.         For Each sp As String In SerialPort.GetPortNames()  
  10.             cmbCom.Items.Add(sp)  
  11.         Next  
  12.         cmbCom.Sorted = True  
  13.         cmbCom.SelectedIndex = 0  
  14.     End Sub  
  15.   
  16.     Private Sub btnStart_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnStart.Click  
  17.         Dim mBaudRate As Integer  
  18.         Dim mParity As IO.Ports.Parity  
  19.         Dim mDataBit As Integer  
  20.         Dim mStopBit As IO.Ports.StopBits  
  21.         Dim mPortName As String  
  22.   
  23.         mPortName = cmbCom.SelectedItem.ToString  
  24.         mBaudRate = 9600  
  25.         mParity = Parity.None  
  26.         mDataBit = 8  
  27.         mStopBit = StopBits.One  
  28.   
  29.         RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopBit)  
  30.   
  31.         If Not RS232.IsOpen Then  
  32.             RS232.Open()  
  33.             btnSend.Enabled = True  
  34.             RS232.ReceivedBytesThreshold = 1        '设置引发事件的门限值  
  35.         Else  
  36.             MsgBox("通讯端口打开错误!", MsgBoxStyle.Critical)  
  37.         End If  
  38.     End Sub  
  39.   
  40.   
  41.     Private Sub RS232_DataReceived(ByVal sender As ObjectByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles RS232.DataReceived  
  42.         Dim InByte() As Byte, ReadCount As Integer, strRead As String  
  43.         If RS232.BytesToRead <= 0 Then Exit Sub  
  44.         ReDim InByte(RS232.BytesToRead - 1)  
  45.         ReadCount = RS232.Read(InByte, 0, RS232.BytesToRead)  
  46.         strRead = ""  
  47.         If ReadCount = 0 Then  
  48.             Exit Sub  
  49.         Else  
  50.             For Each bData As Byte In InByte  
  51.                 strRead += bData.ToString & vbCrLf     '若有数据则加到接收文本框  
  52.                 DisplayText(strRead)  
  53.             Next  
  54.         End If  
  55.   
  56.   
  57.     End Sub  
  58.     '*************************************************  
  59.     '代理子程序  
  60.     '处理上述通信端口的接收事件  
  61.     '由于欲将数据显示到接收文本框中,因此必须检查  
  62.     '是否由另外得Thread所调用的,若是,则必须先  
  63.     '建立代理对象  
  64.     'Invoke用于在拥有控件基础窗口控制代码的线程上  
  65.     '运行代理  
  66.     '*************************************************  
  67.     Private Sub DisplayText(ByVal comData As String)  
  68.         '如果调用txtReceive的另外的线程,返回true  
  69.         If Me.txtReceive.InvokeRequired Then  
  70.             '利用代理类型建立对象,并指定代理的函数  
  71.             Dim d As New SetTextCallback(AddressOf DisplayText)  
  72.             Me.Invoke(d, New Object() {comData})    '以指定的自变量列表调用函数  
  73.         Else '相同的线程  
  74.             'showstring(comData)     '将收到的数据填入接收文本框中  
  75.             Me.txtReceive.Text += comData  
  76.         End If  
  77.     End Sub  
  78.   
  79.     Private Sub btnClose_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnClose.Click  
  80.         If RS232 Is Nothing OrElse Not RS232.IsOpen Then   '尚未打开  
  81.             MsgBox("通讯端口尚未打开", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)  
  82.         Else  
  83.             RS232.Close()  
  84.             btnStart.Enabled = False  
  85.             btnClose.Enabled = False  
  86.             RS232 = Nothing  
  87.         End If  
  88.     End Sub  
  89.   
  90.     Private Sub btnEnd_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnEnd.Click  
  91.         If Not RS232 Is Nothing Then  
  92.             If RS232.IsOpen Then RS232.Close()  
  93.         End If  
  94.         End  
  95.     End Sub  
  96.   
  97.     Private Sub btnSend_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnSend.Click  
  98.         Dim bDataOut(0) As Byte  
  99.         Try  
  100.             bDataOut(0) = CType(Me.txtSend.Text, Byte)        '将类型转换为字节  
  101.             RS232.Write(bDataOut, 0, 1)  
  102.         Catch ex As Exception  
  103.             MessageBox.Show("输入数值错误:" + ex.ToString, "错误通知:", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)  
  104.         End Try  
  105.     End Sub  
  106.   
  107.     Private Sub cmbCom_KeyPress(ByVal sender As ObjectByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCom.KeyPress  
  108.         e.KeyChar = ChrW(0)             '禁止用户在其中输入任何文字  
  109.     End Sub  
  110.   
  111.     Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click  
  112.         Me.Hide()  
  113.         Form2.Show()  
  114.     End Sub  
  115. End Class  
Form2.vb
  1. '**************************************************************  
  2. '时间:2008-11-08  
  3. '作者:lincyang  
  4. '实际应用中,串行通信的数据可能一次发送大量的数据,  
  5. '发送之前就必须将数据先编码,  
  6. '将其编成我们需要的字节数组数据,  
  7. '才能将这些数据以字节的方式发送出去  
  8. '目前操作系统使用的字符数据是Unicode:所有的字符均使用  
  9. '两个字节来表示一个字符  
  10. '**************************************************************  
  11.   
  12. Imports System.IO.Ports  
  13. Imports System.Text  
  14. Public Class Form2  
  15.     Dim RS232 As SerialPort  
  16.     Private Sub Form2_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load  
  17.         For Each sp As String In SerialPort.GetPortNames()  
  18.             cmbCom.Items.Add(sp)  
  19.         Next  
  20.         cmbCom.Sorted = True  
  21.         cmbCom.SelectedIndex = 0  
  22.     End Sub  
  23.   
  24.     Private Sub btnStart_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnStart.Click  
  25.         Dim mBaudRate As Integer  
  26.         Dim mParity As IO.Ports.Parity  
  27.         Dim mDataBit As Integer  
  28.         Dim mStopBit As IO.Ports.StopBits  
  29.         Dim mPortName As String  
  30.   
  31.         mPortName = cmbCom.SelectedItem.ToString  
  32.         mBaudRate = 9600  
  33.         mParity = Parity.None  
  34.         mDataBit = 8  
  35.         mStopBit = StopBits.One  
  36.   
  37.         RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopBit)  
  38.   
  39.         If Not RS232.IsOpen Then  
  40.             RS232.Open()  
  41.             btnSend.Enabled = True  
  42.             Timer1.Interval = 100  
  43.             Timer1.Enabled = True  
  44.         Else  
  45.             MsgBox("通讯端口打开错误!", MsgBoxStyle.Critical)  
  46.         End If  
  47.     End Sub  
  48.   
  49.     Private Sub Timer1_Tick(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Timer1.Tick  
  50.         Dim InByte() As Byte, ReadCount As Integer  
  51.         If RS232.BytesToRead <= 0 Then Exit Sub  
  52.         ReDim InByte(RS232.BytesToRead - 1)  
  53.         ReadCount = RS232.Read(InByte, 0, RS232.BytesToRead)  
  54.   
  55.         If ReadCount = 0 Then  
  56.             Exit Sub  
  57.         Else  
  58.             For Each bData As Byte In InByte  
  59.                 Me.txtReceive.Text += bData.ToString & vbCrLf     '若有数据则加到接收文本框  
  60.   
  61.             Next  
  62.         End If  
  63.     End Sub  
  64.   
  65.     Private Sub btnClose_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnClose.Click  
  66.         If RS232 Is Nothing OrElse Not RS232.IsOpen Then   '尚未打开  
  67.             MsgBox("通讯端口尚未打开", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)  
  68.         Else  
  69.             RS232.Close()  
  70.             btnStart.Enabled = False  
  71.             btnClose.Enabled = False  
  72.             Timer1.Enabled = False  
  73.             RS232 = Nothing  
  74.         End If  
  75.     End Sub  
  76.   
  77.     Private Sub btnSend_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnSend.Click  
  78.         Dim bDataOut() As Byte, Buf As String  
  79.         Dim iSentCount As Integer  
  80.         Dim Encode1 As Encoding = Encoding.ASCII         '声明编码对象,使用ASCII  
  81.   
  82.         Try  
  83.             Buf = txtSend.Text.Trim()  
  84.             bDataOut = Encode1.GetBytes(Buf)      '将字符串转换为字节数组  
  85.             iSentCount = bDataOut.GetLength(0)     '发送总字节数  
  86.             '显示出总字节数  
  87.             lblSentCount.Text = "总传输量:" & iSentCount.ToString & "字节"  
  88.             RS232.Write(bDataOut, 0, iSentCount)  
  89.         Catch ex As Exception  
  90.             MessageBox.Show("输入数值错误:" + ex.ToString, "错误通知", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)  
  91.         End Try  
  92.     End Sub  
  93.   
  94.     Private Sub btnEnd_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnEnd.Click  
  95.         If Not RS232 Is Nothing Then  
  96.             If RS232.IsOpen Then RS232.Close()  
  97.         End If  
  98.         End  
  99.     End Sub  
  100.   
  101.     Private Sub cmbCom_KeyPress(ByVal sender As ObjectByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCom.KeyPress  
  102.         e.KeyChar = ChrW(0)             '禁止用户在其中输入任何文字  
  103.     End Sub  
  104. End Class  

开发环境是VB2008,源码下载 猛击这里
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值