java监听、读取串口数据

一但说要监听一个串口的数据,我们一般都会是会想到C#,但是就是不想用C#来开发。其实java也是可以的。

第一:需要下载一个额外的支持Java串口通信操作的jar包,Rxtx这个jar包(32位/64位均支持)。下载地址(里面有windows(x64和x86)和linux(x64和x86)的驱动包):http://download.csdn.net/download/atgeretg/10122892
官方下载地址:http://fizzed.com/oss/rxtx-for-java (注:可能需要FQ才能下载)
使用方法如下:
拷贝 RXTXcomm.jar 到 <JAVA_HOME>\jre\lib\ext目录中; 
拷贝 rxtxSerial.dll 到 <JAVA_HOME>\jre\bin目录中; 
拷贝 rxtxParallel.dll 到 <JAVA_HOME>\jre\bin目录中; 
<JAVA_HOME>为jdk安装
第二:
下载解压,将RXTXcomm.jar包在 Java Build Path 下引入项目,就可以了,你的java项目就可以监听到电脑com数据了

 

捕获

 

第三:关于该jar包读取串口的使用,我写了一个小Demo,以下是小Demo的部分类。项目下载地址:http://download.csdn.net/download/atgeretg/10121971

MainFrame该类提供界面化的串口通信的各简单操作,代码如下:

public class MainFrame extends JFrame implements ActionListener {


/**
* 程序界面宽度
*/
public static final int WIDTH = 500;


/**
* 程序界面高度
*/
public static final int HEIGHT = 360;


private JTextPane dataView = new JTextPane();
private JScrollPane scrollDataView = new JScrollPane(dataView);


// 串口设置面板
private JPanel serialPortPanel = new JPanel();
private JLabel serialPortLabel = new JLabel("串口");
private JLabel baudrateLabel = new JLabel("波特率");
private JComboBox commChoice = new JComboBox();
private JComboBox baudrateChoice = new JComboBox();


// 操作面板
private JPanel operatePanel = new JPanel();
private JTextArea dataInput = new JTextArea();
private JButton serialPortOpenBtn = new JButton("打开串口");
private JButton sendDataBtn = new JButton("发送数据");
private JButton openCmdButton = new JButton("打开射频");
private JButton closeCmdButton = new JButton("关闭射频");


/**
* 正常的风格
*/
private final String STYLE_NORMAL = "normal";
/**
* 字体为红色
*/
private final String STYLE_RED = "red";


private List<String> commList = null;
private SerialPort serialport;


public MainFrame() {
initView();
initComponents();
initData();
}


private void initView() {
// 关闭程序
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// 禁止窗口最大化
setResizable(false);


// 设置程序窗口居中显示
Point p = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
setBounds(p.x - WIDTH / 2, p.y - HEIGHT / 2, 499, 455);
getContentPane().setLayout(null);


setTitle("串口通讯");
}


private void initComponents() {
// 数据显示
dataView.setFocusable(false);
scrollDataView.setBounds(10, 10, 475, 200);
/* 数据区域的风格 */
Style def = dataView.getStyledDocument().addStyle(null, null);
StyleConstants.setFontFamily(def, "verdana");
StyleConstants.setFontSize(def, 12);
Style normal = dataView.addStyle(STYLE_NORMAL, def);
Style s = dataView.addStyle(STYLE_RED, normal);
StyleConstants.setForeground(s, Color.RED);
dataView.setParagraphAttributes(normal, true);


getContentPane().add(scrollDataView);


// 串口设置
serialPortPanel.setBorder(BorderFactory.createTitledBorder("串口设置"));
serialPortPanel.setBounds(10, 220, 170, 188);
serialPortPanel.setLayout(null);
getContentPane().add(serialPortPanel);


serialPortLabel.setForeground(Color.gray);
serialPortLabel.setBounds(10, 25, 40, 20);
serialPortPanel.add(serialPortLabel);


commChoice.setFocusable(false);
commChoice.setBounds(60, 25, 100, 20);
serialPortPanel.add(commChoice);


baudrateLabel.setForeground(Color.gray);
baudrateLabel.setBounds(10, 60, 40, 20);
serialPortPanel.add(baudrateLabel);


baudrateChoice.setFocusable(false);
baudrateChoice.setBounds(60, 60, 100, 20);
serialPortPanel.add(baudrateChoice);


// 操作
operatePanel.setBorder(BorderFactory.createTitledBorder("操作"));
operatePanel.setBounds(200, 220, 285, 188);
operatePanel.setLayout(null);
getContentPane().add(operatePanel);


dataInput.setBounds(25, 25, 235, 63);
operatePanel.add(dataInput);


serialPortOpenBtn.setFocusable(false);
serialPortOpenBtn.setBounds(45, 98, 90, 20);
serialPortOpenBtn.addActionListener(this);
operatePanel.add(serialPortOpenBtn);


sendDataBtn.setFocusable(false);
sendDataBtn.setBounds(155, 98, 90, 20);
sendDataBtn.addActionListener(this);
operatePanel.add(sendDataBtn);


openCmdButton.setBounds(45, 128, 90, 20);
openCmdButton.addActionListener(this);
operatePanel.add(openCmdButton);


closeCmdButton.setBounds(155, 128, 90, 20);
closeCmdButton.addActionListener(this);
operatePanel.add(closeCmdButton);


JButton btnNewButton = new JButton("clear");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dataView.setText("");
}
});
btnNewButton.setBounds(45, 158, 90, 20);
operatePanel.add(btnNewButton);


}


