java读写串口数据,java面试题,java中级笔试题


写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫码加微信好友进【程序员面试学习交流群】,免费领取。也欢迎各位一起在群里探讨技术。

本博文参考自https://www.cnblogs.com/Dreamer-1/p/5523046.html

最近接触到了串口及其读写,在此记录java进行串口读写的过程。

1.导入串口支持包

需要下载支持Java串口通信操作的jar包,由于java.comm比较老了,而且不支持64位系统,这里推荐Rxtx这个jar包(32位/64位均支持)。

以下下载地址:

http://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x86.zip (32位)

http://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x64.zip (64位)

导入RXTXcomm.jar到项目的buildpath

为防止运行过程中抛出 java.lang.UnsatisfiedLinkError 错误或 gnu.io 下的类找不到,请将rxtx解压包中的 rxtxParallel.dll,rxtxSerial.dll 这两个文件复制到 C:WindowsSystem32 目录下即可解决该错误。

2.编写代码操作串口:

串口必要参数类:包含连接串口所必须的参数,方便在调用串口时设置和传递串口参数

/**

 * 串口必要参数接收类

 * @author: LinWenLi

 * @date: 2018年7月21日 下午4:30:40

 */

public class ParamConfig {

    private String serialNumber;// 串口号

    private int baudRate;        // 波特率

    private int checkoutBit;    // 校验位

    private int dataBit;        // 数据位

    private int stopBit;        // 停止位

    

    public ParamConfig() {}

        

    /**

     * 构造方法

     * @param serialNumber    串口号

     * @param baudRate        波特率

     * @param checkoutBit    校验位

     * @param dataBit        数据位

     * @param stopBit        停止位

     */

    public ParamConfig(String serialNumber, int baudRate, int checkoutBit, int dataBit, int stopBit) {

        this.serialNumber = serialNumber;

        this.baudRate = baudRate;

        this.checkoutBit = checkoutBit;

        this.dataBit = dataBit;

        this.stopBit = stopBit;

    }


    getter()...

    setter()...

}

串口操作类:(其中包含的CustomException是自定义异常类,仅用于抛出异常原因。)

import gnu.io.CommPortIdentifier;

import gnu.io.PortInUseException;

import gnu.io.SerialPort;

import gnu.io.SerialPortEvent;

import gnu.io.SerialPortEventListener;

import gnu.io.UnsupportedCommOperationException;

/**

 * 串口参数的配置 串口一般有如下参数可以在该串口打开以前进行配置: 包括串口号,波特率,输入/输出流控制,数据位数,停止位和奇偶校验。

 */

// 注:串口操作类一定要继承SerialPortEventListener

public class SerialPortUtils implements SerialPortEventListener {

    // 检测系统中可用的通讯端口类

    private CommPortIdentifier commPortId;

    // 枚举类型

    private Enumeration<CommPortIdentifier> portList;

    // RS232串口

    private SerialPort serialPort;

    // 输入流

    private InputStream inputStream;

    // 输出流

    private OutputStream outputStream;

    // 保存串口返回信息

    private String data;

    // 保存串口返回信息十六进制

    private String dataHex;/**

     * 初始化串口

     * @author LinWenLi

     * @date 2018年7月21日下午3:44:16

     * @Description: TODO

     * @param: paramConfig  存放串口连接必要参数的对象(会在下方给出类代码)    

     * @return: void      

     * @throws

     */

    @SuppressWarnings("unchecked")

