Академический Документы
Профессиональный Документы
Культура Документы
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.
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
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:
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
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.
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.
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
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
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???!!!
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
txtEntrada.Atributtes.Add("onkeypress", "javascript:ValidaEntrada()");
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
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); } }
Pedro disse...
Vlw cara manja muito vc.. :D
24 de outubro de 2012 15:58
Ele automaticamente efetua a ao de "colar" o valor escaneado depois do evento disparo pelo ENTER?
Obrigado.
1 de julho de 2013 18:44
Postar um comentrio