Вы находитесь на странице: 1из 17

Usando o controle MSComm no Visual Basic

Neste artigo vamos mostrar como usar controle MSComm da Microsoft e como detectar as portas COM disponveis. Cada computador possui portas seriais denominadas sucessivamente : COM1 , COM2 , etc. Geralmente o mouse usa a porta COM1 o modem a porta COM2 o scanner a COM3 e assim por diante. Assim as portas seriais possibilitam um canal de transmisso de dados a partir destes dispositivos. Se voc tentar verificar a disponibilidade das portas COM de sua mquina provavelmente voc ir obter o erro 8002 - Nmero de porta Invlida . Entretanto voc pode fazer o feitio virar contra o feiticeiro usando este erro para detectar quais portas esto disponveis e exibir somente as portas realmente disponveis. Vamos ento mostrar um projeto que pode ser usado para detectar as portas COM disponveis ( deve funcionar bem no Win95/98 e NT) 1- Inicie um novo projeto no Visual Basic e no formulrio padro - form1 - insira um boto de comando - command1 , uma label - Portas COM disponveis , e um controle ComboBox conforme abaixo:

2- Inclua um mdulo no seu projeto e a seguir insira o seguinte cdigo no mdulo: Type DCB DCBlength As Long BaudRate As Long fBitFields As Long wReserved As Integer XonLim As Integer XoffLim As Integer ByteSize As Byte Parity As Byte StopBits As Byte XonChar As Byte XoffChar As Byte ErrorChar As Byte EofChar As Byte EvtChar As Byte wReserved1 As Integer End Type Type COMMCONFIG

dwSize As Long wVersion As Integer wReserved As Integer dcbx As DCB dwProviderSubType As Long dwProviderOffset As Long dwProviderSize As Long wcProviderData As Byte End Type ' Declare Function GetDefaultCommConfig Lib "kernel32" _ Alias "GetDefaultCommConfigA" (ByVal lpszName As String, _ lpCC As COMMCONFIG, lpdwSize As Long) As Long 3- Ainda no mdulo insira o seguinte cdigo para a funo DetectaPortaCOM : Public Function DetectaPortaCOM(port As Integer) As Long 'retorna zero se a porta com no existir Dim cc As COMMCONFIG, ccsize As Long ccsize = LenB(cc) DetectaPortaCOM = GetDefaultCommConfig("COM" + Trim(Str(port)) + Chr(0), cc, ccsize) End Function 4- Inclua o cdigo abaixo no evento click do boto de comando - command1 : Private Sub Command1_Click() Dim i As Integer Combo1.Clear For i = 1 To 16 If DetectaPortaCOM(i) <> 0 Then Combo1.AddItem "COM" & i End If Next Combo1.ListIndex = 0 End Sub Ao executar o projeto e clicar no boto para detectar as portas a combobox ir exibir as portas disponveis. Ver figura acima.

Usando o Controle MSComm - Propriedades


A primeira coisa a fazer para usar o controle MSComm em seu projeto e incluir o componente no seu formulrio. Clique em Project | Components e selecione : Microsoft Comm Control 6.0 Obs: Este controle somente esta disponvel na verso Professional do VB.

O controle MSComm fornece a interface para um conjunto de comandos de comunicao padro : conectar com uma porta serial , conectar com outro dispositivo de comunicao , trocar dados , monitar e responder a vrios eventos durante uma comunicao serial. Podemos usar o controle para realizar as seguintes tarefas:

1. 2. 3.

Discar um nmero de telefone Monitarar a porta serial para entrada de dados Criar sistemas de comunicao

Ao lado temos o controle MSComm sendo incluido no formulrio e as propriedades que podemos configurar.

Uma das primeiras propriedades que podemos configurar a propriedade Settings. Esta propriedades permite configurar : A Baud Rate - ( a velocidade mxima da porta COM ) o padro 9600 Paridade - usada na validao de dados. O padro usar "N" Data Bits - define o nmero de bits que representa um pacote de dados. Stop Bit - indique quando um pacote de dados foi recebido