    public void init(ParamConfig paramConfig) {

        // 获取系统中所有的通讯端口

        portList = CommPortIdentifier.getPortIdentifiers();

        // 记录是否含有指定串口

        boolean isExsist = false;

        // 循环通讯端口

        while (portList.hasMoreElements()) {

            commPortId = portList.nextElement();

            // 判断是否是串口

            if (commPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {

                // 比较串口名称是否是指定串口

                if (paramConfig.getSerialNumber().equals(commPortId.getName())) {

                    // 串口存在

                    isExsist = true;

                    // 打开串口

                    try {

                        // open:(应用程序名【随意命名】,阻塞时等待的毫秒数)

                        serialPort = (SerialPort) commPortId.open(Object.class.getSimpleName(), 2000);

                        // 设置串口监听

                        serialPort.addEventListener(this);

                        // 设置串口数据时间有效(可监听)

                        serialPort.notifyOnDataAvailable(true);

                        // 设置串口通讯参数:波特率,数据位,停止位,校验方式

                        serialPort.setSerialPortParams(paramConfig.getBaudRate(), paramConfig.getDataBit(),

                                paramConfig.getStopBit(), paramConfig.getCheckoutBit());

                    } catch (PortInUseException e) {

                        throw new CustomException("端口被占用");

                    } catch (TooManyListenersException e) {

                        throw new CustomException("监听器过多");

                    } catch (UnsupportedCommOperationException e) {

                        throw new CustomException("不支持的COMM端口操作异常");

                    }

                    // 结束循环

                    break;

                }

            }

        }

        // 若不存在该串口则抛出异常

        if (!isExsist) {

            throw new CustomException("不存在该串口!");

        }

    }

    /**

     * 实现接口SerialPortEventListener中的方法 读取从串口中接收的数据

     */

    @Override

    public void serialEvent(SerialPortEvent event) {

        switch (event.getEventType()) {

        case SerialPortEvent.BI: // 通讯中断

        case SerialPortEvent.OE: // 溢位错误

        case SerialPortEvent.FE: // 帧错误

        case SerialPortEvent.PE: // 奇偶校验错误

        case SerialPortEvent.CD: // 载波检测

        case SerialPortEvent.CTS: // 清除发送

        case SerialPortEvent.DSR: // 数据设备准备好

        case SerialPortEvent.RI: // 响铃侦测

        case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空

            break;

        case SerialPortEvent.DATA_AVAILABLE: // 有数据到达

            // 调用读取数据的方法

            readComm();

            break;

        default:

            break;

        }

    }

    /**

     * 读取串口返回信息

     * @author LinWenLi

     * @date 2018年7月21日下午3:43:04

     * @return: void      

     */

    public void readComm() {

        try {

            inputStream = serialPort.getInputStream();

            // 通过输入流对象的available方法获取数组字节长度

            byte[] readBuffer = new byte[inputStream.available()];

            // 从线路上读取数据流

            int len = 0;

            while ((len = inputStream.read(readBuffer)) != -1) {
         // 直接获取到的数据

                data = new String(readBuffer, 0, len).trim();
         // 转为十六进制数据

                dataHex = bytesToHexString(readBuffer);

                System.out.println("data:" + data);

                System.out.println("dataHex:" + dataHex);// 读取后置空流对象

                inputStream.close();

                inputStream = null;

                break;

            }

        } catch (IOException e) {

            throw new CustomException("读取串口数据时发生IO异常");

        }

    }

    /**

     * 发送信息到串口

     * @author LinWenLi

     * @date 2018年7月21日下午3:45:22

     * @param: data      

     * @return: void      

     * @throws

     */

    public void sendComm(String data) {

        byte[] writerBuffer = null;

        try {

            writerBuffer = hexToByteArray(data);

        } catch (NumberFormatException e) {

            throw new CustomException("命令格式错误!");

        }

        try {

            outputStream = serialPort.getOutputStream();

            outputStream.write(writerBuffer);

            outputStream.flush();

        } catch (NullPointerException e) {

            throw new CustomException("找不到串口。");

        } catch (IOException e) {

            throw new CustomException("发送信息到串口时发生IO异常");

        }

    }

    /**

     * 关闭串口

     * @author LinWenLi

     * @date 2018年7月21日下午3:45:43

     * @Description: 关闭串口

     * @param:       

     * @return: void      

     * @throws

     */

    public void closeSerialPort() {

        if (serialPort != null) {

            serialPort.notifyOnDataAvailable(false);

            serialPort.removeEventListener();

            if (inputStream != null) {

                try {

                    inputStream.close();

                    inputStream = null;

                } catch (IOException e) {

                    throw new CustomException("关闭输入流时发生IO异常");

                }

            }

            if (outputStream != null) {

                try {

                    outputStream.close();

                    outputStream = null;

                } catch (IOException e) {

                    throw new CustomException("关闭输出流时发生IO异常");

                }

            }

            serialPort.close();

            serialPort = null;

        }

    }

    /**

     * 十六进制串口返回值获取

     */

    public String getDataHex() {

        String result = dataHex;

        // 置空执行结果

        dataHex = null;

        // 返回执行结果

        return result;

    }

    /**

     * 串口返回值获取

     */

    public String getData() {

        String result = data;

        // 置空执行结果

        data = null;

        // 返回执行结果

        return result;

    }

    /**

     * Hex字符串转byte

     * @param inHex 待转换的Hex字符串

     * @return 转换后的byte

     */

    public static byte hexToByte(String inHex) {

        return (byte) Integer.parseInt(inHex, 16);

    }

    /**

     * hex字符串转byte数组

     * @param inHex 待转换的Hex字符串

     * @return 转换后的byte数组结果

     */

    public static byte[] hexToByteArray(String inHex) {

        int hexlen = inHex.length();

        byte[] result;

        if (hexlen % 2 == 1) {

            // 奇数

            hexlen++;

            result = new byte[(hexlen / 2)];

            inHex = "0" + inHex;

        } else {

            // 偶数

            result = new byte[(hexlen / 2)];

        }

        int j = 0;

        for (int i = 0; i < hexlen; i += 2) {

            result[j] = hexToByte(inHex.substring(i, i + 2));

            j++;

        }

        return result;

    }

    /**

     * 数组转换成十六进制字符串

     * @param byte[]

     * @return HexString

     */

    public static final String bytesToHexString(byte[] bArray) {

        StringBuffer sb = new StringBuffer(bArray.length);

        String sTemp;

        for (int i = 0; i < bArray.length; i++) {

            sTemp = Integer.toHexString(0xFF & bArray[i]);

            if (sTemp.length() < 2)

                sb.append(0);

            sb.append(sTemp.toUpperCase());

        }

        return sb.toString();

    }

}

调用串口操作类的代码:

