串口监听工具listen_java使用Rxtx实现串口通信调试工具

本文实例为大家分享了java使用Rxtx实现串口通信调试工具的具体代码,供大家参考,具体内容如下

最终效果如下图:

1、把rxtxParallel.dll、rxtxSerial.dll拷贝到:C:\WINDOWS\system32下。

2、RXTXcomm.jar 添加到项目类库中。

代码:

package serialPort;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.List;

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.SerialPortEventListener;

import gnu.io.UnsupportedCommOperationException;

/**串口服务类,提供打开、关闭串口,读取、发送串口数据等服务

*/

public class SerialTool {

private static SerialTool serialTool = null;

static {

//在该类被ClassLoader加载时就初始化一个SerialTool对象

if (serialTool == null) {

serialTool = new SerialTool();

}

}

//私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象

private SerialTool() {}

/**

* 获取提供服务的SerialTool对象

* @return serialTool

*/

public static SerialTool getSerialTool() {

if (serialTool == null) {

serialTool = new SerialTool();

}

return serialTool;

}

/**

* 查找所有可用端口

* @return 可用端口名称列表

*/

public static final List findPort() {

//获得当前所有可用串口

@SuppressWarnings("unchecked")

Enumeration portList = CommPortIdentifier.getPortIdentifiers();

List portNameList = new ArrayList<>();

//将可用串口名添加到List并返回该List

while (portList.hasMoreElements()) {

String portName = portList.nextElement().getName();

portNameList.add(portName);

}

return portNameList;

}

/**

* 打开串口

* @param portName 端口名称

* @param baudrate 波特率

* @return 串口对象

* @throws UnsupportedCommOperationException

* @throws PortInUseException

* @throws NoSuchPortException

*/

public static final SerialPort openPort(String portName, int baudrate) throws UnsupportedCommOperationException, PortInUseException, NoSuchPortException {

//通过端口名识别端口

CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);

//打开端口,并给端口名字和一个timeout(打开操作的超时时间)

CommPort commPort = portIdentifier.open(portName, 2000);

//判断是不是串口

if (commPort instanceof SerialPort) {

SerialPort serialPort = (SerialPort) commPort;

//设置一下串口的波特率等参数

serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

return serialPort;

}

return null;

}

/**

* 关闭串口

* @param serialport 待关闭的串口对象

*/

public static void closePort(SerialPort serialPort) {

if (serialPort != null) {

serialPort.close();

serialPort = null;

}

}

/**

* 往串口发送数据

* @param serialPort 串口对象

* @param order 待发送数据

* @throws IOException

*/

public static void sendToPort(SerialPort serialPort, byte[] order) throws IOException {

OutputStream out = null;

out = serialPort.getOutputStream();

out.write(order);

out.flush();

out.close();

}

/**

* 从串口读取数据

* @param serialPort 当前已建立连接的SerialPort对象

* @return 读取到的数据

* @throws IOException

*/

public static byte[] readFromPort(SerialPort serialPort) throws IOException {

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) {

throw e;

} finally {

if (in != null) {

in.close();

in = null;

}

}

return bytes;

}

/**添加监听器

* @param port 串口对象

* @param listener 串口监听器

* @throws TooManyListenersException

*/

public static void addListener(SerialPort port, SerialPortEventListener listener) throws TooManyListenersException {

//给串口添加监听器

port.addEventListener(listener);

//设置当有数据到达时唤醒监听接收线程

port.notifyOnDataAvailable(true);

//设置当通信中断时唤醒中断线程

port.notifyOnBreakInterrupt(true);

}

}

package serialPort;

import java.awt.Color;

import java.awt.Font;

import java.awt.Image;

import java.awt.Toolkit;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.io.IOException;

import java.time.Instant;

import java.time.LocalDateTime;

import java.time.ZoneId;

import java.time.format.DateTimeFormatter;

import java.util.List;

import java.util.Timer;

import java.util.TimerTask;

import java.util.TooManyListenersException;

import javax.swing.JButton;

import javax.swing.JComboBox;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.border.TitledBorder;

