VB.NET - Usando a porta COM


Neste artigo vou falar sobre um projeto da Microsoft que mostra como usar a porta COM no VB.NET. O projeto foi retirado do site da Microsoft e transliterado para o português para facilitar a aprendizagem.

Eu já abordei este assunto relacionado com o VB nos seguintes artigos:

Vou começar me repetindo :

"A comunicação paralela e a serial são muito usadas como forma de controlar uma grande variedade de equipamentos eletromecânicos e eletrônicos e você pode acreditar que não precisa conhecer C ou C++ para criar uma interface que lhe possibilite interagir com estes equipamentos; você pode fazer isto usando o Visual Basic ( e até mesmo o Basic...)

Existem algumas limitações que VB possui e que você vai ter que aprender a contornar. O Visual Basic não pode acessar diretamente o hardware em um sistema . Toda requisição feita a um hardware precisa passar pelo sistema operacional , no nosso caso o Windows. Por causa disto o mais perto que você vai conseguir chegar quando tentar realizar uma comunicação serial é em um componente do VB que faz a interface com o Sistema Operacional. (Uma forma de contornar isto é usar as chamadas a API diretamente no seu programa VB.)

Um computador geralmente vem equipado com duas portas seriais e uma porta paralela para comunicação externa. A porta serial envia e recebe dados bit a bit enquanto que a porta paralela faz este serviço usando uma transmissões de múltiplos bits. Uma porta serial pode ser vista então uma interface entre um equipamento que exibe dados (Ex:Monitor ) e um equipamento que transmite dados (Ex:modem). 

A princípio uma porta serial era usada primariamente para exibir dados em um terminal que eram entrados via teclado , mas com o avanço da tecnologia a utilização da porta serial foi sendo usada nas mais variadas aplicações. (Ex: transferência de dados entre Handhelds como o Palm). Nos tempos do bom e velho DOS (lembra dele) tínhamos a interface da linha de comando que foi substituida por uma interface mais amigável com o advento do Windows e do Visual Basic.

O Visual Basic utiliza o componente - Microsoft Common Control : MSComm (MSCOMM32.OCX) para realizar a interface serial. Vamos então começar logo com um exemplo (se bem que não muito prático):"

Vamos abrir o projeto e dar uma espiada nas sua funcionalidades.

Lembre-se que uma porta Comm é sinônimo de porta COM , porta Serial ou porta RS232.

Na verdade ele é muito simples , mas podemos aprender muito com ele.
 

O .NET Framework não da suporte para o controle direto sobre a porta COM, por isto uma classe a parte é usada para fornecer chamadas via API .

 

Portanto o coração desta aplicação é a classe  RS232.vb cujo código exibimos abaixo:

 

Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Threading

' This class provides all the necessary support for communicating
'   with the Comm Port (otherwise known as the Serial Port, or 
'   RS232 port).
Public Class Rs232
|    ' Declare the necessary class variables, and their initial values.		
|    Private mhRS As Integer = -1   ' Handle to Com Port									
|    Private miPort As Integer = 1   ' Default is COM1	
|    Private miTimeout As Integer = 70   ' Timeout in ms
|    Private miBaudRate As Integer = 9600
|    Private meParity As DataParity = 0
|    Private meStopBit As DataStopBit = 0
|    Private miDataBit As Integer = 8
|    Private miBufferSize As Integer = 512   ' Buffers size default to 512 bytes
|    Private mabtRxBuf As Byte()   ' Receive buffer	
|    Private meMode As Mode  ' Class working mode	
|    Private mbWaitOnRead As Boolean
|    Private mbWaitOnWrite As Boolean
|    Private mbWriteErr As Boolean
|    Private muOverlapped As OVERLAPPED
|    Private muOverlappedW As OVERLAPPED
|    Private muOverlappedE As OVERLAPPED
|    Private mabtTmpTxBuf As Byte()  ' Temporary buffer used by Async Tx
|    Private moThreadTx As Thread
|    Private moThreadRx As Thread
|    Private miTmpBytes2Read As Integer
|    Private meMask As EventMasks
|
+ Enums
|
+ Structures
|
+ Exceptions
|
+ Events
|
+ Constants
|
+ Properties
|
+ WIn32API
|
+ Methods
|
End Class

 

O formulário frmPrincipal.vb irá usar esta classe para poder implementar a funcionalidade requerida. O código do início do formulário é:

'Copyright (C) 2002 Microsoft Corporation
Option Strict On

Imports System.Text