@SuppressWarnings("unchecked")
private void initData() {
commList = SerialPortManager.findPort();
// 检查是否有可用串口,有则加入选项中
if (commList == null || commList.size() < 1) {
DialogShowUtils.warningMessage("没有搜索到有效串口!");
} else {
for (String s : commList) {
commChoice.addItem(s);
}
}


baudrateChoice.addItem("9600");
baudrateChoice.addItem("19200");
baudrateChoice.addItem("38400");
baudrateChoice.addItem("57600");
baudrateChoice.addItem("115200");
}




/**
* 打开串口

*/
private void openSerialPort() {




// 获取串口名称
String commName = (String) commChoice.getSelectedItem();
// 获取波特率
int baudrate = 9600;
String bps = (String) baudrateChoice.getSelectedItem();
baudrate = Integer.parseInt(bps);


// 检查串口名称是否获取正确
if (commName == null || commName.equals("")) {
DialogShowUtils.warningMessage("没有搜索到有效串口!");
} else {
try {
serialport = SerialPortManager.openPort(commName, baudrate);
if (serialport != null) {
dataShow("串口已打开",STYLE_RED);
serialPortOpenBtn.setText("关闭串口");
}
} catch (SerialPortParameterFailure e) {
e.printStackTrace();
} catch (NotASerialPort e) {
e.printStackTrace();
} catch (NoSuchPort e) {
e.printStackTrace();
} catch (PortInUse e) {
e.printStackTrace();
DialogShowUtils.warningMessage("串口已被占用!");
}
}


try {
SerialPortManager.addListener(serialport, new SerialListener());
} catch (TooManyListeners e) {
e.printStackTrace();
}
}

/**
* 关闭串口

*/
private void closeSerialPort() {
SerialPortManager.closePort(serialport);
dataShow("已经关闭串口",STYLE_RED);
serialPortOpenBtn.setText("打开串口");
serialport = null;
}