     public static void main(String[] args) {

         // 实例化串口操作类对象

         SerialPortUtils serialPort = new SerialPortUtils();

         // 创建串口必要参数接收类并赋值,赋值串口号,波特率,校验位,数据位,停止位

         ParamConfig paramConfig = new ParamConfig("COM4", 9600, 0, 8, 1);

         // 初始化设置,打开串口,开始监听读取串口数据

         serialPort.init(paramConfig);

         // 调用串口操作类的sendComm方法发送数据到串口

         serialPort.sendComm("FEF10A000000000000000AFF");

         // 关闭串口

         serialPort.closeSerialPort();

     }

当执行main方法中的代码且未执行关闭串口时,程序将一直处于开启状态,自动监听,接收读取来自串口的数据。

注意:一个串口只能打开一次,并只支持一个程序调用。

以上所记录的是简单测试java是否能成功操作串口数据,至于本人所写的Web端的读卡器调试功能则是在串口操作类的基础上编写网页界面,通过请求来控制串口的开启关闭及相应的设置,功能比较简单,放个界面记录一下:


转载:https://www.cnblogs.com/new-life/p/9345849.html

推荐内容:
java线程面试
Java面试题(二)
Java高并发之设计模式.
java主线程结束和子线程结束之间的关系
Java上传视频
Java与c#的一些细节区别
最新Java校招面试题及答案
java中equals,hashcode和==的区别
分享1-3年经验的Java面试
JAVA框架面试题

猜你喜欢

转载自blog.csdn.net/alogtech6/article/details/89444025