Linux系统下运用开源RXTX库实现JAVA串口通讯

概述
    一个嵌入式系统通常需要通过串口与其主控系统进行全双工通讯,譬如我们的环境在线监测系统下的各类监测仪器如流量计,PH计,电机状态检测仪器就需要定时的接受控制系统发送来的查询和控制信息,并将执行结果或查询结果发送回控制系统。

一.java的串口通讯扩展包javax.comm
   Sun的J2SE中并没有直接提供任何一种串行通讯协议的开发包,而是以独立的jar包形式发布在java.sun.com网站上----即comm.jar,称之为Javatm Communications API,它是J2SE的标准扩展。comm.jar并不是最近才有,早在1998年时,sun就已经发布了这个开发包。comm.jar分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。目前sun发布的comm.jar只有Windows和Solaris平台两个版本,如果需要Linux平台下的,可以在http://users.frii.com/jarvi/rxtx/index.html找到。
  所有的comm API位于javax.comm包下面。其中比较重要的类和接口如下,
        javax.comm.CommDriver
        javax.comm.CommPort
        javax.comm.ParallelPort
        javax.comm.SerialPort
        javax.comm.CommPortIdentifier
        javax.comm.CommPortOwnershipListener
        javax.comm.ParallelPortEvent
        javax.comm.SerialPortEvent
        javax.comm.ParallelPortEventListener (extends java.util.EventListener)
        javax.comm.SerialPortEventListener (extends java.util.EventListener)
        javax.comm.NoSuchPortException
        javax.comm.PortInUseException
        javax.comm.UnsupportedCommOperationException 
  通讯方式,CommPort的输入流的读取方式与文件的输入流有些不一样,那就是可能永远不知这个InputStream何时结束,除非对方的OutputStream发送了一个特定数据表示发送结束,收到这个特定字符后,再行关闭InputStream。而comm.jar提供了两种灵活的方式让我们读取数据:
        1.轮询方式(Polling)
        2.监听方式(listening)。Comm API支持标准的Java Bean型的事件模型。也就是说,可以使用类似AddXXXListener这样的方法为一个串口注册自己的监听器,以监听方式进行数据读取。


二.RXTX项目
    RXTX是一个提供串口和并口通信的开源java类库,由该项目发布的文件均遵循LGPL协议。该项目的主页位于http://users.frii.com/jarvi/rxtx/index.html。
    RXTX项目提供了Windows,Linux,Mac os X,Solaris操作系统下的兼容javax.comm串口通讯包API的实现,为其他开发人员在此类系统下开发串口应用提供了相当的方便。
    针对x86体系结构的Linux操作系统平台,RXTX的部署包括下面几个文件:
    * RXTXcomm.jar        RXTX自己的javax.comm实现
    * librxtxSerial.so    由RXTXcomm.jar调用的底层串口库文件
    * librxtxParallel.so    由RXTXcomm.jar调用的底层并口库文件
    * javax.comm.properties    RXTX驱动的类配置文件,内容是Driver=gnu.io.RXTXCommDriver
    

三.RXTX的配置方法及部分源代码
    为了使我们的程序使用RXTX作为串口通讯的底层API,需要配置它的环境。仍然以Linux系统平台为例:
    1.复制librxtxSerial.so,librxtxParallel.so到$JAVA_HOME/lib/$(ARCH)/
    2.复制RXTXcomm.jar到$JAVA_HOME/ext/,或在应用程序启动的CLASSPATH中包含RXTXcomm.jar
    3.定义驱动类后将javax.comm.properties放在应用程序的根目录下
    RXTX的使用上与sun提供的comm.jar基本相同,编程时最明显的不同是要包含的包名由javax.comm.*改成了gnu.io.*。下面是我们环境监测系统中封装的一个232串口驱动类部分源代码,使用RXTX作为串口通讯类库。
    
    下面的driver232类是监测点子系统以开源的rxtx项目提供的串口通讯扩展包为基础自己封装的一个RS232串口驱动类库(部分代码),为系统的其它部分提供简易的访问本机串口的方法。类的前面部分是各个串口参数的声明,后面是读取,写入串口的具体方法实现。

引入 rxtx java 类库包RXTXcomm.jar

package com.kasumi.site.physicalservice;

//import javax.comm.*;
import gnu.io.*;
import java.io.*;
import com.kasumi.util.format.*;
import java.awt.*;
import java.awt.event.*;
import org.apache.log4j.*;
import com.kasumi.site.infrastructure.*;
import com.kasumi.util.misc.*;


 实现已定义好的 ISerial 接口,提供 ISerial 规定的各个方法的实现。

/**
 *

该程序实现 ISerial 接口, 提供 RS-232C 的驱动
 * @author lhh
 * @version 3.0
 * @see com.kasumi.site.publicservice.measuredev
 */