O formato da propriedade Settings : "BBBB,P,D,S" Onde : BBBB - a Baud Rate P a paridade D o nmero de Data bits S o nmero de stop bits

Os valores padro para esta propriedade : "9600,N,8,1"

Se a propriedade for configurada com valores invlidos , ao tentar abrir uma porta COM iremos obter o erro : 380 - Invalid Property value Para usar o controle MSComm e estabelecer uma comunicao com uma porta serial usamos as seguintes propriedades: Propriedade CommPort Settings PortOpen Descrio Define e retorna o nmero a porta de comunicao Define e retorna : baud rate, parity, data bits, e stop bits como uma string Define e retorna o estado da porta de comunicao. Tambm abre e fecha a porta.

Vejamos um exemplo de cdigo para realizar esta tarefa: 'Abre a porta serial MSComm1.CommPort = 2 MSComm1.Settings = "9600,N,8,1" MSComm1.PortOpen = True Como funciona:

a. b. c.

A propriedade CommPort define qual porta serial vai ser aberta . O nmero 2 indica que abrimos a porta COM2. Podemos usar valores entre 1 e 16. O valor padro 1. A propriedade Settings permite definir as propriedades discutidas acima : baud rate, parity, data bits, e stop bits A propriedade PortOpen para estabelecer a conexo . Ela retorna um valor Verdadeiro (True) ou Falso ( False)

Podemos configura estas propriedades em tempo de projeto clicando em Custom na janela de propriedades do controle e definindo os valores na janela Property Pages .

Usando um Modem Podemos usar o controle MSComm com um modem atravs dos comandos compatveis com o padro Hayes; tanto para discar um nmero de telefone como para efetuar uma conexo com outro modem. Apos definir as propriedades CommPort, Settings e PortOpen para estabelecer a conexo , usamos a propriedade Output para ativar e interagir com o modem. Exemplo:

MSComm1.Output = "ATDT 235-4545" & vbCr


Onde : AT - inicia a conexo D - disca o nmero T - define se usamos Tom ou Pulso.

Nota: Os comandos Hayes so padronizados e permitem que o programa de


comunicao controle as funes do modem. Porm, nem todos os modems compatveis com o padro Hayes (hoje, maioria absoluta) aceitam todos os comandos, e alguns possuem comandos especiais. O manual do modem deve conter essas informaes e tambm os valores default (pr-configurados na fbrica). Os comandos so dados a partir do programa de comunicao, em modo terminal, ou j esto embutidos no prprio soft de comunicao. Normalmente, comeam com os caracteres AT, que fazem o modem prestar ateno ao que comandado a seguir, podem ter (conforme o modem) de 40 a 255 caracteres na linha de comando e terminam, como qualquer comando em computador, com o sinal <CR> (Carriage Return - sinal obtido quando se pressiona a tecla [Enter] ou [Return] em cdigo <CR> equivale a usar CHR$(13) ou vbcr) Lista de comandos Hayes Os comandos Hayes so enviados na forma AT[primeiro comando] [segundo comando] [terceiro comando etc.] [Enter/Return]. AT o cdigo de ateno, usado no incio de cada linha de comando, tenha ela um ou mais comandos Hayes. Apenas o comando [A/] no usa o cdigo de ateno, e serve para repetir o ltimo comando executado. A seguir uma lista dos principais comandos Hayes : Comando Hayes A Dx Ex Hx Vx Z Descrio conecta em modo de resposta Discar (Dial) ; onde x pode assumir P(Pulso) , T(Tom) , R (modo de resposta) , W (espera por tom de discar) Ecoa ou no os caracteres para o micro em modo local , onde o x pode assumir : 0 ( retira o eco) ou 1 (inclui o eco) Controla a conexo do modem. O x pode assumir: 0 (desconecta) ou 1 (conecta) Formato de resposta, onde x pode ser : 0 (formato numrico) ou 1 (formato texto) Reseta o modem.

