Rxtx串口通信

最近项目中需要调用串口激光扫码枪,这也是我首次在java项目中实现调用硬件的功能,所以特别感兴趣,经过研究后,在这把实现串口激光扫码枪的实现过程和大家说一下:

好了,下面我们要开始介绍详细的开发过程。
第一、首先我们要安装硬件驱动,这个产品官网上都有,而且产品都有详细的用户手册,自己可以百度下载,这里就不再细讲。官网地址:http://www.mindeo.cn/view_product.php?id=87&cid=71###

第二、安装串口中文输出工具。推荐使用COM_Text V2.0。
COM_Text软件可以仿真串行键输入的效果,将由串口(COM)或USB虚拟串口(USB Virtual COM)获得的数据信息(ASCII码)转换成字符(Unicode、简体中文、日文等)格式,在.txt文本文件或.doc微软Word文件上输出。 所连接的设备(如条码阅读器)使用的必须是RS232串口电缆线或USB电缆线(USB类型必须设置为“USB虚拟串口”)。无论PC机处于何种输入法,都可正确输出中英文等字符。
第三、工具我们都准备好了,我们现在需要的是连接扫码枪,这里我要说明一下,因为我用的是笔记本电脑,大部分笔记本电脑已经不支持串口,所以我用了一根串口转USB线,大家可以根据自己的实际情况进行选择,当然也可以直接使用台式机,那就不需要考虑这件事了。
第四步、扫码枪连到电脑之后,打开COM_Text软件,如果驱动安装正确,此工具会读出几个重要参数。端口名称、波特率、数据位、停止位、无奇偶校验等属性,这些属性后边我们用的到,这是属性也是我们连接扫码枪的必用参数。
第五步、RXTX是个提供串口和并口通信的开源java类库,由该项目发布的文档均遵循LGPL协议。针对x86体系结构的Linux操作系统平台,RXTX的部署包括下面几个文档:* RXTXcomm.jar RXTX自己的实*librxtxSerial.so 由调用的底层串口库文档* librxtxParallel.so 由RXTXcomm.jar调用的底层并口库文档驱动的类配置文档,内容是Driver=gnu.io.RXTXCommDriver。我用的是mfz-rxtx-2.2-20081207-win-x64这个版本。当你选择的时候,必须下载使用适配你电脑的版本,我的电脑是win10 64位专业版,所以必须得使用x64的项目,里面包含两个重要的dll文件,即rxtxParallel.dll、rxtxSerial.dll,我们需要把这两个文件放到C:\Windows\System32下。
第六步、我们靠开始开发了,入口函数代码如下,
package cn.com.checknull.rxtx.main;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import cn.com.checknull.rxtx.bean.SerialPortParms;
import cn.com.checknull.rxtx.listener.SerialReader;

public class SerialPortMain implements Observer {

    private  List<String> mListComName; // 集合:串口名字
    private  SerialReader sr = new SerialReader();

    public static void main(String[] args) {
        new SerialPortMain();       
    }

    public SerialPortMain() {
        searchSerialPort();  //搜索串口
        connectSerialPort(); //连接串口
        sendOrder();         //传数据
    //  sr.close();          //关闭串口
    }

    private  void searchSerialPort() {
        mListComName = new ArrayList<String>();
        CommPortIdentifier portId;
        Enumeration enumeration = CommPortIdentifier.getPortIdentifiers();
        while (enumeration.hasMoreElements()) {
            portId = (CommPortIdentifier) enumeration.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                mListComName.add(portId.getName());
            }
        }
    }

    private  void connectSerialPort() {
        String comName;
        if (mListComName.size() > 0) {
            comName = mListComName.get(0);

            String PortName = comName;
            String rate_value = SerialPortParms.RATE[0];
            String databit_value = SerialPortParms.DATABIT[0];
            String stopbit_value = SerialPortParms.STOPBIT[0];

            HashMap<String, Comparable> params = new HashMap<String, Comparable>();
            int parityInt = SerialPort.PARITY_NONE;
            params.put(SerialReader.PARAMS_PORT, PortName);          // 端口名称
            params.put(SerialReader.PARAMS_RATE, rate_value);        // 波特率
            params.put(SerialReader.PARAMS_DATABITS, databit_value); // 数据位
            params.put(SerialReader.PARAMS_STOPBITS, stopbit_value); // 停止位
            params.put(SerialReader.PARAMS_PARITY, parityInt);       // 无奇偶校验
            params.put(SerialReader.PARAMS_TIMEOUT, 100);            // 设备超时时间 1秒
            params.put(SerialReader.PARAMS_DELAY, 100);              // 端口数据准备时间 1秒
            try {
                sr.open(params);
                sr.addObserver(SerialPortMain.this);
                System.out.println(PortName + ":已经打开");
            } catch (Exception e1) {
                System.out.println("端口被占用");
            }
        }
    }


    private void sendOrder() {
        byte []all = new byte[]{0x00,0x01,0x02};
        if ( all!= null) {
            sr.start();
            sr.run(all);
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        byte []date = (byte[])arg;
        System.out.println(Arrays.toString(date));      
    }
}
package cn.com.checknull.rxtx.listener;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.TooManyListenersException;

