在RXTX中收到的问题

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

问题

该设备工作正常,因为当我连接HyperTerminal时,我发送东西并收到我期望的东西, 串口监视器 (SPM)反映了这一点。

但是,当我运行简单的HyperTerminal-clone时,我编写了诊断我的主要应用程序的问题,根据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  

最重要的问题(再次)

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

编辑:有趣的东西

当我从Java发送一堆应该得到响应的命令后打开HyperTerminal时,所有的响应都会立即出现,好像它们已经放在某个地方的缓冲区中,但是不可用。

编辑2:尝试了一些新的,相同的结果

我运行了这里找到的代码示例,结果相同。 没有数据进入,但是当我切换到一个新程序时,它立刻就出现了。

编辑3

硬件很好,甚至不同的计算机也有同样的问题。 我没有使用任何类型的USB适配器。

我也开始使用PortMon ,它给了我一些有趣的结果。 HyperTerminal和RXTX没有使用相同的设置,并且RXTX总是轮询端口,与HyperTerminal不同,但我仍然无法看到哪些设置会影响这一点。 只要我可以将配置与常量轮询隔离开来,我就会发布我的PortMon日志。

编辑4

是否有可能在过去3个月中某种类型的Windows更新可能导致此问题? 它曾经搞过我的一个基于MATLAB mex的程序。

编辑5

我还注意到HyperTerminal,RXTX和我发现与设备通信的单独程序之间有些不同的东西(但是没有按我想要的那样做,这就是为什么我要编写我自己的程序)

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

从Serial Port Monitor的帮助文件(转述):

 the indicators display the state of the serial control lines RTS - Request To Send CTS - Clear To Send DTR - Data Terminal Ready 

好的,对不起,我花了很长时间才回到这个问题。 这是我让事情发挥作用的方式。

注意:此方法不适用于所有人,请在复制/粘贴到您自己的代码之前阅读以下内容

 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. 使用串行端口监视程序(如串行端口监视器和/或PortMon (均为Windows))来查看实际发生的情况。
  2. 通过rxtx@qbang.org向RXTX开发人员发送电子邮件(他们非常有帮助)

这个问题有一个更简单的解决方案。 这就是我做的:

 BufferedReader br = new BufferedReader(new InputStreamReader(in)); String line; while (keepRunning) { try { while ((br.ready()) && (line = br.readLine()) != null) { .... } 

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

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

(可能太简单了,但也可能从某个地方开始…)

端口在使用中吗? 而不是:

 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? } 

你吞下任何例外吗?

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

  1. 使用com0com创建虚拟comport。 启用跟踪日志记录 比较使用Hyperterminal时和运行自己程序时的日志。 差异将突出你做错了什么。

  2. 在我看来,RXTX的设计是有缺陷的,它的实现非常错误(看看它的源代码,真是一团糟!)。 我在http://kenai.com/projects/jperipheral上发布了一个替代库,其中包含以下注意事项:它仅限Windows,并且没有预先构建的二进制文件。 这些都将在不久的将来发生变化。 如果您有兴趣尝试使用http://desktopbeautifier.com/Main/contactus给我发送电子邮件,我会发给您一个预建版本。

如果有人仍然得到java.io.IOException: Underlying input stream returned zero bytes使用br.readline()为RXTX读取字符后, java.io.IOException: Underlying input stream returned zero bytes (即使您首先检查是否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方法。 这对我有用。