Ex: ATZ - reseta o modem , ATA - coloca o modem em estado de resposta , ATH0 - Desconecta o modem. Alocao do Buffer de Memria

Quando uma porta aberta , so criados buffers para transmitir e receber dados. Para gerenciar estes buffers podemos usar a janela de Property Pages clicando em Custom na janela de propriedades do controle.

As propriedades InBufferSize e OutBufferSize definem quanto de memria alocado para receber e transmitir buffers. ( armazenam os dados de chegada e de saida). Quanto maior o valor usado , menor a memria disponvel para sua aplicao. Se o valor for muito pequeno voc corre o risco de um transbordamento de buffer a menos que voc use Handshaking. Atualmente , devido a quantidade de memria dos computadores , podemos usar valores maiores para alocar memria. As propriedades RThreshold e SThreshold As propriedades RThreshold e SThreshold ajustam ou retornam o nmero de caracteres que so recebidos nos buffers de transmisso e recepo antes que o evento OnComm seja disparado. O evento OnComm usado para monitorar e responder s mudanas no estado da comunicao. Se cada propriedade for definida com o valor 0 ( este o padro ) evita que o evento OnComm seja disparado. Qualquer outro valor diferente de zero far com que o evento OnComm seja disparado sempre que um caractere for recebido no buffer. As propriedades

InputLen e EOFEnable

Definir a propriedade InputLen com o valor 0 faz com que o controle leia todo o contedo do buffer de recepo quando usamos a propriedade Input . Ao ler dados de uma mquina cuja sada esta formatada para blocos de dados de tamanho de comprimento fixo podemos ajustar o valor desta propriedade de forma correta. A propriedade EOFEnable usada para indicar quando um caracter de fim de arquivo ( End of File) for encontrado duranta uma entrada de dados. Definir esta propriedade como True faz com que a entrada de dados pare e o evento OnComm seja disparado para informar a condio acabou de ocorrer. Gerenciando os buffers de transmisso e recepo Quando uma porta aberta os buffers de transmisso e recepo de dados so criados . Eles so usados para receber os dados que chegam e transmitir os dados que saem. O controle MSComm permite gerenciar estes buffers atravs de propriedades que permitem receber e transmitir dados , determinar o tamanho de cada buffer e manipular dados do tipo teto e dados do tipo binrio. O buffer de recepo

A propriedade Input usada para armazenar e retornar dados de um buffer de recepo. Assim se voc que receber dados de um buffer de recepo e exib-los em uma caixa de texto ( text1.text ) pode usar o seguinte cdigo:

Text1.text = MSComm1.Input
Se quiser receber e exibir todo o contedo do buffer deve definir a propriedade InputLen com valor 0 . Para receber dados no formato Texto ou Binario voc deve definir a propriedade InputMode para um dos seguintes valores : comInputModeText (dados no formato ANSI) ou comInputModeBinary(dados que contenham caracteres de controles , Nulls ,etc..) Cada byte de dados recebido movido para o buffer de recepo e a propriedade InBufferCount incrementada de um ; assim podemos usar a propriedade InBufferCount para retornar o numero total de bytes no buffer de recepo. Para limpar o buffer de recepo definimos o valor desta propriedade para o valor igual a 0. O buffer de transmisso A propriedade Output usada para enviar comandos e dados para o buffer de transmisso. Da mesma forma que a propriedade Input , os dados podem ser enviados no formato Texto ou Binrio. Podemos enviar comandos , tetos , ou uma matriz de dados : Veja o cdigo exemplo a seguir: Dim Out as byte ' Envia um comando AT MSComm1.Output = "ATDT 555-5555" ' Envia uma string MsComm1.Output = "Estou enviando uma string" ' Enviando uma matriz de dados MSComm1.Output = Out

Ao final de uma linha de dados devemos usar o caracter de retorno -

vbCr .

Para monitorar o buffer de transmisso usamos a propriedade OutBufferCount. Definindo o valor desta propriedade como igual a zero limparemos o buffer de transmisso.

