GitHub源码:https://github.com/Phoenixsmf/AIS
java实现串口通信:
基于java语言实现 对AIS接收机的数据解析,java代码:
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; /** * 串口管理 * * @author SMF */ @SuppressWarnings("all") public class SerialPortManager {	/**	* 查找所有可用端口	*	* @return 可用端口名称列表	*/	public static final ArrayListfindPorts() {	// 获得当前所有可用串口	EnumerationportList = CommPortIdentifier.getPortIdentifiers();	ArrayListportNameList = new ArrayList();	// 将可用串口名添加到List并返回该List	while (portList.hasMoreElements()) {	String portName = portList.nextElement().getName();	portNameList.add(portName);	}	return portNameList;	}	/**	* 打开串口	*	* @param portName	* 端口名称	* @param baudrate	* 波特率	* @return 串口对象	* @throws PortInUseException	* 串口已被占用	*/	public static final SerialPort openPort(String portName, int baudrate) throws PortInUseException {	try {	// 通过端口名识别端口	CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);	// 打开端口,并给端口名字和一个timeout(打开操作的超时时间)	CommPort commPort = portIdentifier.open(portName, 2000);	// 判断是不是串口	if (commPort instanceof SerialPort) {	SerialPort serialPort = (SerialPort) commPort;	try {	// 设置一下串口的波特率等参数	// 数据位:8	// 停止位: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();	}	return null;	}	/**	* 关闭串口	*	* @param serialport	* 待关闭的串口对象	*/	public static void closePort(SerialPort serialPort) {	if (serialPort != null) {	serialPort.close();	}	}	/**	* 往串口发送数据	*	* @param serialPort	* 串口对象	* @param order	* 待发送数据	*/	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();	}	}	}	/**	* 从串口读取数据	*	* @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 = 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;	}	/**	* 添加监听器	*	* @param port	* 串口对象	* @param listener	* 串口存在有效数据监听	*/	public static void addListener(SerialPort serialPort, DataAvailableListener listener) {	try {	// 给串口添加监听器	serialPort.addEventListener(new SerialPortListener(listener));	// 设置当有数据到达时唤醒监听接收线程	serialPort.notifyOnDataAvailable(true);	// 设置当通信中断时唤醒中断线程	serialPort.notifyOnBreakInterrupt(true);	} catch (TooManyListenersException e) {	e.printStackTrace();	}	}	/**	* 串口监听	*/	public static class SerialPortListener implements SerialPortEventListener {	private DataAvailableListener mDataAvailableListener;	public SerialPortListener(DataAvailableListener mDataAvailableListener) {	this.mDataAvailableListener = mDataAvailableListener;	}	public void serialEvent(SerialPortEvent serialPortEvent) {	switch (serialPortEvent.getEventType()) {	case SerialPortEvent.DATA_AVAILABLE: // 1.串口存在有效数据	if (mDataAvailableListener != null) {	mDataAvailableListener.dataAvailable();	}	break;	case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空	break;	case SerialPortEvent.CTS: // 3.清除待发送数据	break;	case SerialPortEvent.DSR: // 4.待发送数据准备好了	break;	case SerialPortEvent.RI: // 5.振铃指示	break;	case SerialPortEvent.CD: // 6.载波检测	break;	case SerialPortEvent.OE: // 7.溢位(溢出)错误	break;	case SerialPortEvent.PE: // 8.奇偶校验错误	break;	case SerialPortEvent.FE: // 9.帧错误	break;	case SerialPortEvent.BI: // 10.通讯中断	ShowUtils.errorMessage("与串口设备通讯中断");	break;	default:	break;	}	}	}	/**	* 串口存在有效数据监听	*/	public interface DataAvailableListener {	/**	* 串口存在有效数据	*/	void dataAvailable();	} }
界面 代码:
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.nms.ais.AIS_Analyse; import com.yang.serialport.manager.SerialPortManager; import com.yang.serialport.utils.ByteUtils; import com.yang.serialport.utils.ShowUtils; import com.yang.serialport.utils.SqlSessionFactoryInit; import gnu.io.PortInUseException; import gnu.io.SerialPort; /** * 主界面 * * @author SMF */ @SuppressWarnings("all") public class MainFrame extends JFrame {	// 程序界面宽度	public final int WIDTH = 1000;	// 程序界面高度	public final int HEIGHT = 390;	// 数据显示区	private JTextArea mDataView = new JTextArea();	private JScrollPane mScrollDataView = new JScrollPane(mDataView);	//有效数据显示区域	public static JTextArea mDataValiableView = new JTextArea();	public static JScrollPane mScrollDataViewValiable = new JScrollPane(mDataValiableView);	// 串口设置面板	private JPanel mSerialPortPanel = new JPanel();	private JLabel mSerialPortLabel = new JLabel("串口");	private JLabel mBaudrateLabel = new JLabel("波特率");	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("打开串口");	private JButton mSendData = new JButton("发送数据");	// 串口列表	private ListmCommList = null;	// 串口对象	private SerialPort mSerialport;	public MainFrame() {	try{	SqlSessionFactoryInit.creatSqlSessionFactory();	initView();	initComponents();	actionListener();	initData();	}catch(Exception e){	e.printStackTrace();	}	}	/**	* 初始化窗口	*/	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, WIDTH, HEIGHT);	this.setLayout(null);	setTitle("串口通信");	}	/**	* 初始化控件	*/	private void initComponents() {	// 数据显示	mDataView.setFocusable(false);	mScrollDataView.setBounds(10, 10, 505, 200);	add(mScrollDataView);	// 数据显示	mDataValiableView.setFocusable(false);	mScrollDataViewValiable.setBounds(520, 10, 400, 200);	add(mScrollDataViewValiable);	// 串口设置	mSerialPortPanel.setBorder(BorderFactory.createTitledBorder("串口设置"));	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);	// 操作	mOperatePanel.setBorder(BorderFactory.createTitledBorder("操作"));	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);	}	/**	* 初始化数据	*/	private void initData() {	mCommList = SerialPortManager.findPorts();	// 检查是否有可用串口,有则加入选项中	if (mCommList == null || mCommList.size()