我已经使用RXTX大约一年了,没有太多问题 . 我刚开始一个新的程序与一个新的硬件进行交互,所以我重用了我在其他项目中使用的connect()方法,但我有一个我以前从未见过的奇怪问题 .
The Problem
该设备工作正常,因为当我连接HyperTerminal时,我发送东西并收到我期望的东西,Serial Port Monitor(SPM)反映了这一点 .
但是,当我运行简单的HyperTerminal-clone时,我编写了诊断我的主要应用程序的问题,根据SPM发送字节,但没有收到任何内容,我的SerialPortEventListener永远不会触发 . 即使我在主循环中检查可用数据, reader.ready()
也会返回 false
. 如果我忽略了这个检查,那么我会得到一个例外,详情如下 .
Relevant section of connect() method
// 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();
Exception
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>
The big question (again)
我想我已经消除了所有可能的硬件问题,那么我的代码或RXTX库可能出现什么问题?
Edit: something interesting
当我从Java发送一堆应该得到响应的命令后打开HyperTerminal时,所有的响应都会立即出现,好像它们已经放在某个地方的缓冲区中,但是不可用 .
Edit 2: Tried something new, same results
我运行了代码示例here,结果相同 . 没有数据进入,但是当我切换到一个新程序时,它立刻就出现了 .
Edit 3
硬件很好,甚至不同的计算机也有同样的问题 . 我没有使用任何类型的USB适配器 .
我也开始使用PortMon,而且's giving me some interesting results. HyperTerminal and RXTX are not using the same settings, and RXTX always polls the port, unlike HyperTerminal, but I still can'看看哪些设置会影响这个 . 只要我可以将配置与常量轮询隔离开来,我就会发布我的PortMon日志 .
Edit 4
是否有可能在过去3个月中某种类型的Windows更新可能导致此问题?它曾经搞过我的一个基于MATLAB mex的程序 .
Edit 5
我还注意到HyperTerminal,RXTX和我发现与设备通信的单独程序之间有些不同的东西(但是没有按我想要的那样做,这就是为什么我要编写我自己的程序)
-
超级终端 - 设置为无流量控制,但串行端口监视器的RTS和DTR指示灯为绿色
-
其他程序 - 不确定它认为是什么设置's using, but only SPM' s 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
6 回答
好的,对不起,我花了很长时间才回到这个问题 . 这是我让事情发挥作用的方式 .
Note: This method will NOT work for everyone, please read below before copy/pasting into your own code
所以,就我而言,问题是我的特定设备需要RTS流控制 . 其他设备可能需要不同的东西(CTS,XON / XOFF),因此请检查该设备的手册 . 默认情况下,RXTX禁用所有流量控制机制(与Hypertrm或其他程序不同) . 启用每个过程分为两个步骤 .
一旦有了SerialPort对象,就调用
setFlowControlMode()
方法,并按位OR('|
')调用必要的SerialPort.FLOWCONTROL_
常量将适当的流量控制设置为true或false(就像我使用
port.setRTS(true)
一样)对于有类似问题的其他人,如果这不起作用,我建议
使用串行端口监视程序(如Serial Port Monitor和/或PortMon(均为Windows))来查看实际发生的情况 .
通过rxtx@qbang.org向RXTX开发人员发送电子邮件(非常有帮助)
这个问题有一个更简单的解决方案 . 这就是我做的:
如果在阅读之前检查缓冲区是否“准备就绪”,则应该没有问题 .
好吧,我确实意识到这个线程非常陈旧,但这些解决方案都不适用于我 . 我有同样的问题,我尝试了一切来解决它,无济于事 . 然后我做了一些关于导致问题的原因的研究,并且,当不处理串行通信时,它发生在文件的末尾 . 所以,我想我需要为Java应用程序接收的内容添加一个结尾,特别是一行返回(\ n) . 果然,它解决了我的问题!希望这有助于新人,因为我不希望这有助于任何已经在这个线程上的人......
(可能太简单了,但也可能从某个地方开始...)
端口在使用中吗?而不是:
关于什么:
你吞下任何例外吗?
几个月前我尝试过RXTX并遇到了类似的问题 . 我建议两件事:
使用com0com创建虚拟comport . 启用跟踪日志记录比较使用Hyperterminal时和运行自己的程序时的日志 . 差异将突出你做错了什么 .
在我的拙见中,RXTX 's design is flawed and its implementation is quite buggy (take a look at its source-code, what a mess!). I' ve在http://kenai.com/projects/jperipheral发布了一个替代库,其中包含以下警告:它仅限Windows,并且没有预先构建的二进制文件 . 这些都将在不久的将来发生变化 . 如果您有兴趣尝试使用http://desktopbeautifier.com/Main/contactus给我发送电子邮件,我会发给您一个预建版本 .
如果有人在你之后仍然得到
java.io.IOException: Underlying input stream returned zero bytes
使用br.readline()为RXTX读取你的角色(即使你先检查是否br.readline()== null),只需使用try / catch进行这个简单的修复:我已经做了一些搜索,看起来这是解决这个问题的最好/最简单的方法 .
EDIT : I take that back. I tried this and still ended up having some problems. I'd recommend working with the raw InputStream directly, and implementing your own read/readLine method using InputStream.read(). That worked for me.