/**
* 打印数据到面板上

*/
private void dataShow(String text,String style) {
StringBuilder builderData = new StringBuilder();
builderData.setLength(0);
builderData.append(MyUtils.formatDateStr_ss()).append("\r\n").append(text).append("\r\n");
try {
Document document = dataView.getDocument();
if(STYLE_RED.equals(style))
dataView.getDocument().insertString(document.getLength(), builderData.toString(),
dataView.getStyle(style));
else
dataView.getDocument().insertString(document.getLength(), builderData.toString(),
dataView.getStyle(STYLE_NORMAL));
dataView.setCaretPosition(document.getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
}




/**
* 发送指定数据

*/
private void sendData(String data) {
try {
SerialPortManager.sendToPort(serialport, MyUtils.HexString2Bytes(data));
dataShow(data,STYLE_RED);
} catch (SendDataToSerialPortFailure e) {
e.printStackTrace();
} catch (SerialPortOutputStreamCloseFailure e) {
e.printStackTrace();

}


private class SerialListener implements SerialPortEventListener {
/**
* 处理监控到的串口事件
*/
public void serialEvent(SerialPortEvent serialPortEvent) {


switch (serialPortEvent.getEventType()) {


case SerialPortEvent.BI: // 10 通讯中断
DialogShowUtils.errorMessage("与串口设备通讯中断");
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 串口存在可用数据
byte[] data = null;
try {
if (serialport == null) {
DialogShowUtils.errorMessage("串口对象为空!监听失败!");
} else {
// 读取串口数据
data = SerialPortManager.readFromPort(serialport);
dataShow(MyUtils.byteArray2HexString(data, data.length, true), STYLE_NORMAL);
}
} catch (Exception e) {
DialogShowUtils.errorMessage(e.toString());
// 发生读取错误时显示错误信息后退出系统
System.exit(0);
}
break;
}
}
}


public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame().setVisible(true);
}
});
}


@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == serialPortOpenBtn) {
if (serialport == null) {
openSerialPort();
} else {
closeSerialPort();
}
} else if (e.getSource() == sendDataBtn) {
String data = dataInput.getText().toString();
if(MyUtils.isEmpty(data))
return;
sendData(data);
} else if (e.getSource() == openCmdButton) {
// 0x02 0x05 0x01 0xaa 0x03 --> "0x02 0x05 0x01 0x06 0x03"
String data = "020501aa03";
sendData(data);


} else if (e.getSource() == closeCmdButton) {
// 0x02 0x05 0x02 0xaa 0x03 --> "0x02 0x05 0x02 0x05 0x03"
String data = "020502aa03";
sendData(data);
}
}

}

 

这是一个串口管理类主要是读取电脑上的串口:

public class SerialPortManager {


/**
* 查找所有可用端口

* @return 可用端口名称列表
*/
@SuppressWarnings("unchecked")
public static final ArrayList<String> findPort() {
// 获得当前所有可用串口
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 串口对象
* @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();
}
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 读取到的数据 
*/  
public static byte[] readFromPort(SerialPort serialPort) {  
    InputStream in = null;  
    byte[] bytes = {};  
    try {  
        in = serialPort.getInputStream();  
        // 缓冲区大小为一个字节  
        byte[] readBuffer = new byte[1];  
        int bytesNum = in.read(readBuffer);  
        while (bytesNum > 0) {  
            bytes = MyUtils.concat(bytes, readBuffer);  
            bytesNum = in.read(readBuffer);  
        }  
    } catch (IOException e) {  
        new ReadDataFromSerialPortFailure().printStackTrace();  
    } finally { 
        try {  
            if (in != null) {  
                in.close();  
                in = null;  
            }  
        } catch (IOException e) {  
            new SerialPortInputStreamCloseFailure().printStackTrace();  
        }  
    }  
    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();
}
}
}

运行效果:

其项目结构:

项目下载地址:http://download.csdn.net/download/atgeretg/10121971

 

 

  • 20
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 40
    评论
