首页 文章

在RXTX中收到的问题

提问于
浏览
7

我已经使用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 回答

  • 0

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

    Note: This method will NOT work for everyone, please read below before copy/pasting into your own code

    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或其他程序不同) . 启用每个过程分为两个步骤 .

    • 一旦有了SerialPort对象,就调用 setFlowControlMode() 方法,并按位OR(' | ')调用必要的 SerialPort.FLOWCONTROL_ 常量

    • 将适当的流量控制设置为true或false(就像我使用 port.setRTS(true) 一样)

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

    • 使用串行端口监视程序(如Serial Port Monitor和/或PortMon(均为Windows))来查看实际发生的情况 .

    • 通过rxtx@qbang.org向RXTX开发人员发送电子邮件(非常有帮助)

  • 2

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

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

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

  • 2

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

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

    你吞下任何例外吗?

  • 7

    几个月前我尝试过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给我发送电子邮件,我会发给您一个预建版本 .

  • 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);
    }
    

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

    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.

相关问题