Como configurar e abrir uma Porta Serial – Parte II

Dando prosseguimento à primeira parte deste artigo, onde apresentei uma visão geral de como devemos proceder para uma comunicação via porta serial, irei nesta segunda parte solucionar alguns questionamentos.

O primeiro dos questionamentos seria; Como devemos configurar e abrir uma porta tanto para escuta como para escrita de algum tipo de informação?

Para isso a API disponibiliza a seguinte solução:
CommPortIdentifier.Open(); //Este método retorna um objeto do tipo SerialPort.

Ates da chamada para este método é preciso ter em mente que devemos nos preocupar como a porta irá se comportar com o mundo exterior, ou seja, qual será a sua taxa de transferência?; Existe paridade?; Qual será o “Stop Bit” (Bit de parada do pacote)? Fornecer essas informações talvez seria um tanto quanto desconfortáveis caso escrevamos um código sem a utilização da API.

Felizmente, a API da SUN disponibiliza uma interface portável para todos estes parâmetros. Há quatro passos a serem seguidos até ter uma porta pronta para enviar quanto para receber algum dado, são eles:

1 – Escolher a porta.
2 – Chamar o método CommPortIdentifier.Open(), tendo a preocupação de realizar um cast para a porta desejada, neste caso SerialPort.
3 – Configurar os parâmetros de comunicação serial, tais como baud rate (taxa de transferência), parity (paridade), stop bits (bit de parada), entre outros, procedendo a configuração em um único momento ou individualmente, sendo que para qualquer dos procedimentos preferidos, deve-se utilizar o método, setSerialPortParan();
4 – Chamar os métodos getInputStream e getOutputStream do objeto SerialPort, além de prover um Stream e umWriter (Classes do java.io.*, que abrem fluxos de dados entre o programa e qualquer tipo de dados, seja ele um arquivo, teclado, porta de comunicação serial, entre outros.)

Fazendo isso você estará pronto para ler e escrever em uma porta serial. Segue abaixo um trecho de código:


// Abre a porta para comunicação

public void abrePortaCom() {
/*
* Para a porta ser aberta precisa ter um identificador do tipo da porta, para isso usa-se o método getPortIdentifier("Qual é a porta? COM1, LPT1 ...") da classe CommPortIdentifier.
*
* Tendo feito isso há a necessidade, agora, de instanciar o tipo da porta que foi escolhida, nesse caso a porta serial a qual recebe o identificador juntamente com o método open() que recebe como parâmetro um nome identificador (um título) e o tempo de espera de alguma resposta (timeout).
*
* Estando a porta aberta, configura-se os parâmetros de comunicação serial.
*/

try{
  
idPorta = CommPortIdentifier.getPortIdentifier(tipoPorta);
  
portaSerial =(SerialPort)idPorta.open("PlacaSensoriamento",timeout);
   JOptionPane.showMessageDialog(
null, "Configurando Porta Serial");
  
portaSerial.setSerialPortParams(baudrate, portaSerial.DATABITS_8, portaSerial.STOPBITS_1, portaSerial.PARITY_NONE);
}

catch (NoSuchPortException nspe){
   System.
err.println("Posta não existe! : " + tipoPorta);
}

catch (PortInUseException piu){
   System.
err.println("Porta ja esta aberta!");
}

catch (UnsupportedCommOperationException uscoe){
   System.
err.println("Configuração dos parametros da porta não suportada!");
}
}

Suponhamos que você queira enviar um comando para um dispositivo externo e receber uma resposta do mesmo. Segue abaixo o código para realizar a leitura e o envio de uma String que segue alguns passos que o próprio código relada em forma de comentários.

/*
* Ler dados é um pouco mais complicado! passos a serem seguidos
*
* - Criar um fluxo de entrada.
* - Adicionar um gerenciador de eventos para dados na porta serial.
* - Instanciar uma Thread para aguardar os eventos.
* - Tratar os eventos e receber os dados.
*/

public void iniciaLeitura(){
  
try{
     
portaEntrada = portaSerial.getInputStream();
     
portaSerial.addEventListener(this);
     
// Agora tem-se uma notificação de dados disponível

      portaSerial.notifyOnDataAvailable(true);
     
// Threads responsíveis por aguardar os eventos

      thread = new Thread(this);
     
thread.start();
   }

    catch (IOException ioe){
       System.
err.println("Erro de comunicação com a porta!");
    }

    catch (TooManyListenersException tmle){
       System.
err.println("Erro. Muitos métodos ouvintes na porta!");
    }

    catch (Exception e){
        System.
out.println("Erro ao iniciar leitura com a thread!");
    }

}

// Método que envia um bit para a porta serial
public void EnviarUmaString(int comando){

   this.comando = comando;
  
try {
     
saida = portaSerial.getOutputStream();
     
saida.write(comando);
      Thread.sleep(100);
     
saida.flush();
   }
catch (IOException ioe){
      System.
out.println("Não foi possivel abrir/enviar_comando na porta serial");
    
System.out.println("Erro! STATUS: " + ioe );
   }
catch (InterruptedException ie){
      System.
out.println("Problema com as Threads");
      System.
out.println("Erro: Status: " + ie);
   }
}

Segue abaixo mais um trecho de código definindo o tratador de eventos de chegada de dados para a leitura.

// Gerenciador de eventos na porta serial

public void serialEvent(SerialPortEvent spe){
  
switch( spe.getEventType()){
     
case SerialPortEvent.BI:
     
case SerialPortEvent.OE:
     
case SerialPortEvent.FE:
     
case SerialPortEvent.PE:
     
case SerialPortEvent.CD:
      
case SerialPortEvent.CTS:
     
case SerialPortEvent.DSR:
     
case SerialPortEvent.RI:
     
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
     
break;
     
case SerialPortEvent.DATA_AVAILABLE:

   try{
     
while ( portaEntrada.available() > 0 ) {
         tmp = Integer.toHexString(
portaEntrada.read());
         st = st + tmp;
      }
      System.
out.println(" > " + st);
   }

   catch(Exception ioe){
      System.
err.println("Erro de Leitura!");
      ioe.printStackTrace();
   }

Espero que todos tenham tirado proveito desse primeiro artigo que posto para o portal. Muito em breve estarei enviando outro, e neste momento deixo todos à vontade para tecer suas críticas.