### 回答1: 要实现Java实时读取串口数据并展示,可以使用Java串口通信库进行开发,例如RXTX或JSSC。首先,需要导入相关的库文件。 接下来,可以按照以下步骤进行开发: 1. 获取可用的串口列表。使用库提供的函数,获取当前计算机上可用的串口列表。 2. 打开指定的串口。根据需求选择要读取数据串口进行打开。 3. 配置串口参数。设置串口的波特率、数据位、停止位、校验位等参数。 4. 创建数据读取线程。创建一个线程,在该线程中不断循环读取串口上的数据。 5. 解析并展示数据。根据数据的格式,对接收到的数据进行解析,并在界面上展示。 6. 关闭串口。在程序退出或不需要再读取数据时,关闭串口。 代码示例: ```java import gnu.io.*; import java.io.IOException; import java.io.InputStream; public class SerialPortReader { private SerialPort serialPort; private InputStream inputStream; public void readSerialData() { try { // 获取可用的串口列表 String[] portNames = SerialPortList.getPortNames(); // 打开指定的串口 serialPort = (SerialPort) CommPortIdentifier.getPortIdentifier(portNames[0]).open("SerialPortReader", 2000); // 配置串口参数 serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // 获取输入流 inputStream = serialPort.getInputStream(); // 创建数据读取线程 Thread readerThread = new Thread(new SerialDataReader()); readerThread.start(); // 在界面上展示数据 } catch (PortInUseException | NoSuchPortException | UnsupportedCommOperationException | IOException e) { e.printStackTrace(); } } public void closeSerialPort() { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (serialPort != null) { serialPort.close(); } } private class SerialDataReader implements Runnable { public void run() { try { byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) > -1) { // 解析数据并在界面上展示 String data = new String(buffer, 0, len); System.out.println("Received data: " + data); } } catch (IOException e) { e.printStackTrace(); } finally { closeSerialPort(); } } } } ``` 以上代码是一个简单的示例,通过串口读取数据并在控制台输出。可以根据需要将数据展示在UI界面上,例如使用Swing、JavaFX或其他UI库进行开发。在`SerialDataReader`的`run`方法中,可以根据具体的数据格式进行解析,并将解析后的数据展示在界面上。 ### 回答2: 在Java中实时读取串口数据并展示可以使用Java串口通信库来实现,例如RXTXcomm库。以下是一个使用RXTXcomm库实现串口实时读取并展示的简单示例代码: 首先,需要导入RXTXcomm库的jar文件,并添加相关的依赖库。 ```java import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class SerialPortReader { private static final String PORT_NAME = "/dev/ttyUSB0"; // 串口设备名 private static final int BAUD_RATE = 9600; // 波特率 public static void main(String[] args) { // 获取可用的串口通信设备 CommPortIdentifier portIdentifier; try { portIdentifier = CommPortIdentifier.getPortIdentifier(PORT_NAME); // 打开串口 SerialPort serialPort = (SerialPort) portIdentifier.open("SerialPortReader", 2000); // 配置串口 serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // 获取输入流 InputStream in = serialPort.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // 实时读取串口数据并展示 while (true) { String data = reader.readLine(); // 读取串口数据 System.out.println("Received: " + data); // 展示读取数据 } } catch (Exception e) { e.printStackTrace(); } } } ``` 以上代码使用RXTXcomm库获取串口设备的标识符,并打开串口连接。然后通过配置串口参数,配置波特率、数据位、停止位和校验位等。接着,通过获取输入流,可以实时读取串口数据。这里使用BufferedReader来读取数据,在while循环中不断读取,并展示读取到的数据。 请注意,使用RXTXcomm库需要根据其不同的版本和操作系统做相应的配置和兼容性处理。 ### 回答3: 在Java中实时读取串口数并展示,可以借助Java串口通信库来完成。一种常用的库是RXTXComm库。下面是实现的基本步骤: 1. 首先,需要下载并安装RXTXComm库。可以在官方网站上下载对应操作系统的库文件,并按照官方提供的安装说明进行配置。 2. 在Java代码中导入RXTXComm库的相关类。例如,导入SerialPort、SerialPortEventListener等类。 3. 在代码中创建一个SerialPort对象,通过该对象与串口进行通讯。使用SerialPort类的getPortIdentifiers()方法获取可用的串口列表。可以通过遍历该列表来获取需要的串口。 4. 在SerialPort对象上注册一个SerialPortEventListener监听器,以便实时读取串口数据。实现SerialPortEventListener接口中的serialEvent()方法来处理串口事件。 5. 在serialEvent()方法中,可以通过SerialPort对象的getInputStream()方法获取到串口的输入流。通过读取输入流中的数据,可以实现实时读取串口数据。可以根据需要进行处理后再展示。 6. 根据读取到的串口数据,可以展示在用户界面上,比如在控制台打印输出,或者在图形用户界面上显示。 需要注意的是,由于Java本身对于串口通信的支持较弱,所以在使用串口相关库时,需要进行相应的配置和处理,以确保与串口设备的正常通讯。
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值