2009-09-08 41 views
7

我一直在使用RXTX大约一年,没有太多问题。我刚开始一个新程序来与新硬件进行交互,所以我重用了我在其他项目中使用的connect()方法,但是我有一个我从未见过的奇怪问题。接收RXTX的问题

的问题

该设备工作正常,因为当我使用超级终端连接,我送的东西,并接受我的期望,并Serial Port Monitor(SPM)反映了这一点。但是,当我运行简单的超级终端克隆,我写了诊断我的主应用程序的问题,根据SPM发送字节,但没有收到,并且我的SerialPortEventListener从不会触发。即使当我检查主循环中的可用数据时,reader.ready()也会返回false。如果我忽略此检查,那么我会得到一个例外,下面详细介绍。

connect()方法的有关章节

// Configure and open port 
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 
port.setSerialPortParams(baud, databits, stopbits, parity); 
port.setFlowControlMode(fc_mode); 
final BufferedReader br = new BufferedReader(
          new InputStreamReader(
           port.getInputStream(), 
           "US-ASCII")); 

// Add listener to print received characters to screen 
port.addEventListener(new SerialPortEventListener(){ 
    public void serialEvent(SerialPortEvent ev) { 
    try { 
     System.out.println("Received: "+br.readLine()); 
    } catch (IOException e) { e.printStackTrace(); } 
    } 
}); 
port.notifyOnDataAvailable(); 

异常

java.io.IOException: Underlying input stream returned zero bytes 
     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268) 
     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
     at java.io.InputStreamReader.read(InputStreamReader.java:167) 
     at java.io.BufferedReader.fill(BufferedReader.java:136) 
     at java.io.BufferedReader.read(BufferedReader.java:157) 
     at <my code> 

的一个大问题(再次)

我想我已经消除了所有可能的硬件问题,所以可能会出现什么情况用我的代码或RXTX库?

编辑:一些有趣的事情

当我从那个应该得到响应,所有响应立即出现,仿佛他们已经放在缓冲区某处的Java发送一串命令后,打开超级终端,但不可用。

编辑2:尝试新的东西,同样的结果

我跑的代码示例发现here,具有相同的结果。没有数据进入,但是当我切换到一个新的程序时,它一次性完成。

编辑3

硬件是好的,并且甚至在不同的计算机具有相同的问题。我没有使用任何种类的USB适配器。

我也开始使用PortMon,它给了我一些有趣的结果。超级终端和RXTX不使用相同的设置,并且RXTX总是轮询端口,不像超级终端,但我仍然看不到什么设置会影响此设置。只要我可以从持续轮询中分离配置,我就会发布我的PortMon日志。

编辑4

有没有可能是某种在过去3个月的Windows更新可能造成的?它曾经搞乱了我的一个基于MATLAB mex的程序。

编辑5

我也注意到一些事情是超级终端,RXTX之间的不同,和一个单独的程序中,我发现,与该设备通信(但不会做我想做的,这是我为什么我自己的滚动计划)

  • 超级终端 - 设置为无流控,但串行端口监视器的RTS和DTR指标绿色
  • 其他程序 - 不知道什么设置它认为它的使用,但只SPM的RTS指标为绿色
  • RXTX - 无论我设置什么流量控制,只有SPM的CTS和DTR指示灯亮起。

从串行端口监视器的帮助文件(转述):

the indicators display the state of the serial control lines 

    RTS - Request To Send 
    CTS - Clear To Send 
    DTR - Data Terminal Ready 

回答

7

好的,对不起,我已经花了很长时间才回到这个问题。以下是我的工作方式。

注:此方法将为大家不要工作,请在下面复制/粘贴之前读入自己的代码

public void connect(CommPortIdentifier portId) throws Failure { 
    if (portId == null) 
     throw new Failure("No port set"); 

    try { port = (SerialPort) portId.open(getClass().getName(), 10000); } 
    catch (PortInUseException e) { 
     throw new Failure("Port in use by " + e.currentOwner,e); } 

    try { 
     port.setSerialPortParams(9600, SerialPort.DATABITS_8, 
       SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 
     port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN 
           | SerialPort.FLOWCONTROL_RTSCTS_OUT); 
    } catch (UnsupportedCommOperationException e) { throw new Failure(e); } 

    port.setRTS(true); 

    // More setup 
} 

