Envios y recibos de caracteres VB .net

Iniciado por Meta, 27 Febrero 2015, 08:44 AM

0 Miembros y 1 Visitante están viendo este tema.

Meta



1)El programa espera la recepciòn de un ENQ(05 Hex) o STX(02 Hex)

2) Si recibo lo del paso 1 , le envìo un ACK(06 Hex)

3)Luego de enviado el ACK leo todo lo que me manda la maquina externa, si es distinto de cualquier caracter de control, lo muestro.

4) Si recibo un EOT(04 Hex) mando un enter en la pantalla de recepcion para diferenciar las lineas.

5) Si recibo un ETX(03 Hex) le respondo con un ACK.

Supongo que en este caso se podrìa hacer un if o un select preguntando lo recibido, el tema es que no se como leer de manera correcta y poder comparar que es lo que se recibio para poder ejecutar la tarea necesaria segun lo que llega.

Código (vbnet) [Seleccionar]
Imports System.IO.Ports
Imports System.Text

Public Class Form1
    Dim recibidos As String
    Dim stx As String = ASCIIEncoding.ASCII.GetString(New Byte() {2})
    Dim etx As String = ASCIIEncoding.ASCII.GetString(New Byte() {3})
    Dim eot As String = ASCIIEncoding.ASCII.GetString(New Byte() {4})
    Dim enq As String = ASCIIEncoding.ASCII.GetString(New Byte() {5})
    Dim ack As String = ASCIIEncoding.ASCII.GetString(New Byte() {6})


    Public Sub New()
        InitializeComponent()
        If Not SerialPort1.IsOpen Then
            Try
                SerialPort1.Open()
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
            End Try
        End If
        AddHandler SerialPort1.DataReceived, AddressOf recepcion
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If SerialPort1.IsOpen Then
            SerialPort1.Close()
        End If
    End Sub

    Private Sub recepcion(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)

        recibidos = Chr(SerialPort1.ReadChar)
        If recibidos = stx Or recibidos = enq Then
            SerialPort1.Write(ack)
        Else
            If recibidos <> stx And recibidos <> etx And recibidos <> enq And recibidos <> ack And recibidos <> eot Then
                Me.Invoke(New EventHandler(AddressOf actualizar))
            Else
                If recibidos = eot Then
                    Me.Invoke(New EventHandler(AddressOf actualizarenter))
                Else
                    If recibidos = etx Then
                        SerialPort1.Write(ack)
                    End If
                End If
            End If
        End If


    End Sub

    Private Sub actualizar(ByVal s As Object, ByVal e As EventArgs)
        textbox_visualizar_mensaje.Text = textbox_visualizar_mensaje.Text & recibidos
    End Sub

    Private Sub actualizarenter(ByVal s As Object, ByVal e As EventArgs)
        textbox_visualizar_mensaje.Text = textbox_visualizar_mensaje.Text & vbLf
    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        StatusStrip1.Items(0).Text = DateTime.Now.ToLongTimeString
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        SerialPort1.Encoding = System.Text.Encoding.Default
    End Sub
End Class
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Eleкtro

#1
uf, estás utilizando malas prácticas de programación en todos los rincones del código xD.

Prueba así (no lo he testeado, ni tampoco se si he entendido correctamente las condiciones que dices que se deben dar al recibir los datos, pero desde luego puedes simplificar ese IF anidado de tú código en un Switch/Select Case):
Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.IO.Ports

#End Region

Public NotInheritable Class Form1 : Inherits Form

#Region " Objects / Constants-ReadOnly / Properties "

   ' Estos objetos los inicializo en el constructor del Form solo para poder compilar este ejemplo.
   Private WithEvents sp As SerialPort
   Private ReadOnly ss As StatusStrip
   Private ReadOnly tb As TextBox
   ' ***********************************************

   Private WithEvents tmr As New Timer

   Private ReadOnly charStx As Char = Convert.ToChar(&H1)
   Private ReadOnly charEtx As Char = Convert.ToChar(&H3)
   Private ReadOnly charEot As Char = Convert.ToChar(&H4)
   Private ReadOnly charEnq As Char = Convert.ToChar(&H5)
   Private ReadOnly charAck As Char = Convert.ToChar(&H6)

   ''' <summary>
   ''' Gets the next character from the device's input buffer.
   ''' </summary>
   ''' <value>The next character from the device's input buffer.</value>
   Private ReadOnly Property NextChar As Char
       Get
           Return Convert.ToChar(Me.sp.ReadChar)
       End Get
   End Property

#End Region

#Region " Constructors "

   Public Sub New(ByVal sp As SerialPort, ByVal ss As StatusStrip, ByVal tb As TextBox)

       MyClass.InitializeComponent()

       Me.sp = sp
       Me.ss = ss
       Me.tb = tb

   End Sub

   Public Sub New()
       MyClass.InitializeComponent()
   End Sub

#End Region

#Region " Event-Handlers "

   Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
   Handles Me.Load

       Me.OpenPort(Me.sp)

   End Sub

   Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) _
   Handles Me.FormClosing

       Me.ClosePort(Me.sp)

   End Sub

   Private Sub Serialport1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) _
   Handles sp.DataReceived

       Me.ProcessChar(Me.NextChar)

   End Sub

   Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) _
   Handles tmr.Tick

       ss.Items(0).Text = DateTime.Now.ToLongTimeString

   End Sub

#End Region

#Region " Private Methods "

   Private Sub OpenPort(ByVal sp As SerialPort)

       If Not sp.IsOpen Then

           Try
               sp.Open()

           Catch ex As Exception
               MessageBox.Show(ex.ToString &
                               Environment.NewLine &
                               ex.StackTrace, "error", MessageBoxButtons.OK, MessageBoxIcon.Error)

           End Try

       End If

   End Sub

   Private Sub ClosePort(ByVal sp As SerialPort)

       If sp.IsOpen Then

           Try
               sp.Close()

           Catch ex As Exception
               MessageBox.Show(ex.ToString &
                               Environment.NewLine &
                               ex.StackTrace, "error", MessageBoxButtons.OK, MessageBoxIcon.Error)

           Finally
               If sp IsNot Nothing Then
                   sp.Dispose()
               End If

           End Try

       End If

   End Sub

   Private Sub ProcessChar(ByVal chr As Char)

       Select Case chr

           Case Me.charStx, Me.charEnq, Me.charEtx
               sp.Write(Me.charAck)

           Case Me.charAck
               ' Do Nothing?.

           Case Me.charEot
               Me.ThreadSafeAppendText(Me.tb, chr & ControlChars.Lf)

           Case Else
               Me.ThreadSafeAppendText(Me.tb, chr)

       End Select

   End Sub

   Private Sub ThreadSafeAppendText(ByVal tb As TextBox, ByVal str As String)

       SyncLock tb

           If tb.InvokeRequired Then
               tb.Invoke(Sub() tb.AppendText(str))

           Else
               tb.AppendText(str)

           End If

       End SyncLock

   End Sub

#End Region

End Class


Nota:
En mi modificación no modifico la codificación de entrada del dispositivo, ya que puedes hacerlo de la siguiente manera, al declarar e inicializar el puerto de serie:
Código (vbnet) [Seleccionar]
Dim sp As New SerialPort With
   {
     .Encoding = Encoding.Default
   }


Saludos