public class SerialReader extends Observable implements Runnable,
        SerialPortEventListener {
    static CommPortIdentifier portId;
    int delayRead = 100;
    int numBytes; //
    private static byte[] readBuffer = new byte[1024]; //
    static Enumeration portList;
    InputStream inputStream;
    OutputStream outputStream;
    static SerialPort serialPort;
    HashMap serialParams;
    Thread readThread;

    boolean isOpen = false;

    public static final String PARAMS_DELAY = "delay read"; //
    public static final String PARAMS_TIMEOUT = "timeout"; // 超时时间
    public static final String PARAMS_PORT = "port name"; // 端口名称
    public static final String PARAMS_DATABITS = "data bits"; //
    public static final String PARAMS_STOPBITS = "stop bits"; //
    public static final String PARAMS_PARITY = "parity"; // 奇偶校验
    public static final String PARAMS_RATE = "rate"; //
    private HashMap<Byte, byte[]> map;

    public boolean isOpen() {
        return isOpen;
    }

    /**
     * 初始化端口操作的参数.
     * 
     * @throws SerialPortException
     * 
     * @see
     */
    public SerialReader() {
        isOpen = false;
    }

    public void open(HashMap params) throws NoSuchPortException,
            PortInUseException, IOException, UnsupportedCommOperationException,
            TooManyListenersException {
        serialParams = params;
        if (isOpen) {
            close();
        }
        /* try { */
        // 参数初始
        int timeout = Integer.parseInt(serialParams.get(PARAMS_TIMEOUT)
                .toString());
        int rate = Integer.parseInt(serialParams.get(PARAMS_RATE).toString());
        int dataBits = Integer.parseInt(serialParams.get(PARAMS_DATABITS)
                .toString());
        int stopBits = Integer.parseInt(serialParams.get(PARAMS_STOPBITS)
                .toString());
        int parity = Integer.parseInt(serialParams.get(PARAMS_PARITY)
                .toString());
        delayRead = Integer.parseInt(serialParams.get(PARAMS_DELAY).toString());
        String port = serialParams.get(PARAMS_PORT).toString();
        // 打开端口
        portId = CommPortIdentifier.getPortIdentifier(port);
        serialPort = (SerialPort) portId.open("SerialReader", timeout);
        inputStream = serialPort.getInputStream();
        serialPort.addEventListener(this);
        serialPort.notifyOnDataAvailable(true);
        serialPort.setSerialPortParams(rate, dataBits, stopBits, parity);
        isOpen = true;
        serialParams.clear();
    }

    public void run() {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            outputStream = serialPort.getOutputStream();
        } catch (IOException e) {
        }
        try {
            readThread = new Thread(this);
            readThread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run(byte[] message) {
        try {
            Thread.sleep(4);
        } catch (InterruptedException e) {
        }
        try {
            if (message != null) {
                System.out.println("run message:" + message);
                outputStream.write(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() {
        if (isOpen) {
            try {
                serialPort.notifyOnDataAvailable(false);
                serialPort.removeEventListener();
                inputStream.close();
                serialPort.close();
                isOpen = false;
            } catch (IOException ex) {
                // "关闭串口失败";
                ex.printStackTrace();
            }
        }
    }

    @Override
    public void serialEvent(SerialPortEvent event) {
        String strs[] = null;
        try {
            Thread.sleep(delayRead);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        switch (event.getEventType()) {
        case SerialPortEvent.BI:   // 10  Break interrupt,通讯中断
        case SerialPortEvent.OE:   // 7   Overrun error,溢位错误
        case SerialPortEvent.FE:   // 9   Framing error,传帧错误
        case SerialPortEvent.PE:   // 8   Parity error,校验错误
        case SerialPortEvent.CD:   // 6   Carrier detect,载波检测
        case SerialPortEvent.CTS:  // 3   Clear to send,清除发送
        case SerialPortEvent.DSR:  // 4   Data set ready,数据设备就绪
        case SerialPortEvent.RI:   // 5   Ring indicator,响铃指示
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 Output buffer is empty,输出缓冲区清空
            break;
        case SerialPortEvent.DATA_AVAILABLE: // 1 Data available at the serial port,端口有可用数据。读到缓冲数组,输出到终端
            try {
                // 多次读取,将所有数据读
                while (inputStream.available() > 0) {
                    readBuffer = new byte[inputStream.available()];
                    numBytes = inputStream.read(readBuffer);
                }

                // 打印接收到的字节数据
                //for (int i = 0; i < numBytes; i++) {
                strs = changeMessage(readBuffer, numBytes);
                //}
                System.out.print("条形码为:");
                for (int i = 0 ;i < strs.length; i++) {
                    System.out.print(strs[i]);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        }
    }

    // 通过observer pattern将收到的数据给observer
    // 将buffer中的空字节删除后再发送更新消息通知观察者
    public String[] changeMessage(byte[] message, int length) {
        boolean flag = false;
        byte type = message[3];
        setChanged();
        notifyObservers(message);

        List<String> list = new ArrayList<String>();
        for (int i = 0; i < message.length; i++) {
            String result = toAsciiImage(message[i]);
            list.add(result);
        }
        String strs[] = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            strs[i] = list.get(i);
        }

        return strs;
    }

    public  String toAsciiImage(byte b){
        String result = "";
        switch (b) {
        case 48:
            result = "0";
            break;
        case 49:
            result = "1";
            break;
        case 50:
            result = "2";
            break;
        case 51:
            result = "3";
            break;
        case 52:
            result = "4";
            break;
        case 53:
            result = "5";
            break;
        case 54:
            result = "6";
            break;
        case 55:
            result = "7";
            break;
        case 56:
            result = "8";
            break;
        case 57:
            result = "9";
            break;
        default:
            break;
        }
        return result;
    }
    static void listPorts() {
        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
        while (portEnum.hasMoreElements()) {
            CommPortIdentifier portIdentifier = (CommPortIdentifier) portEnum
                    .nextElement();

        }
    }

    static String getPortTypeName(int portType) {
        switch (portType) {
        case CommPortIdentifier.PORT_I2C:
            return "I2C";
        case CommPortIdentifier.PORT_PARALLEL:
            return "Parallel";
        case CommPortIdentifier.PORT_RAW:
            return "Raw";
        case CommPortIdentifier.PORT_RS485:
            return "RS485";
        case CommPortIdentifier.PORT_SERIAL:
            return "Serial";
        default:
            return "unknown type";
        }
    }

    public HashSet<CommPortIdentifier> getAvailableSerialPorts()// 本来static
    {
        HashSet<CommPortIdentifier> h = new HashSet<CommPortIdentifier>();
        Enumeration thePorts = CommPortIdentifier.getPortIdentifiers();
        while (thePorts.hasMoreElements()) {
            CommPortIdentifier com = (CommPortIdentifier) thePorts
                    .nextElement();
            switch (com.getPortType()) {
            case CommPortIdentifier.PORT_SERIAL:
                try {
                    CommPort thePort = com.open("CommUtil", 50);
                    thePort.close();
                    h.add(com);
                } catch (PortInUseException e) {
                    System.out.println("Port, " + com.getName()
                            + ", is in use.");
                } catch (Exception e) {
                    System.out.println("Failed to open port " + com.getName()+ e);
                }
            }
        }
        return h;
    }
}
package cn.com.checknull.rxtx.bean;

public class SerialPortParms {

    /*
     * 串口号、波特率、校验位、数据位、停止位这些常量需要查看具体厂家提供的文档 
     */
    public static final String[] RATE = { "9600", "9600", "4800", "2400" };
    public static final String[] DATABIT = { "8", "7", "6", "5" };
    public static final String[] STOPBIT = { "1", "1.5", "2" };
}
第七步、运行主程序之后,串口扫码枪就可以开始工作了。这里我要特别说一下,我扫描的一般都是条形码,大部分条形码都是采用的ASCII图形格式,因为扫描枪扫描出来的一般是十进制数字,所以在程序中转换了一下,转成ASCII值。


结尾:我只给大家普及一个小知识,大部分药品盒上的条形码采用的ASCII图形格式,所以,童鞋们,为了知道其数字代表的十进制是多少,赶紧去背ASCII数值对照表吧。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值