Public Class frmMain
	Inherits System.Windows.Forms.Form

    ' Declara as variáveis necessárias
    Private m_CommPort As New Rs232()
    Private m_IsModemFound As Boolean = False
    Private m_ModemPort As Integer = 0
      .....
      .....
 
Note que o código cria uma instância da classe Rs232 em  - Private m_CommPort As New Rs232()
 
A partir dai basta usar as funcionalidades dos métodos , eventos e propriedades da classe Rs232. 
 
Assim , no evento Click do botão de comando para - Verificar as Portas - temos :
 
  ' Esta rotina verifica as portas disponíveis na máquina local
    ' Ela efetua a tentativa de abrir da porta 1 até a porta 4
    Private Sub btnCheckForPorts_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCheckForPorts.Click

        ' Verifica a disponibilidade de cada uma das 4 Portas COM, e
        ' realiza uma checagem nos itens do listbox que tem as portas abertas
        Dim i As Integer
        For i = 1 To 4
            WriteMessage("Testando COM" + i.ToString())
            If IsPortAvailable(i) Then
                ' marca o checkbox das portas disponíveis no listbox
                Me.clstPorts.SetItemChecked(i - 1, True)
            Else
                ' Desmarcar o checkbox para as portas não disponíveis
                Me.clstPorts.SetItemChecked(i - 1, False)
            End If
        Next
        ' habilita o botão para verificar o Modem
        Me.btnCheckModems.Enabled = True
    End Sub
 

A seguir o código do botão verificar Modem:

   ' Esta rotina tenta enviar um comando AT para uma porta COM ativa
    ' Se a resposta for retornada então um modem foi detectado na porta
    Private Sub btnCheckModems_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCheckModems.Click
        Dim i As Integer
        For i = 0 To 3
            If Me.clstPorts.GetItemChecked(i) Then
                ' O item esta marcado então pode ser uma porta valida
                ' fazer o Teste para validação
                If IsPortAvailable(i + 1) Then
                    ' verifica se a porta responde ao comando AT
                    If IsPortAModem(i + 1) Then
                        ' Define as variáveis de classe para o último modem encontrado
                        Me.m_IsModemFound = True
                        Me.m_ModemPort = i + 1
                        ' envia mensagem ao usuário
                        WriteMessage("Port " + (i + 1).ToString() + " O modem esta respondendo.")
                    Else
                        ' envia mensagem ao usuário
                        WriteMessage("Port " + (i + 1).ToString() + " modem inativo.")
                    End If
                End If
            End If
        Next
        ' Se um modem foi encontrado habilita o resto dos botões
        ' assim o usuário pode interagir com o modem
        If Me.m_IsModemFound Then
            Me.txtSelectedModem.Text = "Usando Modem na COM" + Me.m_ModemPort.ToString()
            Me.txtUserCommand.Enabled = True
            Me.btnSendATCommand.Enabled = True
            Me.btnSendUserCommand.Enabled = True
        End If
    End Sub 

 

Finalmente o código do botão  que envia um comando AT para o modem é :

Só para você lembrar alguns comandos AT básicos :

ATA - Responder manualmente
ATD - Discar
ATDT - dicar por tom
ATDP - Discagem por pulso
ATDR - Chamar um modem somente de origem


               
    ' envia um comando AT para o modem e e regisra sua resposta
    '   isto depende do timer a fazer a leitura da resposta
    Private Sub btnSendATCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendATCommand.Click

        ' sempre tratar exceção 
        Try
            'habilita o timer
            Me.tmrReadCommPort.Enabled = True
            ' tenta abrir a porta
            m_CommPort.Open(m_ModemPort, 115200, 8, Rs232.DataParity.Parity_None, Rs232.DataStopBit.StopBit_1, 4096)

            ' Escreve um comando AT na porta
            m_CommPort.Write(Encoding.ASCII.GetBytes("AT" & Chr(13)))
            ' Da um tempo suficiente para o modem responder
            System.Threading.Thread.Sleep(200)
            Application.DoEvents()
            m_CommPort.Close()

        Catch ex As Exception
            ' avisa o usuário
            MessageBox.Show("Não foi possível comunicar com o Modem")
        Finally
            ' desabilita o timer
            Me.tmrReadCommPort.Enabled = False
        End Try

    End Sub

 

Pegue a aplicação completa aqui : portaCOM.zip

Veja também este artigo sobre como usar portas paralelas com C# - http://www.linhadecodigo.com.br/artigos.asp?id_ac=254&pag=1

Eu sei é apenas VB , e daí , eu gosto ....


José Carlos Macoratti