Java串口通信

Java串口通信介绍

概述:用Java的方式和我们的硬件(传感器)通过串口(COM3)实现数据交互等功能,基于UART协议实现

串口(串行端口)通信

Java串口通讯是指使用Java编程语言与串行端口(串口)进行数据通讯的过程,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式(注意,是一位一位的传输,区别于并口通讯,传输慢)。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。虽然说慢,不如并,但不代表就要抛弃,某些项目还是很有用的,例如公司最近营养探索馆的一个血压探测仪,就是串口通讯,需要开发串口。

优点:

  1. 适用性广泛: 串口通讯通常用于连接各种外部设备,如传感器、控制器、调制解调器等,因此适用性非常广泛。
  2. 线缆简单: 串口通讯只需要少量的线缆就能实现数据传输,因此在布线和连接方面比较简单。
  3. 长距离传输: 串口通讯可以通过串口转以太网等设备实现远程通讯,支持长距离传输。

缺点:

  1. 速度相对较慢: 串口通讯的传输速度通常比较慢,受到硬件限制,无法满足高速数据传输的需求。
  2. 连接设备数量有限: 串口通讯通常只支持连接少量外部设备,无法承载大规模设备连接的需求。

并口通信

并口通讯是通过计算机的并行接口(并口)进行数据传输的方式。并口通讯可以同时传输多个比特(通常是8位或更多),因此传输速度相对较快。并口通讯通常用于连接一些需要高速数据传输的外部设备,如打印机、扫描仪等。并口通讯所需的线缆较为复杂,包括大量的数据线和控制线,连接和布线相对复杂。

优点:

  1. 高速传输: 并口通讯支持并行传输,因此传输速度相对较快,在某些应用场景下能够满足高速数据传输的需求。
  2. 多设备连接: 并口通讯通常支持连接多个外部设备,能够满足一定规模的设备连接需求。

缺点:

  1. 线缆复杂: 并口通讯所需的线缆较为复杂,包括大量的数据线和控制线,因此在布线和连接方面相对复杂。
  2. 不易远程传输: 由于线缆复杂和传输方式的限制,通常不能实现远程数据传输。

综合来看,串口通讯适用性广泛、连接简单,但传输速度较慢;而并口通讯传输速度快,能够连接多个设备,但线缆复杂且不易远程传输。因此在实际应用中,选择串口通讯还是并口通讯取决于具体的应用场景和需求。

实现方式

1.通过comm.jar实现太老了,对jdk版本有要求(jdk 1.8 32bit),也要配置dll文件

2.通过RXTXcomm.jar实现(更新慢),需要配置dll文件,打包可能会出错

3.通过jserialcomm实现(推荐)跨平台,兼容性好

1.通过comm.jar实现

准备工作

1.下载comm.jar相关资源,将javax.comm.properties,win32com.dll配置文件放到jdk的bin和lib目录

2.准备好一个串口工具,和模拟串口的工具,便于测试

关于依赖引用问题:

当maven拉取不到相关依赖时,有两种解决方案

1.作为资源文件夹内的资源引用

我们可以选择将该依赖的jar包下载下来,通过创建lib文件夹的方式将依赖添加到项目中

		<dependency>
            <groupId>gun.io</groupId>
            <artifactId>rxtx</artifactId>
            <version>1.0.0</version>
            <!--system,类似provided,需要显式提供依赖的jar以后,Maven就不会在Repository中查找它-->
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath>
        </dependency>

2.将jar包手动安装到maven仓库

实现步骤

1.用Configure Virtual Serial Port Driver虚拟串口工具模拟2个串口号

2.导入相应依赖 comm.jar包并添加到项目中,jdk版本为1.8 32bit

3.通过comm.jar包提供的方法和串口建立通讯

4.通过CommPortIdentifier.getPortIdentifiers()方法获取可用串口

5.选择合适端口,通过该commPort.open()方法打开该端口

6.设置常用参数,如波特率,停止位,校验位等 serialPort.setSerialPortParams()

7.端口打开后,可用通过serialPort.addEventListener()方法添加监听器监听我们之前打开的端口

8.通过程序向端口发送数据,核心是基于流的形式,通过outputStream.write()发送数据

相关代码

package com.xxxx.ckcomm.utils;

import javax.comm.*;
import java.io.*;
import java.util.*;

