使用Java实现简单串口通信

另参考网址:[
https://www.cnblogs.com/new-life/p/9345849.html
https://www.cnblogs.com/Dreamer-1/p/5523046.html
https://blog.csdn.net/weixin_37204973/article/details/90318136
]

最近一门课要求编写一个上位机串口通信工具,我基于Java编写了一个带有图形界面的简单串口通信工具,下面详述一下过程,供大家参考 _

一:

首先,你需要下载一个额外的支持Java串口通信操作的jar包,由于java.comm比较老了,而且不支持64位系统,这里推荐Rxtx这个jar包(32位/64位均支持)。

官方下载地址:http://fizzed.com/oss/rxtx-for-java (注:可能需要翻墙才能下载)

不能翻墙的童鞋,可以在这里下载:

http://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x86.zip (32位)

http://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x64.zip (64位)

二:

下载解压jar包并在 Java Build Path 下引入:

注:如果运行过程中抛出 java.lang.UnsatisfiedLinkError 错误或 gnu.io 下的类找不到,请将rxtx解压包中的 rxtxParallel.dll,rxtxSerial.dll 这两个文件复制到 C:\Windows\System32 目录下即可解决该错误。

三:

关于该jar包的使用,我写了一个SerialTool.java类,该类提供关于串口通信的各简单服务,代码如下(注意该类位于 serialPort 包里):

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.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;
import serialException.*;/*** 串口服务类,提供打开、关闭串口,读取、发送串口数据等服务(采用单例设计模式)* @author zhong**/
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 ArrayList<String> findPort() {//获得当前所有可用串口Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();    ArrayList<String> portNameList = new ArrayList<>();//将可用串口名添加到List并返回该Listwhile (portList.hasMoreElements()) {String portName = portList.nextElement().getName();portNameList.add(portName);}return portNameList;}/*** 打开串口* @param portName 端口名称* @param baudrate 波特率* @return 串口对象* @throws SerialPortParameterFailure 设置串口参数失败* @throws NotASerialPort 端口指向设备不是串口类型* @throws NoSuchPort 没有该端口对应的串口设备* @throws PortInUse 端口已被占用*/public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse {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 SerialPortParameterFailure();}//System.out.println("Open " + portName + " sucessfully !");return serialPort;}        else {//不是串口throw new NotASerialPort();}} catch (NoSuchPortException e1) {throw new NoSuchPort();} catch (PortInUseException e2) {throw new PortInUse();}}/*** 关闭串口* @param serialport 待关闭的串口对象*/public static void closePort(SerialPort serialPort) {if (serialPort != null) {serialPort.close();serialPort = null;}}/*** 往串口发送数据* @param serialPort 串口对象* @param order    待发送数据* @throws SendDataToSerialPortFailure 向串口发送数据失败* @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错*/public static void sendToPort(SerialPort serialPort, byte[] order) throws SendDataToSerialPortFailure, SerialPortOutputStreamCloseFailure {OutputStream out = null;try {out = serialPort.getOutputStream();out.write(order);out.flush();} catch (IOException e) {throw new SendDataToSerialPortFailure();} finally {try {if (out != null) {out.close();out = null;}                } catch (IOException e) {throw new SerialPortOutputStreamCloseFailure();}}}/*** 从串口读取数据* @param serialPort 当前已建立连接的SerialPort对象* @return 读取到的数据* @throws ReadDataFromSerialPortFailure 从串口读取数据时出错* @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错*/public static byte[] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure {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 new ReadDataFromSerialPortFailure();} finally {try {if (in != null) {in.close();in = null;}} catch(IOException e) {throw new SerialPortInputStreamCloseFailure();}}return bytes;}/*** 添加监听器* @param port     串口对象* @param listener 串口监听器* @throws TooManyListeners 监听类对象过多*/public static void addListener(SerialPort port, SerialPortEventListener listener) throws TooManyListeners {try {//给串口添加监听器port.addEventListener(listener);//设置当有数据到达时唤醒监听接收线程port.notifyOnDataAvailable(true);//设置当通信中断时唤醒中断线程port.notifyOnBreakInterrupt(true);} catch (TooManyListenersException e) {throw new TooManyListeners();}}}

注:该类方法中 throw 的 Exception 都是我自定义的 Exception,之所以这么做是为了方便在主程序中进行相应处理,下面贴其中一个Exception出来给大家做下说明:

(注意我所有自定义的 Exception 都放在 serialException 包里)

package serialException;public class SerialPortParameterFailure extends Exception {/*** */private static final long serialVersionUID = 1L;public SerialPortParameterFailure() {}@Overridepublic String toString() {return "设置串口参数失败!打开串口操作未完成!";}}

每个自定义的Exception类我都重写了它的 toString() 方法,便于主程序捕捉到该Exception后打印对应的错误信息

其中在serialException包里还有一个专门将接收到的Exception对象内的错误信息提取出来转换成字符串并返回的类,代码如下:

package serialException;import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;/*** 负责将传入的Exception中的错误信息提取出来并转换成字符串;* @author zhong**/
public class ExceptionWriter {/*** 将Exception中的错误信息封装到字符串中并返回该字符串* @param e 包含错误的Exception* @return 错误信息字符串*/public static String getErrorInfoFromException(Exception e) { StringWriter sw = null;PrintWriter pw = null;try {  sw = new StringWriter();  pw = new PrintWriter(sw);  e.printStackTrace(pw);  return "\r\n" + sw.toString() + "\r\n";  } catch (Exception e2) {  return "出错啦!未获取到错误信息,请检查后重试!";  } finally {try {if (pw != null) {pw.close();}if (sw != null) {sw.close();}} catch (IOException e1) {e1.printStackTrace();}}}
}

四:

主程序类的使用,Client.java里含有程序的入口地址(main方法),它的作用是显示一个欢迎界面并调用DataView.java这个类进行实际的串口数据显示。

Client.java代码如下:

package serialPort;import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;import javax.swing.JOptionPane;import serialException.ExceptionWriter;/*** 主程序* @author zhong**/
public class Client extends Frame{/*** */private static final long serialVersionUID = 1L;/*** 程序界面宽度*/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;Color color = Color.WHITE; Image offScreen = null;    //用于双缓冲//设置window的icon(这里我自定义了一下Windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)Toolkit toolKit = getToolkit();Image icon = toolKit.getImage(Client.class.getResource("computer.png"));//持有其他类DataView dataview = new DataView(this);    //主界面类(显示监控数据主面板)/*** 主方法* @param args    //*/public static void main(String[] args) {new Client().launchFrame();    }/*** 显示主界面*/public void launchFrame() {this.setBounds(LOC_X, LOC_Y, WIDTH, HEIGHT);    //设定程序在桌面出现的位置this.setTitle("CDIO工程项目");    //设置程序标题this.setIconImage(icon);this.setBackground(Color.white);    //设置背景色this.addWindowListener(new WindowAdapter() {//添加对窗口状态的监听public void windowClosing(WindowEvent arg0) {//当窗口关闭时System.exit(0);    //退出程序}});this.addKeyListener(new KeyMonitor());    //添加键盘监听器this.setResizable(false);    //窗口大小不可更改this.setVisible(true);    //显示窗口new Thread(new RepaintThread()).start();    //开启重画线程}/*** 画出程序界面各组件元素*/public void paint(Graphics g) {Color c = g.getColor();g.setFont(new Font("微软雅黑", Font.BOLD, 40));g.setColor(Color.black);g.drawString("欢迎使用上位机实时监控系统", 45, 190);g.setFont(new Font("微软雅黑", Font.ITALIC, 26));g.setColor(Color.BLACK);g.drawString("Version:1.0   Powered By:ZhongLei", 280, 260);g.setFont(new Font("微软雅黑", Font.BOLD, 30));g.setColor(color);g.drawString("————点击Enter键进入主界面————", 100, 480);//使文字 "————点击Enter键进入主界面————" 黑白闪烁if (color == Color.WHITE)    color = Color.black;else if (color == color.BLACK)    color = Color.white;}/*** 双缓冲方式重画界面各元素组件*/public void update(Graphics g) {if (offScreen == null)    offScreen = this.createImage(WIDTH, HEIGHT);Graphics gOffScreen = offScreen.getGraphics();Color c = gOffScreen.getColor();gOffScreen.setColor(Color.white);gOffScreen.fillRect(0, 0, WIDTH, HEIGHT);    //重画背景画布this.paint(gOffScreen);    //重画界面元素gOffScreen.setColor(c);g.drawImage(offScreen, 0, 0, null);    //将新画好的画布“贴”在原画布上}/** 内部类形式实现对键盘事件的监听*/private class KeyMonitor extends KeyAdapter {public void keyReleased(KeyEvent e) {int keyCode = e.getKeyCode();if (keyCode == KeyEvent.VK_ENTER) {    //当监听到用户敲击键盘enter键后执行下面的操作setVisible(false);    //隐去欢迎界面dataview.setVisible(true);    //显示监测界面dataview.dataFrame();    //初始化监测界面}}}/** 重画线程(每隔250毫秒重画一次)*/private class RepaintThread implements Runnable {public void run() {while(true) {repaint();try {Thread.sleep(250);} catch (InterruptedException e) {//重画线程出错抛出异常时创建一个Dialog并显示异常详细信息String err = ExceptionWriter.getErrorInfoFromException(e);JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}}}}}

运行截图:

注:实际运行过程中最下面的“点击Enter键进入主界面”有一个一闪一闪的效果(是通过每隔一段时间重画一次界面,让这句话以白黑两色反复交替出现实现的),双缓冲方式利于解决重画时界面闪烁的问题(如果不使用双缓冲方式的话相当于每次重画时是在旧界面上一点一点画上新东西,而双缓冲实质上是通过先在内存中直接画好一张新界面图,然后一次性直接用新界面覆盖掉旧界面)

DataView.java代码如下:(该类用于实时显示串口数据)

简单说明:

硬件设备每隔一段时间通过串口发送一次数据到计算机,该串口工具成功连接至硬件设备并添加监听后,会在每次接收到数据时解析数据并更新界面;

你在使用时很可能需求跟我不一样,该类仅供参考,实际使用中你很可能需要重新制作数据显示界面以及数据解析方式

package serialPort;import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.TooManyListenersException;import javax.swing.JOptionPane;import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import serialException.*;/*** 监测数据显示类* @author Zhong**/
public class DataView extends Frame {/*** */private static final long serialVersionUID = 1L;Client client = null;private List<String> commList = null;    //保存可用端口号private SerialPort serialPort = null;    //保存串口对象private Font font = new Font("微软雅黑", Font.BOLD, 25);private Label tem = new Label("暂无数据", Label.CENTER);    //温度private Label hum = new Label("暂无数据", Label.CENTER);    //湿度private Label pa = new Label("暂无数据", Label.CENTER);    //压强private Label rain = new Label("暂无数据", Label.CENTER);    //雨量private Label win_sp = new Label("暂无数据", Label.CENTER);    //风速private Label win_dir = new Label("暂无数据", Label.CENTER);    //风向private Choice commChoice = new Choice();    //串口选择(下拉框)private Choice bpsChoice = new Choice();    //波特率选择private Button openSerialButton = new Button("打开串口");Image offScreen = null;    //重画时的画布//设置window的iconToolkit toolKit = getToolkit();Image icon = toolKit.getImage(DataView.class.getResource("computer.png"));/*** 类的构造方法* @param client*/public DataView(Client client) {this.client = client;commList = SerialTool.findPort();    //程序初始化时就扫描一次有效串口}/*** 主菜单窗口显示;* 添加Label、按钮、下拉条及相关事件监听;*/public void dataFrame() {this.setBounds(client.LOC_X, client.LOC_Y, client.WIDTH, client.HEIGHT);this.setTitle("CDIO工程项目");this.setIconImage(icon);this.setBackground(Color.white);this.setLayout(null);this.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent arg0) {if (serialPort != null) {//程序退出时关闭串口释放资源SerialTool.closePort(serialPort);}System.exit(0);}});tem.setBounds(140, 103, 225, 50);tem.setBackground(Color.black);tem.setFont(font);tem.setForeground(Color.white);add(tem);hum.setBounds(520, 103, 225, 50);hum.setBackground(Color.black);hum.setFont(font);hum.setForeground(Color.white);add(hum);pa.setBounds(140, 193, 225, 50);pa.setBackground(Color.black);pa.setFont(font);pa.setForeground(Color.white);add(pa);rain.setBounds(520, 193, 225, 50);rain.setBackground(Color.black);rain.setFont(font);rain.setForeground(Color.white);add(rain);win_sp.setBounds(140, 283, 225, 50);win_sp.setBackground(Color.black);win_sp.setFont(font);win_sp.setForeground(Color.white);add(win_sp);win_dir.setBounds(520, 283, 225, 50);win_dir.setBackground(Color.black);win_dir.setFont(font);win_dir.setForeground(Color.white);add(win_dir);//添加串口选择选项commChoice.setBounds(160, 397, 200, 200);//检查是否有可用串口,有则加入选项中if (commList == null || commList.size()<1) {JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);}else {for (String s : commList) {commChoice.add(s);}}add(commChoice);//添加波特率选项bpsChoice.setBounds(526, 396, 200, 200);bpsChoice.add("1200");bpsChoice.add("2400");bpsChoice.add("4800");bpsChoice.add("9600");bpsChoice.add("14400");bpsChoice.add("19200");bpsChoice.add("115200");add(bpsChoice);//添加打开串口按钮openSerialButton.setBounds(250, 490, 300, 50);openSerialButton.setBackground(Color.lightGray);openSerialButton.setFont(new Font("微软雅黑", Font.BOLD, 20));openSerialButton.setForeground(Color.darkGray);add(openSerialButton);//添加打开串口按钮的事件监听openSerialButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {//获取串口名称String commName = commChoice.getSelectedItem();            //获取波特率String bpsStr = 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());//监听成功进行提示JOptionPane.showMessageDialog(null, "监听成功,稍后将显示监测数据!", "提示", JOptionPane.INFORMATION_MESSAGE);} catch (SerialPortParameterFailure | NotASerialPort | NoSuchPort | PortInUse | TooManyListeners e1) {//发生错误时使用一个Dialog提示具体的错误信息JOptionPane.showMessageDialog(null, e1, "错误", JOptionPane.INFORMATION_MESSAGE);}}}}});this.setResizable(false);new Thread(new RepaintThread()).start();    //启动重画线程}/*** 画出主界面组件元素*/public void paint(Graphics g) {Color c = g.getColor();g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 温度: ", 45, 130);g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 湿度: ", 425, 130);g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 压强: ", 45, 220);g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 雨量: ", 425, 220);g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 风速: ", 45, 310);g.setColor(Color.black);g.setFont(new Font("微软雅黑", Font.BOLD, 25));g.drawString(" 风向: ", 425, 310);g.setColor(Color.gray);g.setFont(new Font("微软雅黑", Font.BOLD, 20));g.drawString(" 串口选择: ", 45, 410);g.setColor(Color.gray);g.setFont(new Font("微软雅黑", Font.BOLD, 20));g.drawString(" 波特率: ", 425, 410);}/*** 双缓冲方式重画界面各元素组件*/public void update(Graphics g) {if (offScreen == null)    offScreen = this.createImage(Client.WIDTH, Client.HEIGHT);Graphics gOffScreen = offScreen.getGraphics();Color c = gOffScreen.getColor();gOffScreen.setColor(Color.white);gOffScreen.fillRect(0, 0, Client.WIDTH, Client.HEIGHT);    //重画背景画布this.paint(gOffScreen);    //重画界面元素gOffScreen.setColor(c);g.drawImage(offScreen, 0, 0, null);    //将新画好的画布“贴”在原画布上}/** 重画线程(每隔30毫秒重画一次)*/private class RepaintThread implements Runnable {public void run() {while(true) {//调用重画方法repaint();//扫描可用串口commList = SerialTool.findPort();if (commList != null && commList.size()>0) {//添加新扫描到的可用串口for (String s : commList) {//该串口名是否已存在,初始默认为不存在(在commList里存在但在commChoice里不存在,则新添加)boolean commExist = false;    for (int i=0; i<commChoice.getItemCount(); i++) {if (s.equals(commChoice.getItem(i))) {//当前扫描到的串口名已经在初始扫描时存在commExist = true;break;}                    }if (commExist) {//当前扫描到的串口名已经在初始扫描时存在,直接进入下一次循环continue;}else {//若不存在则添加新串口名至可用串口下拉列表commChoice.add(s);}}//移除已经不可用的串口for (int i=0; i<commChoice.getItemCount(); i++) {//该串口是否已失效,初始默认为已经失效(在commChoice里存在但在commList里不存在,则已经失效)boolean commNotExist = true;    for (String s : commList) {if (s.equals(commChoice.getItem(i))) {commNotExist = false;    break;}}if (commNotExist) {//System.out.println("remove" + commChoice.getItem(i));commChoice.remove(i);}else {continue;}}}else {//如果扫描到的commList为空,则移除所有已有串口commChoice.removeAll();}try {Thread.sleep(30);} catch (InterruptedException e) {String err = ExceptionWriter.getErrorInfoFromException(e);JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}}}}/*** 以内部类形式创建一个串口监听类* @author zhong**/private 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 溢位(溢出)错误case SerialPortEvent.FE: // 9 帧错误case SerialPortEvent.PE: // 8 奇偶校验错误case SerialPortEvent.CD: // 6 载波检测case SerialPortEvent.CTS: // 3 清除待发送数据case SerialPortEvent.DSR: // 4 待发送数据准备好了case SerialPortEvent.RI: // 5 振铃指示case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 输出缓冲区已清空break;case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用数据//System.out.println("found data");byte[] data = null;try {if (serialPort == null) {JOptionPane.showMessageDialog(null, "串口对象为空!监听失败!", "错误", JOptionPane.INFORMATION_MESSAGE);}else {data = SerialTool.readFromPort(serialPort);    //读取数据,存入字节数组//System.out.println(new String(data));// 自定义解析过程,你在实际使用过程中可以按照自己的需求在接收到数据后对数据进行解析if (data == null || data.length < 1) {    //检查数据是否读取正确    JOptionPane.showMessageDialog(null, "读取数据过程中未获取到有效数据!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}else {String dataOriginal = new String(data);    //将字节数组数据转换位为保存了原始数据的字符串String dataValid = "";    //有效数据(用来保存原始数据字符串去除最开头*号以后的字符串)String[] elements = null;    //用来保存按空格拆分原始字符串后得到的字符串数组    //解析数据if (dataOriginal.charAt(0) == '*') {    //当数据的第一个字符是*号时表示数据接收完成,开始解析                            dataValid = dataOriginal.substring(1);elements = dataValid.split(" ");if (elements == null || elements.length < 1) {    //检查数据是否解析正确JOptionPane.showMessageDialog(null, "数据解析过程出错,请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}else {try {//更新界面Label值/*for (int i=0; i<elements.length; i++) {System.out.println(elements[i]);}*///System.out.println("win_dir: " + elements[5]);tem.setText(elements[0] + " ℃");hum.setText(elements[1] + " %");pa.setText(elements[2] + " hPa");rain.setText(elements[3] + " mm");win_sp.setText(elements[4] + " m/s");win_dir.setText(elements[5] + " °");} catch (ArrayIndexOutOfBoundsException e) {JOptionPane.showMessageDialog(null, "数据解析过程出错,更新界面数据失败!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}}    }}}                        } catch (ReadDataFromSerialPortFailure | SerialPortInputStreamCloseFailure e) {JOptionPane.showMessageDialog(null, e, "错误", JOptionPane.INFORMATION_MESSAGE);System.exit(0);    //发生读取错误时显示错误信息后退出系统}    break;}}}}

运行截图:



整个项目源码打包下载:http://files.cnblogs.com/files/Dreamer-1/serialMonitor.rar

使用Java实现简单串口通信相关推荐

  1. java串口发送十六进制数,本文实例为大家分享了Java实现串口通信的具体代码,供大家参考,具体内容如下1.介绍使用Java实现的串口通信程序,支持十六进制数据的发送与接收。 源码:...

    本文实例为大家分享了Java实现串口通信的具体代码,供大家参考,具体内容如下 1.介绍 使用Java实现的串口通信程序,支持十六进制数据的发送与接收. 源码:SerialPortDemo 效果图如下: ...

  2. STM32CubeMX基于HAL库实现简单串口通信

    STM32CubeMX基于HAL库实现简单串口通信 板子:STM32F103C8 编译工具:Keil+STM32CubeMX 烧录工具:FlyMcu 串口调试程序:XCOM 实验要求: 1)设置波特率 ...

  3. java奇偶校验_串口通信的奇偶校验

    串口通信中数据的奇偶校验位算法 转载 奇偶校验位是一个表示给定位数的二进制数中 1 的个数是奇数还是偶数的二进制数.奇偶校验位是最简单的错误检测码.奇偶校验位有两种类型:偶校验位与奇校验位.如果一组给 ...

  4. 使用RXTX实现简单串口通信调试工具

    最终效果如下图: 1.把rxtxParallel.dll.rxtxSerial.dll拷贝到:C:\WINDOWS\system32下. 2.RXTXcomm.jar 添加到项目类库中. packag ...

  5. C#实现简单串口通信助手

    建立好一个form后,选择工具箱,在组件所属里找到SerialPort: 拖拽一个即可. 这时可以看到属性栏: 可以查看修改默认属性值. 这时就可以通过控件设计我们的界面啦: 我这里设计的很简单,包括 ...

  6. Java结合Web页面使用多线程实现全双工串口通信

    在几天在接手的项目中要求实现串口全双工通信,由于自己Java也是刚刚开始学习有些概念还不是理解的很透彻,所以这个工程还是花费了点时间,遇到了些许问题都会在这篇文章中有所体现,还有源码凹,希望可以帮助到 ...

  7. java plc通信协议_Java实现计算机与OMRONPLC串口通信.pdf

    Java实现计算机与OMRONPLC串口通信 · 84 · 工业仪表与 自动化装置 2010年第 1期 Java实现计算机与oMRONPLC串口通信 吴兴军.胡汉春 (北京西动车所:西南交通大学机械工 ...

  8. Java程序与串口的通信实现及调试

    下面为大家介绍一下小编最近一个项目中,牵扯到与串口通信部分的实现及调试. 串口通信原理 串口通信指串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数 ...

  9. 在WEBSTART中实现串口通信(WINDOWS版)

    在WEBSTART中实现串口通信(WINDOWS版) 看到这个题目,你是不是问:这跟在JAVA中实现串口通信有什么区别?在JAVA中能做在WEBSTART中不就 一样吗? 真聪明,的确是这样的,但事实 ...

  10. 使用RXTXcomm进行串口通信

    RXTXcomm 串口通信 虚拟串口和串口调试助手的使用 虚拟串口软件:VSPD,https://www.eltima.com/cn/products/vspdxp/ VSPD会自动识别出本台计算上有 ...

最新文章

  1. (14)Why some people find exercise harder than others
  2. 向一个有N个元素的顺序表中插入一个元素,平均要移动的次数为多少
  3. 为什么《梦幻西游》能这么长寿(二):拆解其交易系统的高深之处
  4. 关于struts2在页面请求转发到action的问题
  5. FFMpeg中apiexample.c例子分析——解码分析
  6. 面板数据回归模型(固定效应、随机效应、混合回归、变系数)、面板数据AR、VAR模型
  7. OpenAI公布强化学习新算法,可控制复杂机器人
  8. 在InstallShield中发布单一的Setup.exe文件
  9. 【Windows网络编程】完成端口IOCP介绍(超详细)
  10. c语言 获取硬盘序列号,获取硬盘序列号的C++代码
  11. 智商、情商和逆商与程序员职业生涯发展
  12. QLabel设置字体颜色
  13. 日了。这个竟然还不让发
  14. rtsp直播流转m3u8
  15. Apache Airflow系列文章
  16. veket+linux+v7,veket linux安装工具
  17. 健壮I/O读写函数——RIO包
  18. IDEA+Java+SSM+Mysql+Bootstrap+Maven实现学校教务管理系统
  19. RT-Thread Studio学习(四)infrared软件包
  20. MySQL设置简单密码

热门文章

  1. 使用线程池管理线程!
  2. jQuery直接调用asp.net后台WebMethod方法
  3. dojo/dom-class源码学习
  4. tcp/ip ---IP路由选择
  5. virtualbox中给CentOS根分区扩容的方法
  6. Spring集成Quartz定时任务框架介绍和Cron表达式详解
  7. [转]在C#中使用MSHTML的高级支持接口
  8. 解决排列组合问题的通用算法(转)
  9. 3.软件架构设计:大型网站技术架构与业务架构融合之道 --- 语言
  10. 变频器22b系列说明书_变频器接电位器正确接法