zoukankan      html  css  js  c++  java
  • 串口通讯随笔

    之前了做了个串口通讯的项目,主要用到 SerialPort类

    这里主要说说几个问题

    1. 在关闭串口的时候软件容易卡死的问题.

        我们在使用SerialPort类打开串口时候,会开一个接收数据的线程来接收从串口发送过来的数据,也可以开个调用SerialPort类的事件DataReceived (我这里使用后者,自己开启的线程要一直循环接收数据,消耗资源)

       

    _serialPort = New SerialPort()
    AddHandler _serialPort.DataReceived, AddressOf serialPort_DataReceived  '添加串口接收数据事件
    Private Sub serialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)

    '
    '这里写接收数据的处理
    '
    End Sub

        在写好接收数据处理的方法后, 我们来看看具体的处理方法

      

     private Delegate sub DelShowMessage(Byval msg As String) '定义一个带字符串参数的委托
    Private
    Sub serialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)
    Dim bytestoread As Integer = _serialPort.BytesToRead If bytestoread = 0 Then Exit Sub End If
       '定义字节数组接收数据 Dim buffer(bytestoread - 1) As Byte

    '读取缓冲区数据到字节数组中 _serialPort.Read(buffer,
    0, bytestoread)
       '把字节转成相应的字符串 (这里只是个Demo 真正的项目接收的字节都是有自己的协议进行转换的)
    Dim messagestr As String = ConvertBuffer(buffer) '接收数据这个方法是个线程,用委托来处理显示
    Me.Invoke(New DelShowMessage(AddressOf ShowMessage),messagestr)
    End Sub

    ‘在文本框中显示字符串 Private Sub ShowMessage(Byval message As String)   TextBox1.Text=message
    End Sub

    '字节转换

      Private Function ConvertBuffer(ByVal buffer() As Byte) As String

           Return BitConverter.ToString(buffer)

      End Function

     上段代码将接收到的数据转换成字符串显示到文本框中

    下面是关闭端口的方法

    '关闭端口方法

     Private Sub btnPortClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPortClose.Click if _serialPort.IsOpen = True Then
    _serialPort.Close()
       End If End Sub

    就是这样直接关闭端口, 有时候软件会卡死

    找到原因: 在点击按钮关闭端口的时候, 关闭这个方法在UI线程中运行, 如果串口接收的数据正好也需要用委托UI线程, 这样操作的的时候, 会结束这个接收的方法,如果这个方法同样在操作UI线程,就会造成死锁.

    改进的方法:1. 在接收的数据的时候加一个标志说明已经有数据在处理,数据处理结束将此标志恢复, 在点击按钮关闭串口的时候, 等待这个标志恢复,再去关闭这个串口.

                       在点击按钮关闭串口的时候同样加一个标志说明需要关闭串口, 接收数据的时候判断是否有此标志, 有此标志则不进行处理

                    2. 是比较简单的方法, 在处理完数据界面显示的用异步委托

     第一种方法:


    '
    关闭端口方法
    Private _bClosing As Boolean = False
    private _bListening As Boolean = False Private Sub btnPortClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPortClose.Click '添加关闭标志,说明在关闭串口
      _bCloseing = True

         '监听界面是否更新数据
         While (_bListening)

                Application.DoEvents()

        End While

    if _serialPort.IsOpen = True Then
             _serialPort.Close()
      EndIf
       _bCloseing = False
     End Sub


     Private Sub serialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)
         '监听端口是否关闭
    If _bCloing = True Then
        Exit Sub
       End If
          Try
               _bListening = True
                If _serialPort.IsOpen = True Then
    Dim bytestoRead As Integer = _serialPort.BytesToRead()
    If bytestoread=0 Then
    Exit Sub
    End
                    '定义字节数组接收数据
                      Dim buffer(bytestoread - 1) As Byte

    '读取缓冲区数据到字节数组中 _serialPort.Read(buffer, 0, bytestoread)
       '把字节转成相应的字符串 (这里只是个Demo 真正的项目接收的字节都是有自己的协议进行转换的) Dim messagestr As String = ConvertBuffer(buffer) '接收数据这个方法是个线程,用委托来处理显示
    Me.Invoke(New DelShowMessage(AddressOf ShowMessage),messagestr)
            End If

             Catch ex As Exception

             Finally

                      _bListening = False

              End Try

     End Sub

    第二种方法:

    将委托的那部分用异步委托代替

            Me.BeginInvoke(New DelShowMessage(AddressOf ShowMessage),messagestr)
    
  • 相关阅读:
    Elasticsearch学习之SearchRequestBuilder的query类型
    Elasticsearch学习之SearchRequestBuilder常用方法说明
    Elasticsearch学习之head插件安装
    SpringBoot学习之Helloworld
    Http Header里的Content-Type
    柯里化
    VoltDB
    Docker
    PHP框架
    转载: 让我们聊聊Erlang的nif中资源的安全释放
  • 原文地址:https://www.cnblogs.com/hdsong/p/4800748.html
Copyright © 2011-2022 走看看