如何解决串行通信中的 java.io.IOException: Input/output error in nativeavailable 错误?

5

我有一台AllWinner A13的Arm处理器,RAM为512mb,操作系统为Linaro 13.01 Ubuntu(即Debian)。现在我正在为/dev/ttyS0制作串行通信程序。我用netbeans制作了一个简单的双向串行通信程序。在我的处理器上,我将ttyS0的rx-tx短接起来,以进行回路连接检查。也就是说,无论我通过串行端口发送什么,我都会收到返回。但是我遇到了错误。我在我的处理器上安装了openjdk-7和librxtx-java。下面是我的代码和错误。如果有任何想法或解决方案,请建议我。

package serialcomm_linaro;


import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TwoWaySerialComm
{
    public TwoWaySerialComm()
    {
        super();
    }

    void connect ( String portName ) throws Exception
    {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if ( portIdentifier.isCurrentlyOwned() )
        {
            System.out.println("Error: Port is currently in use");
        }
        else
        {
            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);

            if ( commPort instanceof SerialPort )
            {
                SerialPort serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(115200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);

                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();

                (new Thread(new SerialReader(in))).start();
                (new Thread(new SerialWriter(out))).start();

            }
            else
            {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }     
    }

    /** */
    public static class SerialReader implements Runnable 
    {
        InputStream in;

        public SerialReader ( InputStream in )
        {
            this.in = in;
        }

        public void run ()
        {
            byte[] buffer = new byte[1024];
            int len = -1;
            try
            {
                while ( ( len = this.in.read(buffer)) > -1 )
                {
                    System.out.print(new String(buffer,0,len));
                }
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
    }

    /** */
    public static class SerialWriter implements Runnable 
    {
        OutputStream out;

        public SerialWriter ( OutputStream out )
        {
            this.out = out;
        }

        public void run ()
        {
            try
            {                
                int c = 0;
                while ( ( c = System.in.read()) > -1 )
                {
                    this.out.write(c);
                }                
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
    }

    public static void main ( String[] args )
    {
        try
        {
            (new TwoWaySerialComm()).connect("/dev/ttyS0");
        }
        catch ( Exception e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

我的输出如下。在这个输出中,我只发送了123,然后先返回23,然后返回1111...多次,然后出现错误。我想要的不是返回111111...,而是只返回123。

enter code here
RXTX Warning:  Removing stale lock file. /var/lock/LCK..ttyS0
123
23
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111



java.io.IOExcepti on: Input/output error in nativeavailable
        at gnu.io.RXTXPort.nativeavailable(Native Method)
        at gnu.io.RXTXPort$SerialInputStream.read(RXTXPort.java:1429)
        at gnu.io.RXTXPort$SerialInputStream.read(RXTXPort.java:1341)
        at serialcomm_linaro.TwoWaySerialComm$SerialReader.run(TwoWaySerialComm.java:66)
        at java.lang.Thread.run(Thread.java:722)
1个回答

5
我之前没有尝试过在RXTX中进行串行通信的回环测试,但这不应该有影响。唯一看起来有点可疑的是您将输入流实例传递给SerialReader的部分。我建议您将SerialPort实例传递给两个构造函数,并且每次需要读取/写入端口的流时,使用流getter,例如用于读取:
 public static class SerialReader implements Runnable 
{
    SerialPort serialPort;

    public SerialReader ( SerialPort serialPort )
    {
        this.serialPort = serialPort;
    }

    public void run ()
    {
        byte[] buffer = new byte[1024];
        int len = -1;
        try
        {
            while ( ( len = serialPort.getInputStream().read(buffer)) > -1 )
            {
                System.out.print(new String(buffer,0,len));
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }            
    }
}

请反馈意见。

更新:

从我的个人 经验 来看,RXTX 是一个有缺陷的解决方案。然而,这并不意味着这种情况是由潜在的 RXTX bug 导致的。可能是因为串口没有正确设置,但在您的情况下,它是一个标准端口名称和标准连接参数。作为一个很长的尝试,尝试将波特率 115200 替换为 9600,但那可能不会有帮助。我可以提供三条路径:

  • 尝试调试 RXTX 代码-您可能会更了解发生了什么
  • 阅读串行线故障排除
  • 考虑其他 Java 解决方案进行串行通信,例如 JSSC 而不是 RXTX。

更新:

抱歉,我之前疏忽了。JSSC本地库(.so,.dll)在jssc.jar文件内部,因此会自动加载。而RXTX的本地库位于jar文件外部,所以需要设置java.library.path系统属性,以便JVM找到并加载它们,否则将会出现UnsatisfiedLinkError错误。
您可以双击打开JSSC jar文件,它会在压缩文件管理器中打开,因为它实际上是一个zip文件。与RXTX一样,您会注意到本地库文件按操作系统命名的目录进行组织(如windows、linux,RXTX还有Mac_OS_X和Solaris)。
在这些目录中,有本地库文件,即.so、dll和.jnilib类型的文件,它们以计算机体系结构命名。这是该词的更广泛含义,这些都是指令集架构(ISA)的简短代码。指令集定义了CPU的指令(命令)集。换句话说,有许多不同的CPU型号(比如您的AllWinner A13),符合相同的指令集。本地库源代码编译生成可执行文件(.so,...),其中包含来自同一指令集的一堆指令。
你使用JSSC时遇到了UnsatisfiedLinkError错误的原因可能是您正在使用不支持的架构,并且对应的本地库正在搜索不存在的目录中。JSSC的ISA简码,也是这些目录的名称包括x86PPC架构,32位和64位变体。RXTX有许多其他架构,但我认为没有一个等同于ARMv7,这是您的AllWinner A13 CPU的ISA。

您可以通过在终端中执行此命令来确定您的架构

uname -m

在我的Linux上,它输出:
x86_64

这意味着它是一个64位Intel 8086架构。JSSC和RXTX都实现了这个架构。如果您的架构没有被实现(支持),那么您就不能使用这些库来连接该计算机上的串口。在这种情况下,您必须编写自己的代码或获取适当的实现。
如果架构匹配仍然存在本地错误,则可以尝试重新编译本地库源代码。这些源代码均提供给RXTXJSSC
更新:
如果你的架构是 armv7l,那么这意味着 JSSC、RXTX 和 JavaComm(粗略地说,RXTX 的“祖先”)在当前状态下对你的情况无用。

我没有找到其他开源的Java串口通信库。如果这是真的,你需要编写符合上述库接口的本地库,以使它们有用。换句话说,你需要编写一个C程序(类似于12),具有串口通信JNI接口到Java库的功能。

就答案的完整性而言,我要提到一个商业产品SerialIO,它支持一些ARM架构(不知道你的是否在其中)。但如果你决定使用这个解决方案,你可以随时向他们的支持团队发送查询。


感谢您的回复。在这里,我使用环回场景来测试通过串口发送的任何内容是否会返回给我。在将此程序用于激光和X射线部分之前,我必须进行彻底的检查和测试。 - Jay
1
感谢您早日回复并帮助我。现在我会逐一尝试您的选项。 - Jay
1
UnsatifsfiedLinkError表示代码尝试使用一些外部库(对于Linux是.so,对于Windows是.dll),但找不到它们。您需要找到这些文件所在的目录并将其设置为系统属性。请参见此处的说明。但很奇怪,上次我使用它时不需要这样做。我得看看,请给我反馈。 - linski
我在我的应用程序中使用了jSSC-0.9.0-Release。但是在jSSC-0.9.0-Release(版本)中,没有任何.dll或.so文件。我知道在Linux中放置.jar文件和.so文件的位置。我还将jssc.jar放在/usr/lib/jvm/openJdk-7/jre/lib/ext/jssc.jar中,并将.so文件放在此路径/usr/lib/jvm/openJdk-7/jre/lib/arm/中。但是我没有jssc的.so文件。那么,我在哪里可以获取(或下载)jSSC-0.9.0-Release版本和arm处理器的.so文件?请帮帮我。 - Jay
rxtx工作得很好。主要问题是我的ARM处理器的串口处于调试模式。所以我在我的脚本文件中进行更改,使用RXTx正常工作。我使用以下命令安装了rxtx。sudo apt-get install librxtx-java。感谢您的帮助并向我提出建议,您给了我新的思路来思考。 - Jay
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接