init
commit
9621c9d1e9
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
### Java读取串口数据测试
|
||||

|
|
@ -0,0 +1,98 @@
|
|||
package sample;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package sample;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class Main extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception{
|
||||
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
|
||||
primaryStage.setTitle("串口测试工具");
|
||||
primaryStage.setScene(new Scene(root, 550, 360));
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.FlowPane?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
|
||||
<GridPane alignment="CENTER" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints />
|
||||
<ColumnConstraints />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints />
|
||||
<RowConstraints />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<FlowPane columnHalignment="CENTER" nodeOrientation="LEFT_TO_RIGHT" orientation="VERTICAL" prefHeight="459.0" prefWidth="270.0">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onMouseClicked="#startCom" text="查找并开启串口通信" />
|
||||
<Label text="串口名称:" />
|
||||
<TextField fx:id="comName" promptText="COM" />
|
||||
<Label text="串口端口:" />
|
||||
<TextField promptText="9600" />
|
||||
<Label text="读取的串口数据:" />
|
||||
<TextArea fx:id="readTextarea" prefHeight="82.0" prefWidth="233.0" promptText="读取的串口数据" />
|
||||
<Label text="写入串口数据" />
|
||||
<TextArea fx:id="writeTextarea" prefHeight="55.0" prefWidth="233.0" promptText="待写入的串口数据" />
|
||||
<Button fx:id="writeButton" mnemonicParsing="false" onMouseClicked="#writeCom" text="写入串口数据" />
|
||||
</children>
|
||||
</FlowPane>
|
||||
</children>
|
||||
</GridPane>
|
|
@ -0,0 +1,285 @@
|
|||
package sample.utils;
|
||||
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 查找所有可用端口
|
||||
* @return 可用端口名称列表
|
||||
*/
|
||||
public static final ArrayList<String> findPort() {
|
||||
|
||||
//获得当前所有可用串口
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
|
||||
ArrayList<String> portNameList = new ArrayList<String>();
|
||||
//将可用串口名添加到List并返回该List
|
||||
while (portList.hasMoreElements()) {
|
||||
String portName = portList.nextElement().getName();
|
||||
portNameList.add(portName);
|
||||
}
|
||||
|
||||
return portNameList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开串口
|
||||
* @param portName 端口名称
|
||||
* @param baudrate 波特率
|
||||
* @return 串口对象
|
||||
*/
|
||||
public static final SerialPort openPort(String portName, int baudrate) {
|
||||
try {
|
||||
//通过端口名识别端口
|
||||
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
|
||||
//打开端口,并给端口名字和一个timeout(打开操作的超时时间)
|
||||
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("端口已被占用");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭串口
|
||||
* @param serialPort 待关闭的串口对象
|
||||
*/
|
||||
public static void closePort(SerialPort serialPort) {
|
||||
if (serialPort != null) {
|
||||
serialPort.close();
|
||||
serialPort = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 往串口发送数据
|
||||
* @param serialPort 串口对象
|
||||
* @param order 待发送数据
|
||||
*/
|
||||
public static void sendToPort(SerialPort serialPort, byte[] order) {
|
||||
try (OutputStream out = serialPort.getOutputStream()){
|
||||
out.write(order);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从串口读取数据
|
||||
* @param serialPort 当前已建立连接的SerialPort对象
|
||||
* @return 读取到的数据
|
||||
*/
|
||||
public static byte[] readFromPort(SerialPort serialPort) {
|
||||
|
||||
InputStream in = null;
|
||||
byte[] bytes = null;
|
||||
|
||||
try {
|
||||
|
||||
in = serialPort.getInputStream();
|
||||
int bufflenth = in.available(); //获取buffer里的数据长度
|
||||
|
||||
while (bufflenth != 0) {
|
||||
bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加监听器
|
||||
* @param port 串口对象
|
||||
* @param listener 串口监听器
|
||||
*/
|
||||
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: // 1.串口存在有效数据
|
||||
if (mDataAvailableListener != null) {
|
||||
mDataAvailableListener.dataAvailable();
|
||||
}
|
||||
break;
|
||||
|
||||
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空
|
||||
break;
|
||||
|
||||
case SerialPortEvent.CTS: // 3.清除待发送数据
|
||||
break;
|
||||
|
||||
case SerialPortEvent.DSR: // 4.待发送数据准备好了
|
||||
break;
|
||||
|
||||
case SerialPortEvent.RI: // 5.振铃指示
|
||||
break;
|
||||
|
||||
case SerialPortEvent.CD: // 6.载波检测
|
||||
break;
|
||||
|
||||
case SerialPortEvent.OE: // 7.溢位(溢出)错误
|
||||
break;
|
||||
|
||||
case SerialPortEvent.PE: // 8.奇偶校验错误
|
||||
break;
|
||||
|
||||
case SerialPortEvent.FE: // 9.帧错误
|
||||
break;
|
||||
|
||||
case SerialPortEvent.BI: // 10.通讯中断
|
||||
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]; // 如果 hex 中的字符不是偶数个, 则忽略最后一个
|
||||
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
/**
|
||||
* byte[]转十六进制字符串
|
||||
*
|
||||
* @param array
|
||||
* byte[]
|
||||
* @return 十六进制字符串
|
||||
*/
|
||||
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();
|
||||
}
|
||||
/**
|
||||
* byte转十六进制字符
|
||||
*
|
||||
* @param b
|
||||
* byte
|
||||
* @return 十六进制字符
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue