本文主要实现读取员工刷卡信息 将淘宝买的刷卡IC卡读取器插入Windows笔记本的USB接口,安装驱动,设备管理器会自动添加一个模拟的COM3串口 本次使用的Java环境为 java version “1.8.0_112” Java? SE Runtime Environment (build 1.8.0_112-b15) Java HotSpot? 64-Bit Server VM (build 25.112-b15, mixed mode)
1. 下载java读取串口的所需依赖
下载地址TXTX for Java
2. 将下载文件解压后dll文件放入jdk的jre文件中
rxtxParallel.dll ,rxtxSerial.dll copy to C:\Program Files\Java\jdk1.8.0_112\jre\bin
3. 新建Java项目
我使用的是创建一个JavaFX项目,因为只是写一个Demo,JavaFX和Java项目区别不大
在项目中创建一个lib包,将下载的RXTXcomm.jar 文件放入lib包中,将lib包设置为项目资源 IDEA设置:右键RXTXcomm.jar ,选择Add as Library... 即可
4. 新建读取串口的工具SerialTool
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Locale;
import java.util.TooManyListenersException;
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;
public class SerialTool {
public static final ArrayList<String> findPort() {
@SuppressWarnings("unchecked")
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<String>();
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
public static final SerialPort openPort(String portName, int baudrate) {
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
CommPort commPort = portIdentifier.open(portName, 2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
try {
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
throw new RuntimeException("设置串口参数失败!打开串口操作未完成!");
}
System.out.println("Open " + portName + " successfully !");
return serialPort;
}
else {
throw new RuntimeException("端口指向设备不是串口类型");
}
} catch (NoSuchPortException e1) {
throw new RuntimeException("没有该端口对应的串口设备");
} catch (PortInUseException e2) {
throw new RuntimeException("端口已被占用");
}
}
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
public static void sendToPort(SerialPort serialPort, byte[] order) {
try (OutputStream out = serialPort.getOutputStream()){
out.write(order);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] readFromPort(SerialPort serialPort) {
InputStream in = null;
byte[] bytes = null;
try {
in = serialPort.getInputStream();
int bufflenth = in.available();
while (bufflenth != 0) {
bytes = new byte[bufflenth];
in.read(bytes);
bufflenth = in.available();
}
} catch (IOException e) {
e.printStackTrace();
System.err.println("从串口读取数据时出错");
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch(IOException e) {
e.printStackTrace();
System.err.println("关闭串口对象输入流出错");
}
}
System.out.println("读取成功");
return bytes;
}
public static void addListener(SerialPort port, DataAvailableListener listener){
try {
port.addEventListener(new SerialPortListener(listener));
port.notifyOnDataAvailable(true);
port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
e.printStackTrace();
System.err.println("监听类对象过多");
}
}
public static class SerialPortListener implements SerialPortEventListener {
private DataAvailableListener mDataAvailableListener;
public SerialPortListener(DataAvailableListener mDataAvailableListener) {
this.mDataAvailableListener = mDataAvailableListener;
}
public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
if (mDataAvailableListener != null) {
mDataAvailableListener.dataAvailable();
}
break;
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.CTS:
break;
case SerialPortEvent.DSR:
break;
case SerialPortEvent.RI:
break;
case SerialPortEvent.CD:
break;
case SerialPortEvent.OE:
break;
case SerialPortEvent.PE:
break;
case SerialPortEvent.FE:
break;
case SerialPortEvent.BI:
System.out.println("与串口设备通讯中断");
break;
default:
break;
}
}
}
public interface DataAvailableListener {
void dataAvailable();
}
public static byte[] hex2Bytes(String hex) {
if (hex == null || hex.length() == 0) {
return null;
}
char[] hexChars = hex.toCharArray();
byte[] bytes = new byte[hexChars.length / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
}
return bytes;
}
public static String byteArrayToHexString(byte[] array) {
if (array == null) {
return "";
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < array.length; i++) {
buffer.append(byteToHex(array[i]));
}
return buffer.toString();
}
public static String byteToHex(byte b) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
return hex.toUpperCase(Locale.getDefault());
}
public static String stringToAscii(String value)
{
StringBuffer sbu = new StringBuffer();
char[] chars = value.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(i != chars.length - 1)
{
sbu.append((int)chars[i]).append(",");
}
else {
sbu.append((int)chars[i]);
}
}
return sbu.toString();
}
}
5. 读写串口测试
import gnu.io.SerialPort;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import sample.utils.*;
import java.util.ArrayList;
public class Controller {
@FXML
Button writeButton;
@FXML
TextArea readTextarea;
@FXML
TextArea writeTextarea;
@FXML
TextField comName;
SerialPort port = null;
@FXML
public void startCom() {
if(port != null){
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "串口已经打开:" + port.getName());
alert.show();
return;
}
ArrayList<String> findPorts = SerialTool.findPort();
if(findPorts.isEmpty()){
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "未找到串口信息!");
alert.show();
return;
}
String portName = findPorts.get(0);
comName.setText(portName);
try {
port = SerialTool.openPort(portName, 9600);
} catch (RuntimeException e){
Alert alert = new Alert(Alert.AlertType.ERROR, e.getMessage());
alert.show();
return;
}
SerialTool.addListener(port, () -> {
byte[] data = null;
try {
if (port == null) {
System.out.println("串口对象为空,监听失败!");
} else {
data = SerialTool.readFromPort(port);
String resultHEX = SerialTool.byteArrayToHexString(data);
readTextarea.setText(resultHEX);
}
} catch (Exception e) {
Alert alert = new Alert(Alert.AlertType.ERROR, "发生了一个异常:".concat(e.getMessage()));
alert.show();
}
});
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "串口开启成功!");
alert.show();
}
@FXML
public void writeCom() {
if(port == null){
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "请先开启串口!");
alert.show();
return;
}
String content = writeTextarea.getText();
if(content == null || content.trim().length() <=0){
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "请填写写入的数据!");
alert.show();
return;
}
byte[] bs = SerialTool.hex2Bytes(content);
SerialTool.sendToPort(port, bs);
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "写入成功!");
alert.show();
}
}
完成后实际界面如下:
6. 结尾
我写的demo源码地址 参考文档-java串口通信demo
|