首页 > 开发 > Java > 正文

java使用Rxtx实现串口通信调试工具

2019-10-21 18:41:57
字体:
来源:转载
供稿:网友

本文实例为大家分享了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<String> findPort() {  //获得当前所有可用串口  @SuppressWarnings("unchecked")  Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();   List<String> 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<String> commChoice; private JComboBox<String> bpsChoice; private JButton openSerialButton; private JButton sendButton; private JTextArea sendArea; private JTextArea receiveArea; private JButton closeSerialButton; private List<String> 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<String>(); //串口选择(下拉框)  commChoice.setBounds(145, 390, 100, 30);  this.add(commChoice);  //添加波特率选项  bpsChoice = new JComboBox<String>(); //波特率选择  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); //显示窗口 }}

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


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表