赞
踩
目录
1、串口通信是指串口按位(bit)发送和接收字节
2、串口通信可以在使用一根线发送数据的同时用另一根线接收数据
3、串口通信常用的协议包括 RS-232、RS-422 和 RS-485
4、串口通信,控制线长度可达1200 米
5、串口通信最重要的参数是波特率、数据位、停止位和奇偶校验,对于两个进行通信的端口,这些参数必须匹配。
6、串口对于普通用户来说很陌生,现在的计算机大都已经取消了这个插口,在工业上和电子行业中,这个端口使用的较为频繁。
7、注意串口与 VGA 插口的区别:串口通常为 9 针,2 排 4+5 排列;而 VGA 插口有15 针,3 排 5+5+5 排列
8、一般来说,带有原生串口的主板,其原生串口的串口号默认为 COM1,如果主板带有2个原生串口,则机箱后方的RS232插口为 COM1,主板上还有一个未能引出的串口插槽为 COM2。
9、如果电脑上没有串口,则一般要用 USB 转串口线进行连接,然后像连接键盘、鼠标一样,要安装USB转串口的驱动
如上所示发送数据时应该给 usb 转串口的 com3 发送
波特率 | 1、衡量信号传输速率的参数 |
数据位 | 1、衡量通信中实际数据位的参数 |
停止位 | 1、用于表示单个包的最后一位,典型的值为 1,1.5 和 2 位 |
奇偶校验位 | 1、串口通信中一种简单的检错方式 |
1、如同 tcp、udp 通信可以先使用测试工具一样,串口通信也推荐先使用工具进行调试,因为至少要先确定被控制的硬件(如投影机、智能灯等)没有问题,否则如果控制失败,就无法指定到底是硬件的问题,还是自己软件的问题了。
2、使用调试助手控制成功后,则可以使用 Java 程序再进行控制。
3、可以使用如下的串口调试工具:Serial Port Utility(友善串口调试助手)
4、如果电脑有串口,则可以直接使用串口线连接硬件使用,如果电脑上没有串口,则可以使用 USB 转串口线进行转换,然后为 USB 转串口线安装好驱动即可。
5、通常一台电脑上的串口是有限的,比如一个串口,此时一个串口通过串口线连接到硬件后,只能控制一台硬件,如何一个串口控制多台硬件呢?可以去网上买一个串口分配器,它可以将一个串口输入分成多个串口输出,通常有 4个、8个等。
1、虽然 Java 也有原生串口通信的 API ,但是使用不太方便,可以选择市面上人家封装好的第三方库,其中以 RXTX 较为常用。
2、rxtx.qbang 官网:http://fizzed.com/oss/rxtx-for-java
3、根据自己电脑系统选择下载:
Version | File | Information |
---|---|---|
RXTX-2-2-20081207 | Windows-x64 | Based on CVS snapshot of RXTX taken on 2008-12-07 |
4、以 Windows-x64 为例,下载解压后如下:
5、其中的 Install.txt 中官方给出了使用说明,Windows 系统如下:
- -----------------------Windows-----------------------------
-
- Choose your binary build - x64 or x86 (based on which version of
- the JVM you are installing to)
-
- NOTE: You MUST match your architecture. You can't install the i386
- version on a 64-bit version of the JDK and vice-versa.
- For a JDK installation:
- Copy RXTXcomm.jar ---> <JAVA_HOME>\jre\lib\ext
- Copy rxtxSerial.dll ---> <JAVA_HOME>\jre\bin
- Copy rxtxParallel.dll ---> <JAVA_HOME>\jre\bin
1)RXTXcomm.jar :作为项目开发包如果已经导入到了项目中,则可以不必复制到 <JAVA_HOME>\jre\lib\ext 下
2)rxtxSerial.dll、rxtxParallel.dll 文件必须放到 <JAVA_HOME>\jre\bin 下,如果是 Windows 系统,则也可以放到 C:\Windows\System32 目录下,否则运行会报错如下:
- java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path] with root cause
- java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path
- at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
- at java.lang.Runtime.loadLibrary0(Runtime.java:870)
- at java.lang.System.loadLibrary(System.java:1122)
Maven 依赖
1、如果是 Maven 应用,则可以 Maven 中央仓库获取 RXTX 依赖:
- <!-- https://mvnrepository.com/artifact/org.bidib.jbidib.org.qbang.rxtx/rxtxcomm -->
- <dependency>
- <groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
- <artifactId>rxtxcomm</artifactId>
- <version>2.2</version>
- </dependency>
1、使用也是很简单,分为三步:
1)打开串口
2)使用 java.io.OutputStream 发送数据,或 java.io.InputStream 读取数据
3)关闭串口
2、完整内容如下:
- import gnu.io.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Enumeration;
- import java.util.List;
- /**
- * Created by Administrator on 2019/3/18 0018.
- * 串口工具类
- */
- public class SerialPortTool {
- private static final Logger logger = LoggerFactory.getLogger(SerialPortTool.class);//slf4j 日志记录器
- /**
- * 查找电脑上所有可用 com 端口
- *
- * @return 可用端口名称列表,没有时 列表为空
- */
- public static final ArrayList<String> findSystemAllComPort() {
- /**
- * getPortIdentifiers:获得电脑主板当前所有可用串口
- */
- Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
- ArrayList<String> portNameList = new ArrayList<>();
-
- /**
- * 将可用串口名添加到 List 列表
- */
- while (portList.hasMoreElements()) {
- String portName = portList.nextElement().getName();//名称如 COM1、COM2....
- portNameList.add(portName);
- }
- return portNameList;
- }
-
- /**
- * 打开电脑上指定的串口
- *
- * @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
- * @param b 波特率(baudrate),如 9600
- * @param d 数据位(datebits),如 SerialPort.DATABITS_8 = 8
- * @param s 停止位(stopbits),如 SerialPort.STOPBITS_1 = 1
- * @param p 校验位 (parity),如 SerialPort.PARITY_NONE = 0
- * @return 打开的串口对象,打开失败时,返回 null
- */
- public static final SerialPort openComPort(String portName, int b, int d, int s, int p) {
- CommPort commPort = null;
- try {
- //当没有传入可用的 com 口时,默认使用电脑中可用的 com 口中的第一个
- if (portName == null || "".equals(portName)) {
- List<String> comPortList = findSystemAllComPort();
- if (comPortList != null && comPortList.size() > 0) {
- portName = comPortList.get(0);
- }
- }
- logger.info("开始打开串口:portName=" + portName + ",baudrate=" + b + ",datebits=" + d + ",stopbits=" + s + ",parity=" + p);
-
- //通过端口名称识别指定 COM 端口
- CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
- /**
- * open(String TheOwner, int i):打开端口
- * TheOwner 自定义一个端口名称,随便自定义即可
- * i:打开的端口的超时时间,单位毫秒,超时则抛出异常:PortInUseException if in use.
- * 如果此时串口已经被占用,则抛出异常:gnu.io.PortInUseException: Unknown Application
- */
- commPort = portIdentifier.open(portName, 5000);
- /**
- * 判断端口是不是串口
- * public abstract class SerialPort extends CommPort
- */
- if (commPort instanceof SerialPort) {
- SerialPort serialPort = (SerialPort) commPort;
- /**
- * 设置串口参数:setSerialPortParams( int b, int d, int s, int p )
- * b:波特率(baudrate)
- * d:数据位(datebits),SerialPort 支持 5,6,7,8
- * s:停止位(stopbits),SerialPort 支持 1,2,3
- * p:校验位 (parity),SerialPort 支持 0,1,2,3,4
- * 如果参数设置错误,则抛出异常:gnu.io.UnsupportedCommOperationException: Invalid Parameter
- * 此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
- */
- serialPort.setSerialPortParams(b, d, s, p);
- logger.info("打开串口 " + portName + " 成功...");
- return serialPort;
- } else {
- logger.error("当前端口 " + commPort.getName() + " 不是串口...");
- }
- } catch (NoSuchPortException e) {
- e.printStackTrace();
- } catch (PortInUseException e) {
- logger.warn("串口 " + portName + " 已经被占用,请先解除占用...");
- e.printStackTrace();
- } catch (UnsupportedCommOperationException e) {
- logger.warn("串口参数设置错误,关闭串口,数据位[5-8]、停止位[1-3]、验证位[0-4]...");
- e.printStackTrace();
- if (commPort != null) {//此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
- commPort.close();
- }
- }
- logger.error("打开串口 " + portName + " 失败...");
- return null;
- }
-
- /**
- * 往串口发送数据
- *
- * @param serialPort 串口对象
- * @param order 待发送数据
- */
- public static void sendDataToComPort(SerialPort serialPort, byte[] orders) {
- OutputStream outputStream = null;
- try {
- if (serialPort != null) {
- outputStream = serialPort.getOutputStream();
- outputStream.write(orders);
- outputStream.flush();
- logger.info("往串口 " + serialPort.getName() + " 发送数据:" + Arrays.toString(orders) + " 完成...");
- } else {
- logger.error("gnu.io.SerialPort 为null,取消数据发送...");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- /**
- * 关闭串口
- *
- * @param serialport 待关闭的串口对象
- */
- public static void closeComPort(SerialPort serialPort) {
- if (serialPort != null) {
- serialPort.close();
- logger.info("关闭串口 " + serialPort.getName());
- }
- }
-
- /**
- * 16进制字符串转十进制字节数组
- * 这是常用的方法,如某些硬件的通信指令就是提供的16进制字符串,发送时需要转为字节数组再进行发送
- *
- * @param strSource 16进制字符串,如 "455A432F5600",每两位对应字节数组中的一个10进制元素
- * 默认会去除参数字符串中的空格,所以参数 "45 5A 43 2F 56 00" 也是可以的
- * @return 十进制字节数组, 如 [69, 90, 67, 47, 86, 0]
- */
- public static byte[] hexString2Bytes(String strSource) {
- if (strSource == null || "".equals(strSource.trim())) {
- System.out.println("hexString2Bytes 参数为空,放弃转换.");
- return null;
- }
- strSource = strSource.replace(" ", "");
- int l = strSource.length() / 2;
- byte[] ret = new byte[l];
- for (int i = 0; i < l; i++) {
- ret[i] = Integer.valueOf(strSource.substring(i * 2, i * 2 + 2), 16).byteValue();
- }
- return ret;
- }
-
- public static void main(String[] args) {
- //发送普通数据
- byte[] bytes = new byte[]{1, 2, 3, 4, 5};
- SerialPort serialPort = SerialPortTool.openComPort(null, 38400, 8, 1, 0);
- SerialPortTool.sendDataToComPort(serialPort, bytes);
- SerialPortTool.closeComPort(serialPort);
-
- //发送16进制数据——实际应用中串口通信传输的数据,大都是 16 进制
- String hexStrCode = "455A432F5600";
- serialPort = SerialPortTool.openComPort(null, 38400, 8, 1, 0);
- SerialPortTool.sendDataToComPort(serialPort, hexString2Bytes(hexStrCode));
- SerialPortTool.closeComPort(serialPort);
- }
- }
上面虽然只有发送数据,但是读取也是同理的,无非就是获取输入流进行读取即可。因为读取没有切实的真实测试使用场景,所以就不贴出了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。