首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > VB Dotnet >

SerialPort控件委托方式显示接收的字符串有关问题

2012-10-13 
SerialPort控件委托方式显示接收的字符串问题Dim strData As StringDim mRecvByte() As BytePrivate Sub S

SerialPort控件委托方式显示接收的字符串问题
Dim strData As String
 Dim mRecvByte() As Byte

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
  Dim mSize As Integer = Me.SerialPort1.BytesToRead
  ReDim mRecvByte(mSize - 1)
  SerialPort1.Read(mRecvByte, 0, mSize)
  BeginInvoke(New EventHandler(AddressOf ONMLoadA), SerialPort1.BytesToRead()) '使用委托方式显示接收的字符串
End Sub

Sub ONMLoadA(ByVal sender As System.Object, ByVal e As System.EventArgs) '委托
  Dim i As Integer
  For i = 0 To mRecvByte.Length 'mSize - 1
  strData = strData & IIf(mRecvByte(i) > 15, Hex(mRecvByte(i)), "0" & Hex(mRecvByte(i))) & " "
  Next

  TextBox2.Text = strData '显示为16进制
  TextBox3.Text = Len(strData) / 3
 End Sub


1. 接收的数据,显示时,只有第一次接近正确值,然后就离真相越来越远
2. 代码运行中途,经常提示 红色部分 数组索引越界,有时一开始运行就报此错误
3. 求其他更好的解决方案

[解决办法]

VB.NET code
Imports System.IO.PortsImports System.TextPublic Class Form1    '声明一个通信端口对象,使用WithEvents关键字,以便可以引发事件    Dim WithEvents RS232 As SerialPort    '声明一个委派类,并声明符合函数参数有一个,而其型态是字符串    Delegate Sub SetTextCallback(ByVal InputString As String)    Dim inStr As String    Dim i As Integer = 0    '**************************************************************    '表单的Load事件中先将所有的通信端口先列出来    '将通信端口排序,并将第一个通信端口设为默认值    '**************************************************************    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    '**************************************************************    '『打开通信端口』按钮的Click事件    '此事件将设定通信端口参数,并打开通信端口    '**************************************************************    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.Even  '同位位检查设定        mDataBit = 7    '数据位设定值        mStopbit = StopBits.Two '停止位设定值        '建立一个通信端口对象        RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopbit)        RS232.Encoding = Encoding.ASCII        ''''  RS232.Encoding = Encoding.Unicode  '设定编码方式为Unicode,以便能显示中文        If Not RS232.IsOpen Then  '尚未打开            RS232.Open()  '打开通信端口            RS232.ReceivedBytesThreshold = 1  '设定引发事件的阀值            btnSend.Enabled = True  '致能传送按钮        Else            MsgBox("~~通信端口打开错误(通信端口已被打开)~~", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)            End        End If    End Sub    '**************************************************************    '『传送』按钮的Click事件    '将欲传送的字符串通过串行端口送出去    '**************************************************************    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click        RS232.Write(txtSend.Text)  '采用Write方法送出    End Sub    '**************************************************************    '『关闭通信端口』按钮的Click事件    '以Close方法关闭通信端口,并释放对象所占用的资源    '**************************************************************    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)            Exit Sub        End If        RS232.Close()        RS232 = Nothing  '释放资源    End Sub    '**************************************************************    '『结束程序』按钮 的Click事件    '此事件将设定通信端口参数,并打开通信端口    '**************************************************************    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    '**************************************************************    '通信端口对象的DataReceived事件程序    '当有数据超过ReceivedBytesThreshold属性设定值会引发此事件    '接收的程序可以写在此事件程序中    '处理数据的部份必须另外以委派(Delagate)类予以处理,否则将会产生错误    '**************************************************************    Private Sub RS232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles RS232.DataReceived        '在此范围内,不能直接将结果指定给txtReceive控制项的Text属性        '原因是事件的引发在不同的执行绪        If e.EventType <> SerialData.Chars Then Exit Sub '判断接收的数据是否为字符        Dim inData As String = RS232.ReadExisting '取得字符串        DisplayText(inData)  '显示数据    End Sub    '**************************************************************    '委派子程序    '处理上述通信端口的接收事件    '由于欲将数据显示到接收文字框中,因此必须检查是否由另外的Thread    '所呼叫的,若是,则必须先建立委派对象    'Invoke用于在拥有控制项基础视窗控制代码的执行绪上执行委派    '**************************************************************    Private Sub DisplayText(ByVal comData As String)        '如果呼叫txtReceive的是另外的执行绪,传回True        Try            If Me.txtReceive.InvokeRequired Then                '利用委派型别建立委派对象,并指定委派的函数                Dim d As New SetTextCallback(AddressOf ShowString)                '用大括号 {} 括住初始值,藉以初始化阵列的值。                Me.Invoke(d, New Object() {comData})  '以指定的引数清单叫用函数            Else  '相同的执行绪                ShowString(comData)   '将收到的数据填入接收文字框中            End If        Catch ex As Exception            'MsgBox(ex.ToString)        Finally        End Try    End Sub    '**************************************************************    '显示数据的函数    '**************************************************************    Private Sub ShowString(ByVal comData As String)        '  Region(将数据存入缓冲)        Dim s As String = comData        Try            If comData.Length < 13 Then Exit Sub            s = comData.Substring(comData.IndexOf(Chr(2)), 10)       '判断首字符            s = s.ToCharArray                      '转换成数组来理解            If s(1) = "M" Then                     '判断是否稳定                Label4.Text = "稳定"            Else                Label4.Text = "动态"            End If            s = s.Substring(3, 7)                   '分离出重量数据            's = s(1) + s(2) + s(3) + s(4) + s(5) + s(6)            s = Single.Parse(s)            txtReceive.Text = s        Catch ex As Exception        Finally        End Try        ' end region    End Sub    '**************************************************************    '通信端口的KeyPress事件,在此不让用户输入数据    '**************************************************************    Private Sub cmbCOM_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCOM.KeyPress        e.KeyChar = ChrW(0)  '禁止用户在其中输入任何的文字    End SubEnd Class 

热点排行