1. Write in front

From an article on the serial communication using Java implementation has been almost two years, during which received a lot of readers’ feedback, is happy to help so many people, according to the feedback received, I to code logic is optimized, and adds some new features, in this record, share with you.

First look at the effect:

2. Environment construction

The development of serial communication in this article is based on RXTX, so some RXTX dependencies need to be referenced:

RXTX dependency package download address, including 32-bit and 64-bit versions

  • Copy rxtxcomm. jar to JAVA_HOME\jre\lib\ext;

  • Copy rxtxserial. DLL to JAVA_HOME\jre\bin;

  • Copy rxtxParallel. DLL to JAVA_HOME\jre\bin;

JAVA_HOME indicates the JDK installation directory

Please check whether the dependency package is copied to the correct path. After JDK installation, two JRE directories will be generated, so you need to copy them to JDK > JRE directory.

3. Serial port communication management

SerialPortManager implements the management of the serial port communication, including search available ports, serial ports, sending | receiving data on | off.

package com.yang.serialport.manager; 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 com.yang.serialport.utils.ArrayUtils; import com.yang.serialport.utils.ShowUtils; 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; /** * serial control ** @author yangle */ @suppresswarnings ()"all") public class SerialPortManager {/** * find all available ports ** @returnPublic static final ArrayList<String>findPorts() {/ / get the current all available serial port Enumeration < CommPortIdentifier > portList. = CommPortIdentifier getPortIdentifiers (); ArrayList<String> portNameList = new ArrayList<String>(); // Add the available serial port names to the List and return the Listwhile (portList.hasMoreElements()) {
			String portName = portList.nextElement().getName();
			portNameList.add(portName);
		}
		returnportNameList; } /** * open the serial port ** @param portName * portName * @param baudrate * baudrate * @returnSerialPort object * @throws PortInUseException * the SerialPort is occupied */ public static final SerialPort openPort(String portName, Int baudrate) throws PortInUseException {try {// Identify ports by port name CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); CommPort CommPort = portIdentifier. Open (portName, 2000); // open the port and give the portName and a timeout (timeout for opening the operation). // Check whether it is a serial portif(commPort instanceof SerialPort) { SerialPort serialPort = (SerialPort) commPort; Try {// Set the baud rate for the serial port // Data bit: 8 // Stop bit: 1 // Parity bit: 1 None serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { e.printStackTrace(); }return serialPort;
			}
		} catch (NoSuchPortException e1) {
			e1.printStackTrace();
		}
		returnnull; } /** * close the serialport ** @param serialport */ public static void closePort(serialport serialport) {if(serialPort ! = null) { serialPort.close(); }} /** * send data to the serialPort ** @param serialPort * @param order * to send data */ public static void sendToPort(serialPort) serialPort, byte[] order) { OutputStream out = null; try { out = serialPort.getOutputStream(); out.write(order); out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try {if(out ! = null) { out.close(); out = null; } } catch (IOException e) { e.printStackTrace(); }}} /** * read data from the serialPort ** @param serialPort ** the currently connected serialPort object * @return*/ public static byte[]readFromPort(SerialPort serialPort) {
		InputStream in = null;
		byte[] bytes = {};
		try {
			in= serialPort.getInputStream(); // The buffer size is one byte byte[]readBuffer = new byte[1];
			int bytesNum = in.read(readBuffer);
			while (bytesNum > 0) {
				bytes = ArrayUtils.concat(bytes, readBuffer);
				bytesNum = in.read(readBuffer);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (in! = null) { in.close();in= null; } } catch (IOException e) { e.printStackTrace(); }}returnbytes; } /** * add a listener ** @param port * SerialPort object * @param listener * valid data is listening to the SerialPort */ public static void addListener(SerialPort) serialPort, DataAvailableListener listener) {try {/ / add listeners to a serial port. SerialPort addEventListener (new SerialPortListener (the listener)); / / set the wake listening when data arrives at receiving threads serialPort. NotifyOnDataAvailable (true); / / set when wake interrupt communication interrupt thread serialPort. NotifyOnBreakInterrupt (true); } catch (TooManyListenersException e) { e.printStackTrace(); }} /** * Serial listener */ public static class SerialPortListener implements SerialPortEventListener {private DataAvailableListener mDataAvailableListener; public SerialPortListener(DataAvailableListener mDataAvailableListener) { this.mDataAvailableListener = mDataAvailableListener; } public void serialEvent(SerialPortEvent serialPortEvent) { switch (serialPortEvent.getEventType()) {caseSerialPortEvent.DATA_AVAILABLE: // 1. The serial port has valid dataif(mDataAvailableListener ! = null) { mDataAvailableListener.dataAvailable(); }break;

			caseSerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2. The output buffer has been clearedbreak;

			caseSerialportevent. CTS: // 3. Clear the data to be sentbreak;

			caseSerialportevent. DSR: // 4. The data to be sent is readybreak;

			caseSerialportevent. RI: // 5. Ring indicationbreak;

			caseSerialportevent. CD: // 6. Carrier detectionbreak;

			caseSerialportevent.oe: // 7. Overflow errorbreak;

			caseSerialportevent. PE: // 8. Parity check is incorrectbreak;

			caseSerialportevent. FE: // 9. Frame errorbreak;

			caseSerialportevent. BI: // 10."Communication with serial device interrupted");
				break;

			default:
				break; Public DataAvailableListener {/** * public DataAvailableListener {/** * public DataAvailableListener {/ void dataAvailable(); }}Copy the code

The previous readFromPort method used the available method in the InputStream to determine whether there is data in the current buffer. The available method returns the number of bytes that have not been blocked. This can result in incomplete data being received.

The modified readFromPort method uses the read method to determine whether there is any data in the current buffer, and then pieces the data together for display. In this method, I set the size of each read to 1 byte, which can be modified according to actual needs:

/** * read data from the serialPort ** @param serialPort * currently connected serialPort object * @return*/ public static byte[]readFromPort(SerialPort serialPort) {
	InputStream in = null;
	byte[] bytes = {};
	try {
		in= serialPort.getInputStream(); // The buffer size is one byte byte[]readBuffer = new byte[1];
		int bytesNum = in.read(readBuffer);
		while (bytesNum > 0) {
			bytes = ArrayUtils.concat(bytes, readBuffer);
			bytesNum = in.read(readBuffer);
		}
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		try {
			if (in! = null) { in.close();in= null; } } catch (IOException e) { e.printStackTrace(); }}return bytes;
}
Copy the code

4. Program main window

package com.yang.serialport.ui; import java.awt.Color; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import com.yang.serialport.manager.SerialPortManager; import com.yang.serialport.utils.ByteUtils; import com.yang.serialport.utils.ShowUtils; import gnu.io.PortInUseException; import gnu.io.SerialPort; /** * main interface ** @author yangle */ @suppresswarnings ("all"Public final int frame extends JFrame; public final int frame extends JFrame; Public final int HEIGHT = 390; Private JTextArea mDataView = new JTextArea(); private JScrollPane mScrollDataView = new JScrollPane(mDataView); Private JPanel mSerialPortPanel = new JPanel(); private JLabel mSerialPortLabel = new JLabel("Serial");
	private JLabel mBaudrateLabel = new JLabel("Baud rate");
	private JComboBox mCommChoice = new JComboBox();
	private JComboBox mBaudrateChoice = new JComboBox();
	private ButtonGroup mDataChoice = new ButtonGroup();
	private JRadioButton mDataASCIIChoice = new JRadioButton("ASCII".true);
	private JRadioButton mDataHexChoice = new JRadioButton("Hex"); Private JPanel mOperatePanel = new JPanel(); private JTextArea mDataInput = new JTextArea(); private JButton mSerialPortOperate = new JButton("Open serial port");
	private JButton mSendData = new JButton("Send data"); Private List<String> mCommList = null; // Private SerialPort mSerialport; publicMainFrame() { initView(); initComponents(); actionListener(); initData(); } /** * Initialize window */ private voidinitView() {// Close the programsetDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); // Disable window maximizationsetResizable(false); / / setup window centered Point p = GraphicsEnvironment. GetLocalGraphicsEnvironment () getCenterPoint ();setBounds(p.x - WIDTH / 2, p.y - HEIGHT / 2, WIDTH, HEIGHT);
		this.setLayout(null);

		setTitle("Serial communication"); } /** * Initializer */ private voidinitComponents() {// display mdataView.setfocusable ()false); mScrollDataView.setBounds(10, 10, 505, 200); add(mScrollDataView); / / serial port Settings mSerialPortPanel. SetBorder (BorderFactory. CreateTitledBorder ("Serial Port Settings"));
		mSerialPortPanel.setBounds(10, 220, 170, 130);
		mSerialPortPanel.setLayout(null);
		add(mSerialPortPanel);

		mSerialPortLabel.setForeground(Color.gray);
		mSerialPortLabel.setBounds(10, 25, 40, 20);
		mSerialPortPanel.add(mSerialPortLabel);

		mCommChoice.setFocusable(false);
		mCommChoice.setBounds(60, 25, 100, 20);
		mSerialPortPanel.add(mCommChoice);

		mBaudrateLabel.setForeground(Color.gray);
		mBaudrateLabel.setBounds(10, 60, 40, 20);
		mSerialPortPanel.add(mBaudrateLabel);

		mBaudrateChoice.setFocusable(false); mBaudrateChoice.setBounds(60, 60, 100, 20); mSerialPortPanel.add(mBaudrateChoice); mDataASCIIChoice.setBounds(20, 95, 55, 20); mDataHexChoice.setBounds(95, 95, 55, 20); mDataChoice.add(mDataASCIIChoice); mDataChoice.add(mDataHexChoice); mSerialPortPanel.add(mDataASCIIChoice); mSerialPortPanel.add(mDataHexChoice); / / operation mOperatePanel. SetBorder (BorderFactory. CreateTitledBorder ("Operation"));
		mOperatePanel.setBounds(200, 220, 315, 130);
		mOperatePanel.setLayout(null);
		add(mOperatePanel);

		mDataInput.setBounds(25, 25, 265, 50);
		mDataInput.setLineWrap(true);
		mDataInput.setWrapStyleWord(true);
		mOperatePanel.add(mDataInput);

		mSerialPortOperate.setFocusable(false);
		mSerialPortOperate.setBounds(45, 95, 90, 20);
		mOperatePanel.add(mSerialPortOperate);

		mSendData.setFocusable(false); mSendData.setBounds(180, 95, 90, 20); mOperatePanel.add(mSendData); } /** * Initialize data */ private voidinitData() { mCommList = SerialPortManager.findPorts(); // Check whether a serial port is available. If yes, add it to the optionsif (mCommList == null || mCommList.size() < 1) {
			ShowUtils.warningMessage("No valid serial port found!");
		} else {
			for (String s : mCommList) {
				mCommChoice.addItem(s);
			}
		}

		mBaudrateChoice.addItem("9600");
		mBaudrateChoice.addItem("19200");
		mBaudrateChoice.addItem("38400");
		mBaudrateChoice.addItem("57600");
		mBaudrateChoice.addItem("115200"); } /** * Button listen for events */ private voidactionListener() {/ / serial mCommChoice. AddPopupMenuListener (newPopupMenuListener() { @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { mCommList = SerialPortManager.findPorts(); // Check whether a serial port is available. If yes, add it to the optionsif (mCommList == null || mCommList.size() < 1) {
					ShowUtils.warningMessage("No valid serial port found!");
				} else {
					int index = mCommChoice.getSelectedIndex();
					mCommChoice.removeAllItems();
					for(String s : mCommList) { mCommChoice.addItem(s); } mCommChoice.setSelectedIndex(index); } } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { // NO OP } @Override public void popupMenuCanceled(PopupMenuEvent e) { // NO OP } }); / / on | off serial mSerialPortOperate. AddActionListener (newActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if ("Open serial port".equals(mSerialPortOperate.getText()) && mSerialport == null) {
					openSerialPort(e);
				} else{ closeSerialPort(e); }}}); / / send data mSendData. AddActionListener (newActionListener() { @Override public void actionPerformed(ActionEvent e) { sendData(e); }}); } / opens a serial port of * * * * * @ * param evt * click events/private void openSerialPort (Java. The awt. Event. An ActionEvent evt) {/ / for a serial port name String commName = (String) mCommChoice.getSelectedItem(); Int baudrate = 9600; int baudrate = 9600; String bps = (String) mBaudrateChoice.getSelectedItem(); baudrate = Integer.parseInt(bps); // Check whether the serial port name is correctif (commName == null || commName.equals("")) {
			ShowUtils.warningMessage("No valid serial port found!");
		} else {
			try {
				mSerialport = SerialPortManager.openPort(commName, baudrate);
				if(mSerialport ! = null) { mDataView.setText("Serial port open" + "\r\n");
					mSerialPortOperate.setText("Close serial port");
				}
			} catch (PortInUseException e) {
				ShowUtils.warningMessage("The serial port is occupied!"); }} / / add a serial port to monitor SerialPortManager. AddListener (mSerialport, new SerialPortManager.DataAvailableListener() {

			@Override
			public void dataAvailable() {
				byte[] data = null;
				try {
					if (mSerialport == null) {
						ShowUtils.errorMessage("Serial port object is empty, listening failed!");
					} else{/ / read serial data data = SerialPortManager. ReadFromPort (mSerialport); // Receive the data as a stringif (mDataASCIIChoice.isSelected()) {
							mDataView.append(new String(data) + "\r\n"); } // Receive data in hexadecimal formatif (mDataHexChoice.isSelected()) {
							mDataView.append(ByteUtils.byteArrayToHexString(data) + "\r\n"); } } } catch (Exception e) { ShowUtils.errorMessage(e.toString()); // When a reading error occurs, the System displays an error message and exits system.exit (0); }}}); } / close a serial port of * * * * * @ * param evt * click events/private void closeSerialPort (Java. The awt. Event. An ActionEvent evt) { SerialPortManager.closePort(mSerialport); mDataView.setText("Serial port closed" + "\r\n");
		mSerialPortOperate.setText("Open serial port"); mSerialport = null; Send data} / * * * * * @ param evt * * click events/private void sendData publishes the event (Java. The awt. Event. An ActionEvent evt) {/ / sent data String data = mDataInput.getText().toString();if (mSerialport == null) {
			ShowUtils.warningMessage("Please open the serial port first!");
			return;
		}

		if ("".equals(data) || data == null) {
			ShowUtils.warningMessage("Please enter the data to send!");
			return; } // Send the data as a stringif(mDataASCIIChoice.isSelected()) { SerialPortManager.sendToPort(mSerialport, data.getBytes()); } // Send data in hexadecimal formatif (mDataHexChoice.isSelected()) {
			SerialPortManager.sendToPort(mSerialport, ByteUtils.hexStr2Byte(data));
		}
	}

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

Added data format (send, receive), ASCII (normal string) or Hex (hexadecimal), this is the most feedback problem.

When choosing to send and receive data in hexadecimal format, added support for odd digit data, such as 1, will be automatically completed to send 01.

5. FatJar packaging

Packaging encountered problems, and serial communication has nothing to do, some students may encounter the same problem, here to say, the new installation of an Eclipse 4.7.3 version, found that the local installation FatJar has not been installed, online check said FatJar does not support Eclipse 3.4 after the version, You can install it in the following ways:

Help -> Install New Software, In The “Work with” options in The Eclipse Project Updates – http://download.eclipse.org/eclipse/updates/4.7, Select Eclipse 2.0 Style Plugin Support under Eclipse Tests, Tools, Examples, and Extras and restart Eclipse.

When the restart is complete, open Help -> Install New Software again, enter fatjat – http://kurucz-grafika.de/fatjar in the “Work with” option, and select “FatJar” in the following option. The next step is to restart Eclipse and right-click on the project to see the Build Fat Jar option:

6. Write at the end

In this paper, the Demo download address: https://github.com/alidili/SerialPortDemo