最近看了JavaEye中一些有关使用RxTxComm.jar扩展包开发串口监听的代码,正好有个朋友让我做一个这方面的小软件,就把别人的代码整合了一下,做了一个小Demo。
项目结构其他的都是网上的代码,或我自己扩展的未完成的类:
软件可以接收串口传送的数据,显示在state标签后,并将数据返回给发送端。只是在本本上测试通过了,没有在真正的串口设备上测试。
使用了一个串口模拟的软件,模拟了一对串口设备com1,和com2,
使用串口调试助手发送模拟数据。
界面布局使用了GridBagLayout,相关代码在前一篇的博客中。
好了,贴代码了:
package gui; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; 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.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; import javax.swing.DefaultComboBoxModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; public class SerialPortMoniterPanel extends JPanel implements SerialPortEventListener{ static final String STATE = "STATE: "; static final String COUNT = "COUNT: "; static final String ERROR = "ERROR, PLEASE RETRY !"; static int count = 0; JPanel panel; JLabel commLabel; //端口号 JComboBox commComboBox; JLabel BPSLabel; //波特率 JComboBox BPSComboBox; //BPS JLabel flowInLabel; //Flow Control In 输入流控制 JComboBox flowInBox; JLabel flowOutLabel; //Flow Control Out 输出流控制 JComboBox flowOutBox; JLabel dataBitsLabel; //Data Bits 数据位数 JComboBox dataBitsBox; JLabel stopBitsLabel; //Stop Bits 停止位 JComboBox stopBitsBox; JLabel parityLabel; //Parity 奇偶校验 JComboBox parityBox; JLabel logoLabel; JLabel stateLabel; JLabel countLabel; JButton connButton; static CommPortIdentifier portId; static Enumeration portList; InputStream inputStream; //由串口读入的流 OutputStream outputStream;// 向串口输出的流 SerialPort serialPort; ConnectAction action; Thread buttonThread; public SerialPortMoniterPanel(){ super(new BorderLayout()); initPanel(); add(panel,BorderLayout.CENTER); } public void initPanel(){ GridBagLayout layout = new GridBagLayout(); panel = new JPanel(layout); connButton = new JButton("CONNECTION"); action = new ConnectAction(); connButton.addActionListener(action); stateLabel = new JLabel(STATE); stateLabel.setHorizontalAlignment(JLabel.LEFT); countLabel = new JLabel(COUNT+String.valueOf(count)); countLabel.setHorizontalAlignment(JLabel.LEFT); logoLabel = new JLabel(); Image image = Toolkit.getDefaultToolkit().getImage("logo/logo.png"); Icon icon = new ImageIcon(image); logoLabel.setIcon(icon); commLabel = new JLabel("Port Name"); commComboBox = new JComboBox(getCOMArray().toArray()); BPSLabel = new JLabel("Baud Rate"); Object[] bpsArray = {300,600,1200,2400,4800,9600, 19200,38400,43000,56000, 57600, 115200 }; DefaultComboBoxModel model = new DefaultComboBoxModel(bpsArray); BPSComboBox = new JComboBox(model); flowInLabel = new JLabel("Flow Control In"); flowInBox = new JComboBox(); flowOutLabel = new JLabel("Flow Control Out"); flowOutBox = new JComboBox(); dataBitsLabel = new JLabel("Data Bits"); Object[] dataBitsArray = {8,7,6}; dataBitsBox = new JComboBox(dataBitsArray); stopBitsLabel = new JLabel("Stop Bits"); Object[] stopBitsArray = {1,2}; stopBitsBox = new JComboBox(stopBitsArray); parityLabel = new JLabel("Parity"); Object[] parityArray = {"NONE", "ODD", "EVEN"}; parityBox = new JComboBox(parityArray); GridBagHelper.addComponent(panel, stateLabel, 0, 1, 2, 1, 2, 0, 0.0, 0.0, GridBagConstraints.NONE, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, countLabel, 0, 2, 2, 1, 2, 0, 0.0, 0.0, GridBagConstraints.NONE, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, commLabel, 0, 4, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, commComboBox, 1, 4, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, BPSLabel, 2, 4, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, BPSComboBox, 3, 4, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, flowInLabel, 0, 5, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, flowInBox, 1, 5, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, flowOutLabel, 2, 5, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, flowOutBox, 3, 5, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, dataBitsLabel, 0, 6, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, dataBitsBox, 1, 6, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, stopBitsLabel, 2, 6, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, stopBitsBox, 3, 6, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, parityLabel, 0, 7, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, parityBox, 1, 7, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, logoLabel, 4, 4, 1, 4, 1, 0, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.EAST); GridBagHelper.addComponent(panel, connButton, 4, 8, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.BOTH, GridBagConstraints.WEST); } public static ArrayList<String> getCOMArray(){ ArrayList<String> comList = new ArrayList<String>(); portList = CommPortIdentifier.getPortIdentifiers(); //System.out.println(portList.toString()); while (portList.hasMoreElements()) { portId = (CommPortIdentifier) portList.nextElement(); //System.out.println(portId.getName()); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { comList.add(portId.getName()); } } return comList; } @Override public void serialEvent(SerialPortEvent event) { // TODO Auto-generated method stub switch (event.getEventType()) { case SerialPortEvent.BI: case SerialPortEvent.OE: case SerialPortEvent.FE: case SerialPortEvent.PE: case SerialPortEvent.CD: case SerialPortEvent.CTS: case SerialPortEvent.DSR: case SerialPortEvent.RI: case SerialPortEvent.OUTPUT_BUFFER_EMPTY: break; case SerialPortEvent.DATA_AVAILABLE: //声明一个20个字节的缓冲区。 byte[] readBuffer = new byte[20]; try { stateLabel.setText(STATE); int numBytes = 0; while (inputStream.available() > 0) { //将数据读入readBuffer中。 numBytes = inputStream.read(readBuffer); } stateLabel.setText(STATE+(new String(readBuffer)).trim()); System.out.println(new String(readBuffer).trim()); outputStream.write(readBuffer); //计数 count++; countLabel.setText(COUNT+String.valueOf(count)); } catch (IOException e) { System.out.println(e); } break; } } public void initConnect(){ try { serialPort = (SerialPort) portId.open("myapp", 2000);// 打开串口名字为myapp,延迟为2毫秒 } catch (PortInUseException e) { JOptionPane.showMessageDialog(null, ERROR); System.exit(0); } try { inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); } catch (IOException e) { JOptionPane.showMessageDialog(null, ERROR); System.exit(0); } try { serialPort.addEventListener(this); // 给当前串口天加一个监听器 } catch (TooManyListenersException e) { JOptionPane.showMessageDialog(null, ERROR); System.exit(0); } serialPort.notifyOnDataAvailable(true); // 当有数据时通知 try { int bps = Integer.parseInt(String.valueOf(BPSComboBox.getSelectedItem())); //System.out.println(bps); serialPort.setSerialPortParams(bps, SerialPort.DATABITS_8, // 设置串口读写参数 SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); //serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN|SerialPort.FLOWCONTROL_RTSCTS_OUT); } catch (UnsupportedCommOperationException e) { JOptionPane.showMessageDialog(null, ERROR); System.exit(0); } JOptionPane.showMessageDialog(null, "CONNECTION SUCCESS"); } //联接事件 class ConnectAction implements Runnable, ActionListener { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub if(null != buttonThread){ return; }else{ buttonThread = new Thread(this); buttonThread.start();//开启线程 } } @Override public void run() { // TODO Auto-generated method stub if(null != serialPort){ serialPort.close(); } String comString = String.valueOf(commComboBox.getSelectedItem()); try { portList = CommPortIdentifier.getPortIdentifiers(); // 得到当前连接上的端口 while (portList.hasMoreElements()) { portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {// 判断如果端口类型是串口 if (portId.getName().equals(comString)) { // 判断如果COM3端口已经启动就连接 initConnect(); } } } } catch (Exception e) { e.printStackTrace(); } buttonThread = null; } } }
对话框类:
package gui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Random; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class CurrentStatePanel extends JPanel{ static int LENGTH = 16; JPanel panel; JLabel nameLabel; JLabel countLabel; JLabel stateLabel; StatusMessage message ; StatusMessage oldMessage; ArrayList<Integer>countList; public CurrentStatePanel(StatusMessage message){ super(new BorderLayout()); countList = new ArrayList<Integer>(); for(int i=0; i<LENGTH; i++){ countList.add(0); } this.message = message; this.oldMessage = message; refreshPanel(message); } public void refreshPanel(StatusMessage message){ this.removeAll(); initPanel(message); } public void initPanel(StatusMessage message){ GridBagLayout layout = new GridBagLayout(); panel = new JPanel(layout); panel.setBorder(BorderFactory.createTitledBorder("Current Status")); Image image = Toolkit.getDefaultToolkit().getImage("logo/on.png"); Icon onIcon = new ImageIcon(image); image = Toolkit.getDefaultToolkit().getImage("logo/off.png"); Icon offIcon = new ImageIcon(image); if(message.statusList.size()==0){ for(int i=0; i<LENGTH; i++){ message.statusList.add((byte)1); } } for(int i=0; i<LENGTH; i++){ if(message.statusList.get(i) != oldMessage.statusList.get(i)){ int temp = countList.get(i); countList.set(i, ++temp); //System.out.print(temp); } nameLabel = new JLabel(String.valueOf(i)); stateLabel = new JLabel(); stateLabel.setBorder(BorderFactory.createLoweredBevelBorder()); stateLabel.setIcon(message.statusList.get(i).byteValue()==1?onIcon:offIcon); countLabel = new JLabel(String.valueOf(countList.get(i))); GridBagHelper.addComponent(panel, nameLabel, i, 1, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.NONE, GridBagConstraints.CENTER); GridBagHelper.addComponent(panel, stateLabel, i, 2, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.NONE, GridBagConstraints.WEST); GridBagHelper.addComponent(panel, countLabel, i, 3, 1, 1, 1, 0, 0.0, 0.0, GridBagConstraints.NONE, GridBagConstraints.CENTER); } add(panel,BorderLayout.CENTER); panel.repaint(); panel.revalidate(); oldMessage = message; } public static void main(String[] args){ JFrame frame = new JFrame(); frame.setSize(new Dimension(300,300)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final StatusMessage message = new StatusMessage(); final CurrentStatePanel panel = new CurrentStatePanel(message); frame.add(panel); frame.setVisible(true); JButton button = new JButton("change"); button.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub StatusMessage message2 = new StatusMessage(); message2.statusList.clear(); for(int i=0; i<16; i++){ Random random = new Random(); message2.statusList.add((byte)(random.nextInt(2))); } panel.refreshPanel(message2); } }); frame.add(button,BorderLayout.NORTH); } }
本来还想写一些对ModBus的协议分析,处理得代码,但老板认为我不务正业,只能以后再私下研究了。