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.