Java串口通信读写串口导致程序崩溃问题
最近心血来潮想用java实现与下位机的串口通讯,下位机使用STM32等间隔向串口发送八位的数据,上位机主要实现数据的接收和发送。过程中遇到的问题为:一旦执行到输入输出流对串口进行读写操作时,程序直接崩溃,截图和全部代码如下,希望有经验的朋友能指点迷津:
程序运行初始界面:
点击“打开串口”按钮后直接闪退崩溃:
项目所有代码片(无保留):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Scanner;
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 serialCommunication extends JFrame implements ActionListener, SerialPortEventListener {//串口对象、串口名称列表SerialPort serialPort;ArrayList<String> arrayList = null;InputStream inputStream = null;OutputStream outputStream = null;//拆分窗格JSplitPane jSplitPane1;//设置、接收区、发送区、发送总区、左总区、右绘图区、小区1,2,3JPanel panel1, panel2, panel3, panel4, panel5, panel6, panel7, panel8, panel9;//清空接收区、打开/关闭串口、清空发送区、发送数据JButton button1, button2, button3, button4;//选择串口、波特率、发送模式、接收模式JLabel jLabel1, jLabel2, jLabel3, jLabel4;//选择串口组合框、波特率组合框JComboBox jComboBox1, jComboBox2;//Hex、字符、Hex、字符JRadioButton jRadioButton1, jRadioButton2, jRadioButton3, jRadioButton4;//组里只可二选一ButtonGroup buttonGroup1, buttonGroup2;//接收显示区、发送显示区JTextArea jTextArea1, jTextArea2;//显示区滚动条JScrollPane jScrollPane1, jScrollPane2;//主--方法public static void main(String[] args) {new serialCommunication();}//构造--方法public serialCommunication() {initWindow();addSerialPort();}//初始化窗口控件--方法--调用于构造函数serialCommunication()public void initWindow() {panel1 = new JPanel(); //设置panel2 = new JPanel(); //接收区panel3 = new JPanel(); //发送区panel4 = new JPanel(); //发送总区panel5 = new JPanel(); //左边总区panel6 = new JPanel(); //右边绘图区panel7 = new JPanel(); //单选区1panel8 = new JPanel(); //单选区2panel9 = new JPanel(); //小区3//设置panel左上标题Border titleBorder1 = BorderFactory.createTitledBorder("设置");panel1.setBorder(titleBorder1);Border titleBorder2 = BorderFactory.createTitledBorder("接收区");panel2.setBorder(titleBorder2);Border titleBorder3 = BorderFactory.createTitledBorder("发送区");panel3.setBorder(titleBorder3);jLabel1 = new JLabel("选择串口", JLabel.CENTER);jLabel2 = new JLabel("波 特 率", JLabel.CENTER);jLabel3 = new JLabel("发送模式", JLabel.CENTER);jLabel4 = new JLabel("接收模式", JLabel.CENTER);jLabel1.setFont(new Font("Dialog", Font.BOLD, 14));jLabel2.setFont(new Font("Dialog", Font.BOLD, 14));jLabel3.setFont(new Font("Dialog", Font.BOLD, 14));jLabel4.setFont(new Font("Dialog", Font.BOLD, 14));jComboBox1 = new JComboBox();String[] baudRate_str = {"600", "1200", "2400", "4800", "9600", "14400", "19200", "115200"};jComboBox2 = new JComboBox(baudRate_str);//设置波特率默认显示值“9600”jComboBox2.setSelectedIndex(4);jComboBox1.setFont(new Font("Dialog", Font.BOLD, 12));jComboBox2.setFont(new Font("Dialog", Font.BOLD, 12));jRadioButton1 = new JRadioButton("HEX", true);jRadioButton2 = new JRadioButton("字符", false);jRadioButton3 = new JRadioButton("HEX", true);jRadioButton4 = new JRadioButton("字符", false);jRadioButton1.setFont(new Font("Dialog", Font.BOLD, 12));jRadioButton2.setFont(new Font("Dialog", Font.BOLD, 12));jRadioButton3.setFont(new Font("Dialog", Font.BOLD, 12));jRadioButton4.setFont(new Font("Dialog", Font.BOLD, 12));buttonGroup1 = new ButtonGroup();buttonGroup2 = new ButtonGroup();buttonGroup1.add(jRadioButton1);buttonGroup1.add(jRadioButton2);buttonGroup2.add(jRadioButton3);buttonGroup2.add(jRadioButton4);jTextArea1 = new JTextArea();jTextArea2 = new JTextArea();jScrollPane1 = new JScrollPane(jTextArea1);jScrollPane2 = new JScrollPane(jTextArea2);button1 = new JButton("清 空"); //清空接收区button2 = new JButton("打开串口"); //打开/关闭串口button3 = new JButton("清 空"); //清空发送区button4 = new JButton("发送数据"); //发送button2.setSize(100, 60);button4.setSize(100, 60);button1.setFont(new Font("Dialog", Font.BOLD, 14));button2.setFont(new Font("Dialog", Font.BOLD, 16));button3.setFont(new Font("Dialog", Font.BOLD, 14));button4.setFont(new Font("Dialog", Font.BOLD, 16));//添加按钮监听设置按钮区别码button1.addActionListener(this);button1.setActionCommand("清空接收区");button2.addActionListener(this);button2.setActionCommand("打开/关闭串口");button3.addActionListener(this);button3.setActionCommand("清空发送区");button4.addActionListener(this);button4.setActionCommand("发送");panel7.add(jRadioButton1);panel7.add(jRadioButton2);panel8.add(jRadioButton3);panel8.add(jRadioButton4);//网格布局 //使控件之间有间隙panel1.setLayout(new GridLayout(4, 2, 0, 18));panel1.add(jLabel1);panel1.add(jComboBox1);panel1.add(jLabel2);panel1.add(jComboBox2);panel1.add(jLabel3);panel1.add(panel7);panel1.add(jLabel4);panel1.add(panel8);//边界布局(文本域可以变大)panel2.setLayout(new BorderLayout(0, 10));panel2.add(button1, BorderLayout.NORTH);panel2.add(jScrollPane1);panel3.setLayout(new BorderLayout(0, 7));panel3.add(button3, BorderLayout.NORTH);panel3.add(jScrollPane2);//设置控件与边界距离panel9.setBorder(BorderFactory.createEmptyBorder(15, 0, 15, 5));panel9.setLayout(new GridLayout(2, 1, 0, 20));panel9.add(button2);panel9.add(button4);panel4.setLayout(new GridLayout(1, 2, 10, 10));panel4.add(panel3);panel4.add(panel9);panel5.setLayout(new GridLayout(3, 1));panel5.add(panel1);panel5.add(panel2);panel5.add(panel4);jSplitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel5, panel6);jSplitPane1.setEnabled(false); //禁止拖动分隔线jSplitPane1.setOneTouchExpandable(false); //禁止分隔线上的左右缩扩小箭头this.add(jSplitPane1);this.setTitle("Upper"); //设置主窗体名称this.setIconImage((new ImageIcon("image/07_up.png")).getImage()); //设置主窗体图标this.setSize(800, 600); //设置主窗体宽度、高度this.setLocation(50, 50); //设置主窗体起始位置this.setResizable(false); //禁止修改主窗体大小this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //关闭JFrame时,退出程序this.setVisible(true);jSplitPane1.setDividerLocation(0.3); //设置拆分窗格分隔比}//重写按钮监听--方法@Overridepublic void actionPerformed(ActionEvent actionEvent) {if (actionEvent.getActionCommand().equals("清空接收区")) {jTextArea1.setText("");} else if (actionEvent.getActionCommand().equals("打开/关闭串口")) {if ("打开串口".equals(button2.getText()) && serialPort == null) {//打开串口之后如果有数据即可接收并显示openSelectedSerialPort();} else {closeSelectedSerialPort();}} else if (actionEvent.getActionCommand().equals("清空发送区")) {jTextArea2.setText("");} else if (actionEvent.getActionCommand().equals("发送")) {sendData();}}//检测串口并添加--方法--调用于构造函数serialCommunication()public void addSerialPort() {arrayList = findPorts();if (arrayList == null || arrayList.size() < 1) {jComboBox1.addItem("未发现可用串口");} else {for (String s : arrayList) {jComboBox1.addItem(s);}}}//检测并返回可用串口名称列表--方法--调用于addSerialPort()public ArrayList<String> findPorts() {//不带参数的getPortIdentifiers方法获得一个枚举对象,该对象又包含了系统中管理每个端口的CommPortIdentifier对象。//注意这里的端口不仅仅是指串口,也包括并口。//这个方法还可以带参数。//getPortIdentifiers(CommPort)获得与已经被应用程序打开的端口相对应的CommPortIdentifier对象。//getPortIdentifier(String portName)获取指定端口名(比如“COM1”)的CommPortIdentifier对象。Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();//存储可用串口的ArrayListArrayList<String> serialPortNameList = new ArrayList<>();while (portList.hasMoreElements()) {//获取端口名称String portName = portList.nextElement().getName();//通过端口名识别端口CommPortIdentifier commPortIdentifier = null;try {commPortIdentifier = CommPortIdentifier.getPortIdentifier(portName);} catch (NoSuchPortException e) {e.printStackTrace();}//打开端口,并给端口名字和一个timeout(打开操作的超时时间)CommPort commPort = null;try {commPort = commPortIdentifier.open(portName, 2000);} catch (PortInUseException | NullPointerException e) {e.printStackTrace();}//判断是不是串口if (commPort instanceof SerialPort) {serialPortNameList.add(portName);//判断完后关闭串口commPort.close();}}return serialPortNameList;}//打开选中的串口--方法--调用于按钮监听public void openSelectedSerialPort() {//获取串口名称 //获取波特率String serialPortName = (String) jComboBox1.getSelectedItem();int baudRate = Integer.parseInt((String) jComboBox2.getSelectedItem());if (serialPortName == null || serialPortName.equals("未发现可用串口")) {JOptionPane.showMessageDialog(this, "未发现可用串口", "error", JOptionPane.ERROR_MESSAGE);} else {try {CommPortIdentifier commPortIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);//CommPort commPort = commPortIdentifier.open(serialPortName, 1000);serialPort = (SerialPort) commPortIdentifier.open(serialPortName, 1000);//设置选中串口的参数serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);jTextArea1.append("串口已打开!" + "\r\n");button2.setText("关闭串口");//向串口添加事件监听对象serialPort.addEventListener(this);//设置当串口有可用数据时触发事件,此设置必不可少serialPort.notifyOnDataAvailable(true);} catch (NoSuchPortException | PortInUseException | UnsupportedCommOperationException | TooManyListenersException e) {e.printStackTrace();}}}//关闭选中的串口--方法--调用于按钮监听public void closeSelectedSerialPort() {if (serialPort != null) {serialPort.close();jTextArea1.append("串口已关闭!" + "\r\n");button2.setText("打开串口");serialPort = null;}}//重写串口监听--方法@Overridepublic void serialEvent(SerialPortEvent serialPortEvent) {if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {try {//获取串口输入流inputStream = serialPort.getInputStream();int availableBytes = inputStream.available();byte[] cache = new byte[availableBytes];
/* System.out.println("带读取字节数" + availableBytes);Scanner in = new Scanner(System.in);int a = in.nextInt();System.out.println(a);*/ //测试部分,让程序卡在这里,一旦注释掉//就会崩溃,使用输入输出流进行读写直接崩溃!!!求大神解答while (availableBytes > 0) {inputStream.read(cache);for (int i = 0; i < availableBytes; i++) {int v = cache[i] & 0xFF;String hv = Integer.toHexString(v);jTextArea1.append(hv);inputStream.close();}}} catch (IOException e) {e.printStackTrace();}}}//向串口发送数据--方法--调用与按钮监听public void sendData() {try {if (serialPort != null) {outputStream = serialPort.getOutputStream();/* System.out.println("带读取字节数" + availableBytes);Scanner in = new Scanner(System.in);int a = in.nextInt();System.out.println(a);*/ //测试部分,让程序卡在这里,一旦注释掉就会崩溃,使用输入输出流进行读写直接崩溃!!!求大神解答outputStream.write(new byte[]{'h', 'e', 'l', 'l', 'o', '!'});outputStream.flush();outputStream.close();} else {JOptionPane.showMessageDialog(this, "请先打开串口", "warning", JOptionPane.WARNING_MESSAGE);}} catch (IOException e) {e.printStackTrace();}}
}
Java串口通信读写串口导致程序崩溃问题相关推荐
- java程序一写文件就崩溃_为什么直接修改java的.class文件会导致程序崩溃
是这样的. 有一次,hardcode了ip地址在代码里,由于懒得重新编译. 强行用记事本打开.class文件,发现里面已经面目全非了,但是数字还是原来的样子. 于是直接改了.class文件里的数字,换 ...
- 解决QT接受串口数据时数据更新不及时,串口数据太多导致程序界面崩溃,串口接收数据过快等问题
1.问题背景 最近在使用上位机测试传感器接受数据是否正常,发现了很多问题,由于没有系统的学过Qt,用到什么库就学什么库,导致库中的函数很多不清晰,产生了标题中的一系列问题,经过不断的尝试,终于解决上述 ...
- 基于串口通信的DSP应用程序在线升级方法
摘 要:为解决特殊场合DSP程序升级困难的问题,以TMS320F28035为例,介绍了一种基于串口通信的适合于TMS320C2000系列DSP实现程序更新的在线升级方法.描述了该在线升级方法的基本思 ...
- 串口通信及串口转蓝牙相关知识
之前没有接触过硬件相关的工作, 因此对硬件的知识一知半解. 最近由于项目需要, 用到了串口通信以及串口跟蓝牙之间通信相关的东西.记录下来, 希望对新手有所帮助. 如有疏漏之处, 欢迎指正. 1 串口通 ...
- 树莓派已经通过网络连接通过串口通信在串口调试小助手打印与操作
在树莓派编译运行 树莓派已经通过网络连接通过串口通信在串口调试小助手打印C gcc xxx.c -lwiringPi 源码 #include <wiringSerial.h> #inclu ...
- goroutine中使用recover,解决协程中出现panic,导致程序崩溃的问题。recover panic 协程的错误处理
package mainimport ("fmt""time" )//goroutine中使用recover,解决协程中出现panic,导致程序崩溃的问题. f ...
- OpenCV中waitKey()函数失效问题汇总(按键失效、按键不灵、按键导致程序崩溃)
提示:阅读文章,大约需要3分钟 问题描述 在使用OpenCV编程的时候,我们经常会使用按键等待函数:waitKey(),大家可能会用它来作为 延迟.等待用户输入按键的功能使用,以下列出了在使用过程中遇 ...
- laravel清理缓存(config:clear)后导致程序崩溃
laravel清理缓存(config:clear)后导致程序崩溃 前情提要:导致这个错误的可能性有很多,如此不人性化的提示是因为在config:clear后laravel重载出错,然后尝试从log输出 ...
- MFC使用GetDlgItem获取控件导致程序崩溃的问题
对于MFC窗口,在没有被创建完成时,是无法获取控件资源的.如果将GetDlgItem写在窗口类构造函数中,就会导致程序崩溃 正确方法是将GetDlgItem放在窗口类的OnInitDialog函数中执 ...
最新文章
- 如何使用Ajax技术开发Web应用程序(2)
- linux/centos 解决Tomcat内存溢出,centostomcat
- 双轴机械臂中的闭环步进电机平顺控制算法: 42HS48EIS,57HS
- 2020年全国大学生智能汽车竞赛山东赛区比赛专家组工作方案
- 理解Java对象序列化
- python tushare获取股票数据并可视化_荐Python获取股票数据及其可视化--基于tushare库...
- 链式运动JavaScript实现
- php+剥去标签,php剥去字符串中的html与xml及php标签的函数strip_tags()
- 在 Azure App Service 上运行 .NET 6 预览版
- OpenJudge NOI 1.7 32:行程长度编码
- c#winform演练 ktv项目 实现上一曲和下一曲的播放功能
- docker部署web项目_IntelliJ IDEA 部署 Web 项目
- 使用 TFLite 在移动设备上优化与部署风格转化模型
- MSSQL差异备份拿shell(转)
- 向eclipse中导入myeclipse项目
- Scrapy爬取小说简单逻辑
- JanusGraph对于Gremlin查询语言的介绍
- 级联阴影贴图(CSM)
- H5接入支付流程-微信支付支付宝支付
- TCPDF 解决中文乱码的问题
热门文章
- 相关系数pearson、spearman、kendall和R语言中的cor/or.test()
- Oracle分页查询存储过程(适用于单表查询)
- 前端页面模拟浏览器搜索功能Ctrl+F实现
- 通信基础篇小项目-----简单网络画板的的实现
- scp命令默认传输速度多大_加速scp传输速度
- python flask 直接调用摄像头直播
- 在小程序中实现海报制作
- Enter键绑定按钮或方法
- linux 备份信息查看器,linux 全新的备份神器 Duplicity
- 创建数据库失败((Microsoft.SqlServer.Smo))执行Transact-SQL语句或批处理时发生了异常。