7

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

问题

该设备工作正常,因为当我与超级终端连接时,我发送并接收我期望的东西,而串行端口监视器(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:尝试了一些新的东西,同样的结果

我运行了此处找到的代码示例,结果相同。没有数据进来,但是当我切换到一个新程序时,它一下子就进来了。

编辑 3

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

我也开始使用PortMon,它给了我一些有趣的结果。超级终端和 RXTX 没有使用相同的设置,并且 RXTX 总是轮询端口,这与超级终端不同,但我仍然看不到什么设置会影响这一点。一旦我可以将配置与持续轮询隔离开来,我就会发布我的 PortMon 日志。

编辑 4

过去 3 个月内的某种 Windows 更新是否可能导致这种情况?它曾经把我的一个基于 MATLAB mex 的程序搞砸了。

编辑 5

我还注意到 HyperTerminal、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
4

6 回答 6

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()方法,并按位或(' |')必要的SerialPort.FLOWCONTROL_常量
  2. 将适当的流控制设置为 true 或 false(就像我所做的那样port.setRTS(true)

对于其他有类似问题的人,如果这不起作用,我建议

  1. 使用串行端口监控程序,如Serial Port Monitor和/或PortMon(都是 Windows)来查看实际发生的情况。
  2. 通过 rxtx@qbang.org 向 RXTX 开发人员发送电子邮件(他们非常有帮助)
于 2009-10-28T23:00:50.420 回答
3

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

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

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

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

于 2012-06-14T08:59:25.950 回答
2

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

于 2014-08-02T06:55:41.523 回答
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?
}

你吞下任何例外吗?

于 2009-09-08T00:54:01.287 回答
0

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

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

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

于 2009-09-08T03:47:42.170 回答
0

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

于 2014-09-18T16:06:56.953 回答