Agora um exemplo prtico


Vamos aplicar toda a teoria vista acima em um exemplo prtico. Vamos criar um projeto para discar um nmero telefnico usando um modem. 1- Inicie um novo projeto no VB e no formulrio padro insira uma caixa de texto text1.text 2- Faa uma referncia ao componente MSComm - MSComm1 - no seu projeto Microsoft Comm Control 6.0 ( MSCOMM32.ocx)

3- Inicialmente vamos configurar as seguintes propriedades do controle MSComm1 :

Propriedade Valor RThreshold SThreshold InputLen ComPort


1 1 0 A porta do seu modem

A primeira a fazer e abrir a porta COM , para isto usamos a propriedade PortOpen . Depois enviamos um comando a porta . Como queremos discar um nmero vai modem vamos usar os comandos Hayes - ATDT AT diz ao modem que um comando esta chegando DT informa para discar o nmero usando a discagem de tom. Veja abaixo o cdigo:

Private Sub Command1_Click() MSComm1.PortOpen = True MSComm1.Output = "ATDT" & text1.Text & Chr$(13) End Sub Obs: precisamos incluir o codigo de controle CHR$(13) depois do comando. O nmero a ser discado dever ser informado na caixa de texto - text1.text. Como vamos ter certeza de que a discagem ocorreu com sucesso ??? Para isto vamos usar o evento OnComm. Usamos o evento OnComm para verificar se os dados esto sendo recebidos. Para receber os dados checamos a propriedade Input , ocorre que os dados ficam por pouco segundos na propriedade Input. A que entra o evento OnComm . Para disparar o evento configuramos as propriedades RThreshold e SThreshold com valor igual a 1. Para obter o resultado de um comando enviado para o modem vamos usar o seguinte cdigo no evento OnComm: Private Sub MSComm1_OnComm() Select Case MSComm1.CommEvent 'mensagens dos eventos Case comEvReceive Text1.Text = Text1.Text & StrConv(MSComm1.Input, vbUnicode) End Select End Sub Este cdigo verifica qual evento ocorreu e se o for o evento Receive o contedo da propriedade Input adicionada ao final da caixa de texto: Podemos usar o evento OnComm tambm para monitorar erros durante a comunicao. Vejamos a seguir uma tabela com as constantes que podem ocorrer quando o evento OnComm ocorre.

Constante comEvSend comEvReceive comEvCTS comEvDSR comEvCD comEvRing

Valor Descrio 1 2 3 4 5 6 Numeros de caracteres no buffer de transmisso menor que RThreshold. Recebendo RThreshold nmero de caracteres. Alteraao em Clear To Send line. Alterao na linha Data Set Ready. Alterao em Carrier Detect line. Chamado detectado. Alguns UARTs (universal asynchronous receiver-transmitters) podem no suportar este evento. Fim de arquivo (ASCII character 26)

comEvEOF

Para encerrar o artigo vamos mostrar um projeto onde usamos as propriedades e eventos do controle MSComm discutidas. 1-) inicie um novo projeto no VB e no formulrio padro insira os controles conforme o layout abaixo: Private Sub Form_Load() Dim i As Integer Dim sSettings As String sSettings = MSComm1.Settings cboBaubRate.Text = Left$(sSettings, 4) cboParity.Text = Mid$(sSettings, 6, 1) cboDataBits.Text = Mid$(sSettings, 8, 1) cboStopBits.Text = Mid$(sSettings, 10, 1) cboCommand.ListInde x = 0 '// obtem porta com Show DoEvents ListaPortasCom End Sub Como podemos ver na carga do formulrio , no evento Load , obtemos os valores da propriedade Settings e preenchemos as caixas de combinao extraindo os valores pertinentes a cada propriedade. A seguir usamos a funo ListaPortasCom para detectar e listar as portas COM disponveis. A funo exibida a seguir: Private Sub ListaPortasCom()