import gnu.io.NoSuchPortException;

import gnu.io.PortInUseException;

import gnu.io.SerialPort;

import gnu.io.SerialPortEvent;

import gnu.io.SerialPortEventListener;

import gnu.io.UnsupportedCommOperationException;

/**

* 监测数据显示类

* @author Zhong

*

*/

public class SerialView extends JFrame {

/**

*/

private static final long serialVersionUID = 1L;

//设置window的icon

Toolkit toolKit = getToolkit();

Image icon = toolKit.getImage(SerialView.class.getResource("computer.png"));

DateTimeFormatter df= DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss.SSS");

private JComboBox commChoice;

private JComboBox bpsChoice;

private JButton openSerialButton;

private JButton sendButton;

private JTextArea sendArea;

private JTextArea receiveArea;

private JButton closeSerialButton;

private List commList = null; //保存可用端口号

private SerialPort serialPort = null; //保存串口对象

/**类的构造方法

* @param client

*/

public SerialView() {

init();

TimerTask task = new TimerTask() {

@Override

public void run() {

commList = SerialTool.findPort(); //程序初始化时就扫描一次有效串口

//检查是否有可用串口,有则加入选项中

if (commList == null || commList.size()<1) {

JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);

}else{

commChoice.removeAllItems();

for (String s : commList) {

commChoice.addItem(s);

}

}

}

};

Timer timer = new Timer();

timer.scheduleAtFixedRate(task, 0, 10000);

listen();

}

/**

*/

private void listen(){

//打开串口连接

openSerialButton.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

//获取串口名称

String commName = (String) commChoice.getSelectedItem();

//获取波特率

String bpsStr = (String) bpsChoice.getSelectedItem();

//检查串口名称是否获取正确

if (commName == null || commName.equals("")) {

JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);

}else {

//检查波特率是否获取正确

if (bpsStr == null || bpsStr.equals("")) {

JOptionPane.showMessageDialog(null, "波特率获取错误!", "错误", JOptionPane.INFORMATION_MESSAGE);

}else {

//串口名、波特率均获取正确时

int bps = Integer.parseInt(bpsStr);

try {

//获取指定端口名及波特率的串口对象

serialPort = SerialTool.openPort(commName, bps);

SerialTool.addListener(serialPort, new SerialListener());

if(serialPort==null) return;

//在该串口对象上添加监听器

closeSerialButton.setEnabled(true);

sendButton.setEnabled(true);

openSerialButton.setEnabled(false);

String time=df.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.of("Asia/Shanghai")));

receiveArea.append(time+" ["+serialPort.getName().split("/")[3]+"] : "+" 连接成功..."+"\r\n");

receiveArea.setCaretPosition(receiveArea.getText().length());

} catch (UnsupportedCommOperationException | PortInUseException | NoSuchPortException | TooManyListenersException e1) {

e1.printStackTrace();

}

}

}

}

});

//发送数据

sendButton.addMouseListener(new MouseAdapter() {

@Override

public void mouseClicked(MouseEvent e) {

if(!sendButton.isEnabled())return;

String message= sendArea.getText();

//"FE0400030001D5C5"

try {

SerialTool.sendToPort(serialPort, hex2byte(message));

} catch (IOException e1) {

e1.printStackTrace();

}

}

});

//关闭串口连接

closeSerialButton.addMouseListener(new MouseAdapter() {

@Override

public void mouseClicked(MouseEvent e) {

if(!closeSerialButton.isEnabled())return;

SerialTool.closePort(serialPort);

String time=df.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.of("Asia/Shanghai")));

receiveArea.append(time+" ["+serialPort.getName().split("/")[3]+"] : "+" 断开连接"+"\r\n");

receiveArea.setCaretPosition(receiveArea.getText().length());

openSerialButton.setEnabled(true);

closeSerialButton.setEnabled(false);

sendButton.setEnabled(false);

}

});

}

/**

* 主菜单窗口显示;

* 添加JLabel、按钮、下拉条及相关事件监听;

*/

