我一直在使用RXTX大约一年,没有太多问题。我刚刚开始一个新的程序与一个新的硬件进行交互,所以我重用了我在其他项目中使用的connect()方法,但是我有一个我以前从未见过的奇怪问题。
问题
设备工作正常,因为当我连接HyperTerminal时,我发送内容并收到我期望的内容,Serial Port Monitor(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 <my code>
重大问题(再次)
我认为我已经消除了所有可能的硬件问题,那么我的代码或RXTX库可能出现什么问题?
编辑:有趣的事情
当我从java发送一堆应该得到响应的命令后打开HyperTerminal时,所有的响应都会立即显示,好像它们已放在缓冲区某处,但不可用。
编辑2:尝试了一些新的,相同的结果
我运行了代码示例here,结果相同。没有数据进入,但当我切换到一个新程序时,它立刻就出现了。
编辑3
硬件很好,即使是不同的计算机也有同样的问题。我没有使用任何类型的USB适配器。
我也开始使用PortMon,它给了我一些有趣的结果。 HyperTerminal和RXTX没有使用相同的设置,并且RXTX总是轮询端口,不像HyperTerminal,但我仍然看不出会影响这个设置。只要我可以将配置与常量轮询隔离开来,我就会发布我的PortMon日志。
编辑4
过去3个月内某种类型的Windows更新是否可能导致此问题?它曾经搞过我的一个基于MATLAB mex的程序。
编辑5
我还注意到HyperTerminal,RXTX和我发现与设备通信的单独程序之间有些不同的东西(但是没有按我想要的那样做,这就是为什么我要编写我自己的程序)
来自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
答案 0 :(得分:7)
好的,对不起,我花了很长时间才回到这个问题。这就是我让事情发挥作用的方式。
注意:此方法 NOT 适用于所有人,请在复制/粘贴到您自己的代码之前阅读以下内容
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或其他程序不同)。启用每个步骤分为两个步骤。
setFlowControlMode()
方法,并按位或('|
')调用必要的SerialPort.FLOWCONTROL_
常量port.setRTS(true)
)对于有类似问题的其他人,如果这不起作用,我建议
答案 1 :(得分:3)
这个问题有一个更简单的解决方案。这就是我所做的:
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((br.ready()) && (line = br.readLine()) != null) {
....
}
如果在阅读之前检查缓冲区是否“准备就绪”,则应该没有问题。
答案 2 :(得分:2)
好的,我确实意识到这个线程非常陈旧,但这些解决方案都不适用于我。我有同样的问题,我尝试了一切来解决它,无济于事。然后我对导致问题的原因进行了一些研究,并且,当不处理串行通信时,它发生在文件的末尾。所以,我想我需要为Java应用程序接收的内容添加一个结尾,特别是一行返回(\ n)。果然,它解决了我的问题!希望这可以帮助一个新人,因为我不希望这有助于任何已经在这个线程上的人......
答案 3 :(得分: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?
}
你吞下任何例外吗?
答案 4 :(得分:0)
使用com0com创建虚拟comport。启用跟踪日志记录比较使用Hyperterminal时的日志与运行自己的程序时的日志。差异将突出你做错了什么。
在我的拙见中,RXTX的设计存在缺陷,其实现非常错误(看看它的源代码,真是一团糟!)。我在http://kenai.com/projects/jperipheral发布了一个替代库,但有以下注意事项:它仅限Windows,并且没有预先构建的二进制文件。这些都将在不久的将来发生变化。如果您有兴趣尝试使用http://desktopbeautifier.com/Main/contactus向我发送电子邮件,我会向您发送预建版本。
答案 5 :(得分:0)
如果有人在使用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方法。这对我有用。