public class driver232
    implements ISitePlugin, IPoolable, ISiteConfigurable, ISerial
{
    /** Clear all buffer data before lent out */
    private boolean clearBufferData = true;


类的前面部分是各个串口参数的声明,在本类中也提供了设置与获取这些参数的方法,运用Ioc技术在运行时根据配置文件plugin.conf的配置注入这些参数,以利于各个不同监测仪器的串口通讯参数设置。

    /** Serial default setting */
    private String portName = "COM1";
    private int baudRate = 2400;
    private int flowControlIn = SerialPort.FLOWCONTROL_NONE;
    private int flowControlOut = SerialPort.FLOWCONTROL_NONE;
    private int databits = SerialPort.DATABITS_8;
    private int stopbits = SerialPort.STOPBITS_1;
    private int parity = SerialPort.PARITY_NONE;
    private ISiteContext siteContext = null;

    // private SerialParameters parameters;
    private OutputStream os;
    private InputStream is;
    private CommPortIdentifier portId;
    private SerialPort sPort;
    private boolean open;
    private String poolName;
    static Logger logger = Logger.getLogger(driver232.class);
    private String domainName=null;


设置串口连接参数的方法

    public void setConnectionParameters() throws IOException
    {
        // Set connection parameters, if set fails return parameters object
        // to original state.
        try
        {
            sPort.setSerialPortParams(baudRate,databits,stopbits,parity);
        }
        catch (UnsupportedCommOperationException e)
        {
            throw new IOException(getDomainName() + ":" + e.toString());
        }

        // Set flow control.
        try
        {
            sPort.setFlowControlMode(flowControlIn|flowControlOut);
        }
        catch (UnsupportedCommOperationException e)
        {
            throw new IOException(getDomainName() + ":" + e.toString());
        }
    }


用已定义好的连接参数"打开"串口连接

    /*
     *    Open the port
     */
    public void openConnection() throws IOException
    {
        try
        {
            portId = CommPortIdentifier.getPortIdentifier(portName);
        }
        catch (NoSuchPortException e)
        {
            throw new IOException(getDomainName() + ":" + e.toString());
        }

        try
        {
            sPort = (SerialPort)portId.open("SerialCom", 30000);
        }
        catch (PortInUseException e)
        {
            throw new IOException(getDomainName() + ":" + e.toString());
        }

        try
        {
            setConnectionParameters();
        }
        catch (IOException e)
        {
            sPort.close();
            throw e;
        }

        try
        {
            os = sPort.getOutputStream();
            is = sPort.getInputStream();
        }
        catch (IOException e)
        {
            sPort.close();
            throw new IOException(getDomainName() + ":" + e.toString());
        }

        sPort.notifyOnDataAvailable(true);
        open = true;
    }


一次串口通讯结束后关闭当前的串口连接,以让系统其它监测仪器复用串口

    /**
     * Close the port and clean up associated elements.
     * @param
     * @return void
    */
    public void closeConnection()
    {
        // If port is alread closed just return.
        if (!open)
        {
            return;
        }

        if (sPort != null)
        {
            try
            {
                // close the i/o streams.
                os.close();
                is.close();
            }
            catch (IOException e)
            {
                logger.error(e.toString());
            }

            // Close the port.
            sPort.close();

            //portId.removePortOwnershipListener(this);
        }

        open = false;
    }


读取串口的方法。读取与写入串口的方法在本类中提供了多个,因为系统中各个仪器的串口通讯要求不同,读取和写入的方法在实现上有一些差异,所以提供了多个方法以适应这类需求

    /**
     *

在指定的时间内从串口读取指定长度的数据


     *
注意: 如果在指定的时间内未能读取指定长度的数据,
     * 

      那么将返回实际读取的数据以及对应的长度


     * @param data 用于存放从串口读取的数据的缓冲区
     * @param rdLen 指定要读取的数据的长度
     * @param timeout 指定读取数据的时间长度
     * @return 实际读取的数据的长度
     * @throws  IOException 如果读串口时低层 API 抛出异常
     */
    public int read(byte[] data, int rdLen, int timeout)
        throws IOException {

        try {
            if (!sPort.isReceiveTimeoutEnabled()){
                sPort.enableReceiveTimeout(timeout);
            }
        } catch (UnsupportedCommOperationException e) {
            throw new IOException(e.toString());
        }

        int offset = 0;
        int curRdLen = rdLen;
        long start = System.currentTimeMillis();
        long end = start + timeout;

        while (offset < rdLen && System.currentTimeMillis() < end) {
        //while (offset < rdLen) {
            try {
                int len = is.read(data, offset, curRdLen);
                offset += len;
                curRdLen -= len;
            } catch (IOException e) {
                throw e;
            }
        }
        if (offset > 0)
        {
            HexDumper.dumpLogger(logger,"<< ", data, 0, offset);
        }
        return offset;
    }


往串口写数据的方法

   /**
     * 写串口数据
     *
     * @param outdata 写出数据
     * @param outoffset 开始写出偏移量
     * @param outlen 写出长度
     * @return 实际读入的数据长度
     */
    public int writeData(byte[] outdata, int outoffset, int outlen)
        throws IOException
    {
        HexDumper.dumpLogger(logger,">> ",outdata, outoffset, outlen);
        try
        {
            os.write(outdata, outoffset, outlen);
            os.flush();
        }
        catch (IOException e)
        {
            throw new IOException(getDomainName() + ":" + e.toString());
        }

        return outlen;
    }

}

  TAG  rxtx  java  串口
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Java中,可以使用JavaComm API来实现串口通讯。以下是实现串口通讯的基本步骤: 1. 下载并安装JavaComm API,该API包括了访问串口的类和方法。 2. 导入JavaComm API。 ```java import javax.comm.*; ``` 3. 使用CommPortIdentifier类获取可用的串口。 ```java Enumeration portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { System.out.println(portId.getName()); } } ``` 4. 打开选定的串口。 ```java CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("COM1"); SerialPort serialPort = (SerialPort) portId.open("MyApp", 2000); ``` 5. 配置串口参数,例如波特率、数据位、停止位、奇偶校验位等。 ```java serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); ``` 6. 获取输入输出流并进行数据传输。 ```java InputStream in = serialPort.getInputStream(); OutputStream out = serialPort.getOutputStream(); out.write("Hello World".getBytes()); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println(new String(buffer, 0, len)); ``` 7. 关闭串口。 ```java serialPort.close(); ``` 以上是Java实现串口通讯的基本步骤,根据具体需求可以进行进一步的修改和扩展。 ### 回答2: Java可以通过使用第三方实现串口通讯。其中最常用的之一是RXTX,它可以在 Java 平台上提供串口通讯的功能。 RXTX是一个开源串口通讯,支持跨平台运行。以下是实现串口通讯的一般步骤: 1. 添加RXTX:首先,你需要下载RXTX的最新版本。然后,将的JAR文件添加到你的Java项目的classpath中。 2. 打开串口:使用RXTX提供的类,打开你要进行通讯串口。你可以选择串口的名称、波特率和其他参数。 3. 设置串口监听器:通过注册一个监听器来监听串口的输入数据。这样,当串口接收到数据时,你就可以在监听器中处理它。 4. 发送数据:使用串口对象的输出流,你可以将数据发送到串口设备上。 5. 接收数据:使用串口对象的输入流,你可以读取从串口设备接收到的数据。 6. 关闭串口:当你完成通讯后,要记得关闭串口,释放资源。 需要注意的是,在使用RXTX之前,你需要在你的操作系统上安装相应的驱动程序。具体的驱动程序安装方法和操作系统有关。 总结起来,通过使用RXTX,我们可以在Java平台上实现串口通讯。我们可以打开和关闭串口,发送和接收数据。这为与硬件设备的交互提供了便利,例如与传感器、机器人或其他串口设备进行通讯。 ### 回答3: 串口通讯Java中可以通过Java的Comm API来实现。下面是一个简单的示例来说明如何使用Java实现串口通讯。 1. 首先,我们需要下载并安装Java Comm API。可以从Oracle官方网站上下载相应版本的Java Comm API。 2. 在Java代码中,我们需要导入相应的类,包括javax.comm包中的SerialPort和CommPortIdentifier类。 3. 然后,我们需要通过调用CommPortIdentifier类的getPortIdentifiers()方法获取当前系统中可用的串口列表。 4. 对于每个可用的串口,我们可以调用CommPortIdentifier类的方法来获得串口对象。 5. 通过打开串口,我们可以得到一个串口输入流和一个串口输出流。 6. 通过串口输出流,我们可以发送数据。通过串口输入流,我们可以接收数据。 7. 当需要关闭串口时,我们需要调用close()方法来关闭串口。 下面是一个简单的示例代码: ``` import javax.comm.*; public class SerialCommunication { public static void main(String[] args) { CommPortIdentifier portId; try { // 获取当前系统中可用的串口列表 Enumeration portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { // 获取串口对象 portId = (CommPortIdentifier) portList.nextElement(); // 判断串口类型 if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { // 打开串口 SerialPort serialPort = (SerialPort) portId.open("SerialCommunication", 2000); // 配置串口参数 serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // 获取串口输入流和输出流 InputStream in = serialPort.getInputStream(); OutputStream out = serialPort.getOutputStream(); // 使用串口输出流发送数据 out.write("Hello, Serial Port!".getBytes()); out.flush(); // 接收串口输入流数据 byte[] buffer = new byte[1024]; int len = in.read(buffer); String receivedData = new String(buffer, 0, len); System.out.println("Received Data: " + receivedData); // 关闭串口 serialPort.close(); } } } catch (Exception e) { e.printStackTrace(); } } } ``` 这就是一种基本的方法来实现Java中的串口通讯。当然,还有其他的一些高级应用,比如监听串口数据事件等。 希望这个简单的示例可以帮助您理解在Java中如何实现串口通讯

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值