Dim i As Integer cboComm.Clear SetStatus "Verificando as portas disponveis...", True For i = 1 To 16 If DetectaPortaCOM(i) Then cboComm.AddItem i SetStatus "COM" & i & " encontrada", False End If Next cboComm.ListIndex = 0 End Sub Abaixo a tela de exibio do projeto:

A funo DetectaPortaCOM foi discutida no inicio do artigo. O resto do cdigo trivial. Para fazer o download do projeto clique aqui : Exemplo de utilizao do MSComm - Mscom.zip

Exemplo Avanado

Ler cdigo de barras atravs de um leitor ptico com ASP.NET


POSTADO POR THIAGO MARAL ON SEGUNDA-FEIRA, 21 DE JUNHO DE 2010 / MARCADORES: CDIGO DE BARRAS

No h nenhum segredo ou driver especfico para realizar a leitura. Basicamente o leitor ptico l o cdigo de barras, converte para string e retorna para o buffer de entrada do computador. Ou seja, como se fosse digitar no teclado! Acabou o mistrio...

H vrias formas de codificao do cdigo de barras e quem responsvel por essa codificao/decoficao pode ser tanto a leitora quanto a aplicao. Irei considerar em nosso exemplo que o que a leitora l e irei utilizar no me importando o que seja. Supondo e para fins ilustrativos que nosso cdigo de barras seja essa a de cima, o valor de entrada seria 3805565154 (frisando novamente, apenas supondo). A leitora ir passar para nossa aplicao a seguinte entrada 3805565154 ENTER. A maioria das leitoras j facilitam sua vida forando o ENTER ao terminar de ler o contedo. Ento fica fcil! Vamos por a mo na massa. Crie uma tela com apenas um TextBox. Criei essa bonitinha aqui:

Selecione o TextBox, v na guia Properties e clique no cone de Events. Adicione um evento em KeyDown conforme a figura abaixo:

Com isso, ao digitar qualquer valor no TextBox, ir disparar esse evento. Mas como queremos ler apenas o valor completo, adicionamos uma determinada condio para comear a analisar apenas quando pressionar/entrar o ENTER, logo nosso cdigo ficaria da seguinte forma:

private void txtNumero_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { string entrada = txtNumero.Text; txtNumero.Text = ""; } }

Ou seja, a cada entrada de caracteres, ativo o evento mas s iniciarei a anlise quando a entrada for um ENTER. Ao final, zero o contedo do TextBox para que possa dar uma nova entrada. Da voc pode adicionar outras instrues no meio para fazer o que quiser. Eu complementei a aplicao fazendo uma consulta em um banco de dados e analisando se existe ou no um determinado cupom. Vamos aos testes... A leitora que usei plugada diretamente na entrada PS/2 do teclado. A depender de sua leitora pode ser na USB, na PS/2 ou utilizar algum adaptador especfico. Depois de

conectado, inicie sua aplicao. Posicione o leitor sobre o cdigo de barras e pressione o boto para realizar a leitura e voil... Sua aplicao ir ler a entrada e realizar o processo que desejar.

Minha aplicao leu um cupom cujo nmero codificado era 1000909. Bem fcil e til... Quem quiser saber mais informaes como tipos de codificaes, como gerar/codificar/decodificar strings para cdigo de barras no Access, acessem esse artigo da MSDN que bem interessante e explicativo.

13 comentrios:
Annimo disse...
Ser necessrio instalar alguma dll do leitor de cdigo de barras para que o asp.net identifique o leitor ?
5 de agosto de 2010 09:32

Thiago Maral disse...


No preciso de DLL para a leitura. A maioria dos leitores hoje so conectadas diretamente na porta PS/2 do teclado ou na USB. Ento quando h a leitura como se fosse digitado, ou seja, como se voc estivesse teclado a informao e presisonado ENTER logo em seguida. Mas avalie qual leitora esteja usando pois o comportamento de cada uma pode distinguir a depender do modelo / marca.
5 de agosto de 2010 14:27

Annimo disse...