public class DSerialPort implements Runnable, SerialPortEventListener {
   
   

    private String appName = "串口通讯测试";
    private int timeout = 2000;// open 端口时的等待时间,延迟时间(毫秒数)
    private int threadTime = 0;

    private CommPortIdentifier commPort;
    private SerialPort serialPort;
    private InputStream inputStream;
    private OutputStream outputStream;
    //当前接收COM口的数据
    public static String receiptDataString = "";
    //当前已取的数组下标
    public static int nowDataIndex = 0;
    //当前接收COM口的数据自动切割成StringList
    public static ArrayList<String> receiptDataList = new ArrayList<String>();


    static {
   
   
        String driverName = "com.sun.comm.Win32Driver";
        CommDriver driver;
        try {
   
   
            driver = (CommDriver) Class.forName(driverName).newInstance();
        } catch (InstantiationException e) {
   
   
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
   
   
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
   
   
            throw new RuntimeException(e);
        }
        driver.initialize();
    }


    /**
     * @方法名称 :listPort
     * @功能描述 :列出所有可用的串口
     * @返回值类型 :List<String>
     */
    @SuppressWarnings("rawtypes")
    public List<String> listPort() {
   
   
        //获得当前所有可用串口
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        ArrayList<String> portNameList = new ArrayList<>();
        //将可用串口名添加到List并返回该List
        while (portList.hasMoreElements()) {
   
   
            String portName = portList.nextElement().getName();
            portNameList.add(portName);
        }
        return portNameList;
    }

    /**
     * @param portName
     * @方法名称 :selectPort
     * @功能描述 :选择一个端口,比如:COM1
     * @返回值类型 :void
     */
    @SuppressWarnings("rawtypes")
    public void selectPort(String portName) {
   
   

        this.commPort = null;
        CommPortIdentifier cpid;
        Enumeration portList = CommPortIdentifier.getPortIdentifiers();
        while (portList.hasMoreElements()) {
   
   
            System.out.println("串口接口调用成功");
            cpid = (CommPortIdentifier) portList.nextElement();
            if (cpid.getPortType() == CommPortIdentifier.PORT_SERIAL && cpid.getName().equals(portName)) {
   
   
                this.commPort = cpid;
                break;
            }
        }
        openPort();
    }

    /**
     * @方法名称 :openPort
     * @功能描述 :打开SerialPort
     * @返回值类型 :void
     */
    private void openPort() {
   
   
        if (commPort == null)
            log("无法找到串口!");
        else {
   
   
            log("端口选择成功,当前端口:" + commPort.getName() + ",现在实例化 SerialPort:");

            try {
   
   
                serialPort = (SerialPort) commPort.open(appName, timeout);//打开端口
                serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                //设置参数
                log("实例 SerialPort 成功!");
            } catch (PortInUseException e) {
   
   
                throw new RuntimeException(String.format("端口'%1$s'正在使用中!", commPort.getName()));
            } catch (UnsupportedCommOperationException e) {
   
   
                e.printStackTrace();
            }
        }
    }

    /**
     * @方法名称 :checkPort
     * @功能描述 :检查端口是否正确连接
     * @返回值类型 :void
     */
    public void checkPort() {
   
   
        if (commPort == null)
            throw new RuntimeException("没有选择端口,请使用 " + "selectPort(String portName) 方法选择端口");

        if (serialPort == null) {
   
   
            throw new RuntimeException("SerialPort 对象无效!");
        }
    }

    /**
     * @方法名称 :write
     * @功能描述 :向端口发送数据,请在调用此方法前 先选择端口,并确定SerialPort正常打开!
     * @返回值类型 :void
     */
    public void write(String message) {
   
   
        checkPort();

        try {
   
   
            outputStream = new BufferedOutputStream(serialPort.getOutputStream());
        } catch (IOException e) {
   
   
            throw new RuntimeException("获取端口的OutputStream出错:" + e.getMessage());
        }

        try {
   
   
            outputStream.write(message.getBytes());
            log("信息发送成功!");
        } catch (IOException e) {
   
   
            throw new RuntimeException("向端口发送信息时出错:" + e.getMessage());
        } finally {
   
   
            try {
   
   
                outputStream.close();
            } catch (IOException e) {
   
   
                throw new RuntimeException(e);
            }
        }
    }

    public void write(byte[] message
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值