private void init() {

this.setBounds(WellcomView.LOC_X, WellcomView.LOC_Y, WellcomView.WIDTH, WellcomView.HEIGHT);

this.setTitle("串口调试");

this.setIconImage(icon);

this.setBackground(Color.gray);

this.setLayout(null);

Font font =new Font("微软雅黑", Font.BOLD, 16);

receiveArea=new JTextArea(18, 30);

receiveArea.setEditable(false);

JScrollPane receiveScroll = new JScrollPane(receiveArea);

receiveScroll.setBorder(new TitledBorder("接收区"));

//滚动条自动出现 FE0400030001D5C5

receiveScroll.setHorizontalScrollBarPolicy(

JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

receiveScroll.setVerticalScrollBarPolicy(

JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

receiveScroll.setBounds(52, 20, 680,340);

this.add(receiveScroll);

JLabel chuankou=new JLabel(" 串口选择: ");

chuankou.setFont(font);

chuankou.setBounds(50, 380, 100,50);

this.add(chuankou);

JLabel botelv=new JLabel(" 波 特 率: ");

botelv.setFont(font);

botelv.setBounds(290, 380, 100,50);

this.add(botelv);

//添加串口选择选项

commChoice = new JComboBox(); //串口选择(下拉框)

commChoice.setBounds(145, 390, 100, 30);

this.add(commChoice);

//添加波特率选项

bpsChoice = new JComboBox(); //波特率选择

bpsChoice.setBounds(380, 390, 100, 30);

bpsChoice.addItem("1500");

bpsChoice.addItem("2400");

bpsChoice.addItem("4800");

bpsChoice.addItem("9600");

bpsChoice.addItem("14400");

bpsChoice.addItem("19500");

bpsChoice.addItem("115500");

this.add(bpsChoice);

//添加打开串口按钮

openSerialButton = new JButton("连接");

openSerialButton.setBounds(540, 390, 80, 30);

openSerialButton.setFont(font);

openSerialButton.setForeground(Color.darkGray);

this.add(openSerialButton);

//添加关闭串口按钮

closeSerialButton = new JButton("关闭");

closeSerialButton.setEnabled(false);

closeSerialButton.setBounds(650, 390, 80, 30);

closeSerialButton.setFont(font);

closeSerialButton.setForeground(Color.darkGray);

this.add(closeSerialButton);

sendArea=new JTextArea(30,20);

JScrollPane sendScroll = new JScrollPane(sendArea);

sendScroll.setBorder(new TitledBorder("发送区"));

//滚动条自动出现

sendScroll.setHorizontalScrollBarPolicy(

JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

sendScroll.setVerticalScrollBarPolicy(

JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

sendScroll.setBounds(52, 450, 500,100);

this.add(sendScroll);

sendButton = new JButton("发 送");

sendButton.setBounds(610, 520, 120, 30);

sendButton.setFont(font);

sendButton.setForeground(Color.darkGray);

sendButton.setEnabled(false);

this.add(sendButton);

this.setResizable(false); //窗口大小不可更改

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

}

/**字符串转16进制

* @param hex

* @return

*/

private byte[] hex2byte(String hex) {

String digital = "0123456789ABCDEF";

String hex1 = hex.replace(" ", "");

char[] hex2char = hex1.toCharArray();

byte[] bytes = new byte[hex1.length() / 2];

byte temp;

for (int p = 0; p < bytes.length; p++) {

temp = (byte) (digital.indexOf(hex2char[2 * p]) * 16);

temp += digital.indexOf(hex2char[2 * p + 1]);

bytes[p] = (byte) (temp & 0xff);

}

return bytes;

}

/**字节数组转16进制

* @param b

* @return

*/

private String printHexString(byte[] b) {

StringBuffer sbf=new StringBuffer();

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

String hex = Integer.toHexString(b[i] & 0xFF);

if (hex.length() == 1) {

hex = '0' + hex;

}

sbf.append(hex.toUpperCase()+" ");

}

return sbf.toString().trim();

}

/**

* 以内部类形式创建一个串口监听类

* @author zhong

*/

class SerialListener implements SerialPortEventListener {

/**

* 处理监控到的串口事件

*/

public void serialEvent(SerialPortEvent serialPortEvent) {

switch (serialPortEvent.getEventType()) {

case SerialPortEvent.BI: // 10 通讯中断

JOptionPane.showMessageDialog(null, "与串口设备通讯中断", "错误", JOptionPane.INFORMATION_MESSAGE);

break;

case SerialPortEvent.OE: // 7 溢位(溢出)错误

break;

case SerialPortEvent.FE: // 9 帧错误

break;

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

break;

case SerialPortEvent.CD: // 6 载波检测

break;

case SerialPortEvent.CTS: // 3 清除待发送数据

break;

case SerialPortEvent.DSR: // 4 待发送数据准备好了

break;

case SerialPortEvent.RI: // 5 振铃指示

break;

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

break;

case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用数据

String time=df.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.of("Asia/Shanghai")));

byte[] data;//FE0400030001D5C5

try {

data = SerialTool.readFromPort(serialPort);

receiveArea.append(time+" ["+serialPort.getName().split("/")[3]+"] : "+ printHexString(data)+"\r\n");

receiveArea.setCaretPosition(receiveArea.getText().length());

} catch (IOException e) {

e.printStackTrace();

}

break;

default:

break;

}

}

}

}