所以,在我的情况下,问题是,我特别的设备需要RTS流量控制。其他设备可能需要不同的东西(CTS,XON/XOFF),因此请检查该设备的手册。默认情况下,RXTX禁用所有流量控制机制(与Hypertrm或其他程序不同)。启用每个步骤是一个两步过程。

  1. 一旦你有一个的SerialPort对象,调用setFlowControlMode()方法,以及按位OR(“|”)的必要SerialPort.FLOWCONTROL_常数
  2. 设置适当的流量控制为true或false(像我一样有port.setRTS(true)

对于其它类似的问题,如果不工作,我建议

  1. 使用串行端口监视程序(如Serial Port Monitor和/或PortMon(包括Windows))来查看实际正在进行的操作。
  2. 通过电子邮件发送的[email protected]的RXTX开发者(他们是非常有帮助的)
+1

请问您使用流量控制吗? 在此先感谢... – Oso

+0

希望这个编辑帮助 –

+0

@drhorrible我看你是如何设置你的串口对象的流量控制。这很清楚。但是我想弄清楚你是如何检测流量控制字符已经发送的?我像你一样使用XON XOFF和RTS。不过,我认为它应该是相似的。 0x13,0x11是我期望在serialEvent中看到的字符吗?你怎么能够在代码中检测到这一点? – ril3y

0

(可能是太简单了,但还不如开始的地方......)

正在使用的端口?而不是:

port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 

怎么样:

CommPortIdentifier portIdentifier; 
try { 
    portIdentifier = CommPortIdentifier.getPortIdentifier(name); 
} catch (NoSuchPortException nspe) { 
    // handle? 
} 
if (portIdentifier.isCurrentlyOwned()) { 
    // handle? 
} 
port = portIdentifier.open(owner, 1000); 
if (!(port instanceof SerialPort)) { 
    // handle? 
} 

你吞咽任何异常?

+0

谢谢,但connect()方法的其余部分捕获所有这些异常并打印堆栈跟踪和死亡。 –

0

几个月前我尝试过RXTX并遇到过类似的问题。我建议两件事:

  1. 使用com0com创建一个虚拟comport。启用跟踪记录。比较使用超级终端时的日志与运行自己的程序时的日志。差异将突出显示你在做错什么。在我看来,RXTX的设计是有缺陷的,它的实现相当麻烦(看看它的源代码,真是太麻烦了!)。我已经发布了一个替代库http://kenai.com/projects/jperipheral,但有以下注意事项:它仅限于Windows,并且没有预先构建的二进制文件。这两种情况在不久的将来都会改变。如果您有兴趣尝试使用http://desktopbeautifier.com/Main/contactus发送给我一封电子邮件,我会给您发送一个预建版本。

+1

现在还有[purejavacomm](https://github.com/nyholku/purejavacomm)可用。 – HRJ

2

有一个简单的解决这个问题。这是我所做的:

BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
    String line; 

    while (keepRunning) { 
     try { 
      while ((br.ready()) && (line = br.readLine()) != null) { 
.... 
} 

如果您在阅读之前检查缓冲区是否“准备就绪”,则应该没有问题。

2

好吧,我确实意识到这个线程是非常古老的,但这些解决方案都不适合我。我有同样的问题,我试图解决它,无济于事。然后我对导致问题的原因做了一些研究,并且在不处理串行通信时,它发生在文件末尾。所以,我想我需要为Java应用程序接收的任何内容添加一个结尾,具体来说就是一个行返回(\ n)。果然,它解决了我的问题!希望这可以帮助一个新的,因为我不期望这可以帮助任何人已经在这个线程...

0

如果任何人仍然得到java.io.IOException: Underlying input stream returned zero bytes之后,你已经阅读你的字符使用br.readline()RXTX(偶数当您首先检查,看是否br.readline()== NULL),只是做这个简单的解决方法有一个try/catch:

String line; 
while (true){ 
    try{ 
     line = br.readLine(); 
    }catch(IOException e){ 
     System.out.println("No more characters received"); 
     break; 
    } 
    //Print the line read 
    if (line.length() != 0) 
     System.out.println(line); 
} 

我已经做了一些搜索,看来,这是最好的/最简单的方法来解决这个问题。

编辑:我收回。我试过这个,但仍然有一些问题。我建议直接使用原始InputStream,并使用InputStream.read()实现自己的read/readLine方法。这对我有效。