Estou com uma pequena dvida... Tenho uma aplicao de controle de vendas onde coloquei um leitor tico para reconheciimento de cdigo do banco, para puxar o produto correspondente. Porm, quando o leitor tico l o produto ele insere seu cdigo + \n\n.Ou seja minha aplicao no consegue deixar fixo o valor lido pelo leito no meu inputText. Estas quebras de linha faz com que a aplicao avance um passo... Teria como eu deixar com que o leitor no quebrasse estas duas linhas ao ler um cdigo de produto???!!!

Fico no aguardo... Valeuu, Abs,


28 de agosto de 2010 19:45

Thiago Maral disse...


O \n\n inserido pela leitora aps a leitura do cdigo corresponde a dois ENTERS caso fosse pelo teclado. Como voc quer manter no campo, TextBox, o cdigo sem a quebra voc pode usar o seguinte artifcio quando estiver lendo: capture o campo, limpe o TextBox, remova o \n\n da string capturada e reinsira apenas a string com o cdigo. Se voc estiver usando o cdigo acima ou uma variao dela, veja abaixo como poderia ser:

if (e.KeyCode == Keys.Enter) { string entrada = txtNumero.Text.Replace("\n", ""); txtNumero.Text = entrada; }


29 de agosto de 2010 01:46

Annimo disse...
Legal. O codigo de barras do DVD Amigos Por Siempre. Massa
24 de fevereiro de 2011 03:17

TH Informtica disse...
Thiago!Blz? Otimo seu Post, estou trabalhando com WebForms. Sabe me dizer como fazer esquema KeyDown via webForms? Obrigado!Abrao
23 de maro de 2011 14:08

Thiago Maral disse...


Voc pode adicionar um evento Atributtes para o textbox:

txtEntrada.Atributtes.Add("onkeypress", "javascript:ValidaEntrada()");

Ento voc cria um JS da seguinte forma:

function ValidaEntrada() { if (e.KeyCode == 13) __doPostBack('Process',''); }

Ento no Page_Load coloca:

if (Request.Form["__EVENTTARGET"] == "Process") // Executa o processo

Seria algo do tipo...


25 de maro de 2011 18:22

Unknown disse...
Amigo vc teria como me dizer, como fazer pro campo que l o codigo de barras ir ao banco de dados consultar e retornar o produto? Como em um sistema de mercado. Grato
27 de maio de 2012 16:00

Thiago Maral disse...


Basta usar o evento no TextBox conforme o cdigo abaixo:

private void txtNumero_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { string entrada = txtNumero.Text; // Consulta no banco de dados DataSet ds = RetornaDS("SELECT * FROM Produtos WHERE codigo = " + entrada); } }

Isso apenas uma sugesto do cdigo bastando adequar sua necessidade.


27 de maio de 2012 17:31

Pedro disse...
Vlw cara manja muito vc.. :D
24 de outubro de 2012 15:58

Felype Santos disse...


Nossa Show de bola.. ta de parabns Thiago Maral! Muito bons os seus artigos at aqui os melhores que j li e consegui compreender..
10 de fevereiro de 2013 00:30

Marcio Ordoez disse...


Ol Thiago, o que no est compreensvel nesse post, como o valor escaneado pelo aparelho, passa do buffer para o campo txtNumero.

Ele automaticamente efetua a ao de "colar" o valor escaneado depois do evento disparo pelo ENTER?

Poderia dar mais detalhar por gentileza?

Obrigado.
1 de julho de 2013 18:44

Thiago Maral disse...


Marcio, Quando o aplicativo est em execuo, o cursor fica em foco no campo texto. Ento qualquer entrada de texto via teclado ser efetuada nesse campo. O leitor funciona como um teclado. O modelo que usei l o contedo do cdigo de barras e d um ENTER no final. Ento, se o cdigo for "123", o leitor dar uma entrada "123ENTER". E no campo texto configuro um evento para ler o ENTER e assim pegar o contedo para manipulao. Veja se ficou claro e me avise qualquer coisa. Abs
2 de julho de 2013 19:19

Postar um comentrio