package serialPort;

import java.awt.Color;

import java.awt.Font;

import java.awt.Image;

import java.awt.Toolkit;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import javax.swing.JFrame;

import javax.swing.JLabel;

/**

* @author bh

* 如果运行过程中抛出 java.lang.UnsatisfiedLinkError 错误,

* 请将rxtx解压包中的 rxtxParallel.dll,rxtxSerial.dll 这两个文件复制到 C:\Windows\System32 目录下即可解决该错误。

*/

public class WellcomView {

/** 程序界面宽度*/

public static final int WIDTH = 800;

/** 程序界面高度*/

public static final int HEIGHT = 620;

/** 程序界面出现位置(横坐标) */

public static final int LOC_X = 200;

/** 程序界面出现位置(纵坐标)*/

public static final int LOC_Y = 70;

private JFrame jFrame;

/**主方法

* @param args //

*/

public static void main(String[] args) {

new WellcomView();

}

public WellcomView() {

init();

listen();

}

/**

*/

private void listen() {

//添加键盘监听器

jFrame.addKeyListener(new KeyAdapter() {

public void keyReleased(KeyEvent e) {

int keyCode = e.getKeyCode();

if (keyCode == KeyEvent.VK_ENTER) { //当监听到用户敲击键盘enter键后执行下面的操作

jFrame.setVisible(false); //隐去欢迎界面

new SerialView(); //主界面类(显示监控数据主面板)

}

}

});

}

/**

* 显示主界面

*/

private void init() {

jFrame=new JFrame("串口调试");

jFrame.setBounds(LOC_X, LOC_Y, WIDTH, HEIGHT); //设定程序在桌面出现的位置

jFrame.setLayout(null);

//设置window的icon(这里我自定义了一下Windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)

Toolkit toolKit = jFrame.getToolkit();

Image icon = toolKit.getImage(WellcomView.class.getResource("computer.png"));

jFrame.setIconImage(icon);

jFrame.setBackground(Color.white); //设置背景色

JLabel huanyin=new JLabel("欢迎使用串口调试工具");

huanyin.setBounds(170, 80,600,50);

huanyin.setFont(new Font("微软雅黑", Font.BOLD, 40));

jFrame.add(huanyin);

JLabel banben=new JLabel("Version:1.0 Powered By:cyq");

banben.setBounds(180, 390,500,50);

banben.setFont(new Font("微软雅黑", Font.ITALIC, 26));

jFrame.add(banben);

JLabel enter=new JLabel("————点击Enter键进入主界面————");

enter.setBounds(100, 480,600,50);

enter.setFont(new Font("微软雅黑", Font.BOLD, 30));

jFrame.add(enter);

jFrame.setResizable(false); //窗口大小不可更改

jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

jFrame.setVisible(true); //显示窗口

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值