JAVA IO/Serial

 Bom dia a todos, 

 Estou desenvolvendo uma aplicação que faz uso de comunicação serial. O código faz abertura da porta, bem como a associação das streams de comunicação. Apesar da abertura da porta e associação de streams, terem sido bem sucedidas, ao tentar fazer a leitura dos dados disponíveis no buffer de recepção, leio uma quantidade de dados superior à esperada e esses dados são apenas zeros. Utilizei o programa Serial Monitor para verificar a comunicação, o envio é feito corretamente, o erro ocorre somente na recepção de dados. A taxa está correta, assim como o cabo serial utilizado na comunicação. Apenas enfatizando, não ocorre excessão alguma durante todo o processo.

Estou utilizando a seguinte IDE e versão de sw:
Windows XP Professional
NetBeans 5.5
JDK 1.6
javax

Desde já agradeço a todos, abraços

Segue o código:

package Comunicacao;

import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.UnsupportedCommOperationException;
import java.util.Enumeration;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import lactec_utils.ThreadSleep;

/**
*Classe responsável pelo controle da porta serial, e pelo disponibilizacao do dispositivo para leitura e escrita
*/
public class Serial extends COM {

private static int PORTAID = 2000;
/**
 *Nome da porta serial ao qual essse objeto corresponde, ex:(WINDOWS)COM1, (LINUX)ttyS0
 */
private String portName = "";
/**
 *Taxa que esta sendo empregada na comunicacao com a porta serial
 */
private int taxa = 0;
/**
 *Variavel encarregada do armazenamento do identificador da porta serial
 */
public SerialPort serialPort = null;
/**
 *Stream de leitura de dados pela serial
 */
private InputStream inSerial = null;
/**
 *Stream de envio de dados pela serial
 */
private OutputStream outSerial = null;

/**
 *Funcao que retorna os dados disponiveis no buffer para leitura
 */
public byte[] readData() {
byte[] data = null;
try{
    if (serialPort != null){// Testa se a porta foi aberta
	int dataLength = inSerial.available();// Pega o numero de bytes disponiveis na porta
	if (dataLength>0){// Verifica se ha dados para leitura
	    data = new byte[dataLength];// Alocacao do buffer para leitura
	    inSerial.read(data);// Leitura dos dados presentes no buffer
	}
    }
}catch(Exception e){
    data = null;
}
return data;
}
/**
 *Funcao responsável pelo envio de dados através da serial, retorna
 * TRUE: em caso de sucesso,
 * FALSE: caso contrário
 */
public boolean writeData(byte[] dataToSend) {
boolean ret = false;
try{
    if (serialPort!=null){// Verificando se a serial esta aberta
	outSerial.write(dataToSend);// Fazendo o envio dos dados
	// Aguarda um intervalo proporcional à quantidade de dados
	// a serem enviados, sendo que o tempo para envio de um byte
	// é de (1/TAXA). O acréscimo de 10 mili se deve ao tempo
	// estimado para verificacao de disponibilidade para comunicacao
	// dentre outros metodos das camadas inferiores
	ThreadSleep.sleepWithSemaphore((dataToSend.length/taxa)+10);
	ret = true;// Sinaliza sucesso na operacao de envio dos dados
    }
}catch(Exception e){
    //log de sistema
}
return ret;
}
/**
 *Funcao que indica se há dados disponiveis para leitura no
 *buffer de leitura da serial
 */
public int dataAvailable() {
int ret = 0;
try{
    if (serialPort != null){// Verifica se a porta foi aberta
	ret = inSerial.available();// Verifica o numero de bytes disponiveis para leituras no buffer
    }
}catch(Exception e){
    ret = 0;
}
return ret;// Retorna o numero de bytes disponiveis para leitura no buffer
}
/**
 *Metodo responsavel pela abertura da porta, e configuracao de sua respectiva taxa de velocidade para comunicacao
 *retornando
 * TRUE: em caso de sucesso na operacao ou
 * FALSE: caso contrario
 */
public boolean open(String Porta, int BaudRate) {
try {
    CommPortIdentifier portId;
    Enumeration portList = CommPortIdentifier.getPortIdentifiers();
    while (portList.hasMoreElements()) {
	portId = (CommPortIdentifier)portList.nextElement();
	if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
	    if (portId.getName().equals(Porta)) {
		try {
		    serialPort = (SerialPort)portId.open("PortaPD"+Integer.toString(PORTAID), PORTAID++);
		    outSerial = serialPort.getOutputStream();
		    inSerial = serialPort.getInputStream();
		    serialPort.setFlowControlMode(serialPort.FLOWCONTROL_NONE);
		    this.taxa = BaudRate;
		    this.portName = Porta;
		    if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) {
			serialPort.setSerialPortParams(BaudRate,serialPort.DATABITS_8,serialPort.STOPBITS_1,serialPort.PARITY_NONE);
		    } else {
			Process p = Runtime.getRuntime().exec("stty -F "+Porta+" "+Integer.toString(BaudRate)+" -icanon -icrnl -inlcr -onlcr -ocrnl");
			p.waitFor();
			p.destroy();
		    }
		    System.gc();
		    return true;
		} catch(PortInUseException e) {
		    //System.out.println(e.getMessage());
		    break;
		}
	    }
	}
    }
} catch (Exception e) { };//System.out.println(e.getMessage());}

return false;
}
/**
 *Procedimento responsavel pelo fechamento da porta serial, retornando
 * TRUE: em caso de sucesso ou
 * FALSE: caso contrario
 */
public boolean close() {
boolean ret = false;
try{
    inSerial.close();// Fechando a stream de leitura de dados
    outSerial.close();// Fechando a stream de escrita de dados
    serialPort.close();// Liberando a porta serial
    ret = true;// Sinaliza sucesso na operacao de fechamento da serial
}catch(Exception e){
    // Mensagem para o log
}
return ret;
}
/**
 * Metodo encarregado de esvaziar o buffer de recepcao e transmissao da porta serial
 */
public void flush(){
try{
    inSerial.skip(inSerial.available());
}catch(IOException e){
    
}
}
/**
 *Metodo que indica se a conexao com a porta serial foi estabeleciada
 */
public boolean conectado(){
return serialPort != null;
}

}

Já faz tempo, mas na última vez que tentei usar as APIs de serial do Java desisti em função de problemas de instabilidade e algumas limitações (não lembro agora quais…).

Achei bem mais simples fazer um aplicativo em C que funcionava como ponte entre um socket TCP e a porta serial. Fim dos problemas…

 serialPort.setFlowControlMode(serialPort.FLOWCONTROL_NONE); 

Sem controle de fluxo, o receptor não tem como determinar se recebeu informações (visto que em serial, são apenas pulsos de 1 e 0). Pra isso, existem 2 pinos de controle: CTS e RTS. Troque o flowControlMode para:

serialPort.setFlowControlMode((javax.comm.SerialPort.FLOWCONTROL_RTSCTS_OUT | javax.comm.SerialPort.FLOWCONTROL_RTSCTS_IN));