java串口编程-读取称重仪表中净重

一、需求说明

        将仪表和计算机串口相连,计算机通过软件向仪表发送指令,然后仪表返回结果,在计算机软件界面上显示。

 

二、实现过程

1、查看仪表说明书

        仪表型号为XK3190-A9,主要是查看相关参数(波特率、数据位、停止位、奇偶校验),通讯方式及指令规则。

 

2、使用串口通讯工具、串口监听工具进行调试

        网上可以下到很多相关软件,主要是方便测试。串口通讯工具、串口监听工具(AccessPort)

 

3、将仪表“通讯方式”改成“指令模式”

        根据说明书,在仪表上输入:打印设置--->98--->输入--->....

 

4、java编码(重点)

(1)使用comm在java程序中管理本地端口,目前,常见的Java串口包有SUN在1998年发布的串口通信API:comm2.0.jar(Windows下)、comm3.0.jar(Linux/Solaris);IBM的串口通信API以及一个开源的实现。鉴于在Windows下SUN的API比较常用以及IBM的实现和SUN的在API层面都是一样的,那个开源的实现又不像两家大厂的产品那样让人放心,这里就只介绍SUN的串口通信API在Windows平台下的使用。

(2)附件中“javacomm20-win32.zip”


java串口编程-读取称重仪表中净重_第1张图片
 

(3)解压该压缩包,从commapi\Readme.html开始读起

(4)Copy win32com.dll to your <JDK>\bin directory.
(5)Copy comm.jar、javax.comm.properties to your <APP>\lib directory.

(6)研究java.comm包中的相关类及功能


java串口编程-读取称重仪表中净重_第2张图片
----javax.comm.CommPortIdentifier 这个类主要用于对串口进行管理和设置,是对串口进行访问控制的核心类。

 

----javax.comm.SerialPort 这个类用于描述一个RS-232串行通信端口的底层接口,它定义了串口通信所需的最小功能集。通过它,用户可以直接对串口进行读、写及设置工作。 

 

 

(7)开始编写自己的代码

 

##### 串口参数配置(配置到spring容器里) #####

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
	<bean class="self.phoenix.application.SerialParameters">
		<!-- 端口名称 -->
		<property name="portName"><value>COM1</value></property>
		<!-- 波特率 -->
		<property name="baudRate"><value>4800</value></property>
		<!-- 输入流控制 -->
		<property name="flowControlIn"><value>0</value></property>
		<!-- 输出流控制 -->
		<property name="flowControlOut"><value>0</value></property>
		<!-- 数据位 -->
		<property name="databits"><value>8</value></property>
		<!-- 停止位 -->
		<property name="stopbits"><value>1</value></property>
		<!-- 奇偶校验 -->
		<property name="parity"><value>0</value></property>
	</bean>
</beans>

 

#####用于处理注册驱动、打开端口、发送指令、关闭端口及释放资源#####

 

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.comm.CommDriver;
import javax.comm.CommPortIdentifier;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.UnsupportedCommOperationException;

import self.phoenix.application.SerialConnectionException;
import self.phoenix.application.SerialParameters;

public class SerialConnUtils {
	
	private OutputStream os= null;
    private InputStream is = null;
    private CommPortIdentifier portId = null;
	private SerialPort sPort = null;
	private SerialParameters parameters = null;
	private CommDriver commDriver = null;
	
	public SerialConnUtils(SerialParameters parameters) {
		this.parameters = parameters;
		if(commDriver == null){
			try {
				commDriver = (CommDriver) Class.forName("com.sun.comm.Win32Driver").newInstance();
				commDriver.initialize();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void openConnection() throws SerialConnectionException {
		// Obtain a CommPortIdentifier object for the port you want to open.
		try {
		    portId = CommPortIdentifier.getPortIdentifier(parameters.getPortName());
		} catch (NoSuchPortException e) {
		    throw new SerialConnectionException(e.getMessage());
		}
		
		// Open the port represented by the CommPortIdentifier object. Give
		// the open call a relatively long timeout of 30 seconds to allow
		// a different application to reliquish the port if the user 
		// wants to.
		try {
		    sPort = (SerialPort)portId.open("SerialDemo", 30000);
		} catch (PortInUseException e) {
		    throw new SerialConnectionException(e.getMessage());
		}
		
		try {
		    setConnectionParameters();
		} catch (SerialConnectionException e) {	
		    sPort.close();
		    throw e;
		}
		
		// Set receive timeout to allow breaking out of polling loop during
		// input handling.
		/*try {
		    sPort.enableReceiveTimeout(30);
		} catch (UnsupportedCommOperationException e) {
		}*/
	}
	
	public void setConnectionParameters() throws SerialConnectionException {

		// Save state of parameters before trying a set.
		int oldBaudRate = sPort.getBaudRate();
		int oldDatabits = sPort.getDataBits();
		int oldStopbits = sPort.getStopBits();
		int oldParity = sPort.getParity();
		int oldFlowControl = sPort.getFlowControlMode();

		// Set connection parameters, if set fails return parameters object
		// to original state.
		try {
			sPort.setSerialPortParams(parameters.getBaudRate(),
					parameters.getDatabits(), parameters.getStopbits(),
					parameters.getParity());
		} catch (UnsupportedCommOperationException e) {
			parameters.setBaudRate(oldBaudRate);
			parameters.setDatabits(oldDatabits);
			parameters.setStopbits(oldStopbits);
			parameters.setParity(oldParity);
			throw new SerialConnectionException("Unsupported parameter");
		}

		// Set flow control.
		try {
			sPort.setFlowControlMode(parameters.getFlowControlIn()
					| parameters.getFlowControlOut());
		} catch (UnsupportedCommOperationException e) {
			throw new SerialConnectionException("Unsupported flow control");
		}
	}
	
	/**
	 * 向端口发送十六进制指令 02 41 44 30 35 03
	 * 返回:02 41 44 2B 30 30 30 35 36 36 31 31 41 03
	 * @return 净重
	 * @throws SerialConnectionException
	 */
	public double sendSerialCommand() throws SerialConnectionException {

		//十六进制指令
		byte[] baKeyword = new byte[6];
		baKeyword[0] = 0x02;
		baKeyword[1] = 0x41;
		baKeyword[2] = 0x44;
		baKeyword[3] = 0x30;
		baKeyword[4] = 0x35;
		baKeyword[5] = 0x03;
		
		//净重
		Double netWeight = 0.0;

		try {
			//向串口发送指令
			os = sPort.getOutputStream();
			os.write(baKeyword, 0, baKeyword.length);
			
			//用于从串口读数据,返回14字节的信息
    		byte[] readBuffer = new byte[14]; 
    		int numBytes = 0; 
    		is = sPort.getInputStream();
    		
    		numBytes = is.read(readBuffer);
    		
    		System.out.println(new String(readBuffer));
    		
    		//4~12为数据内容
    		String value = Hex2StringUtils.byte2HexStrByi(readBuffer,4,12);
			if (value != null && !value.trim().equals(""))
				netWeight = Double.valueOf(value) / 1000;
    		
		} catch (IOException e) {
			e.printStackTrace();
		}
		return netWeight;
	}

	public void closeConnection() {
		// Check to make sure sPort has reference to avoid a NPE.
		if (sPort != null) {
			try {
				// close the i/o streams.
				os.close();
				is.close();
			} catch (IOException e) {
				System.err.println(e);
			}

			// Close the port.
			sPort.close();
			
			//Release resources
			portId = null;
		}
	}
}

 

 ###### ACSII与16进制转换的Utils类 #####

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Hex2StringUtils {

	public static void main(String[] args) throws IOException {

	}

	/*
	 * 16进制数字字符集
	 */
	private static String hexString = "0123456789ABCDEF";

	/*
	 * 将字符串编码成16进制数字,适用于所有字符(包括中文)
	 */
	public static String encode(String str) {
		// 根据默认编码获取字节数组
		byte[] bytes = str.getBytes();
		StringBuilder sb = new StringBuilder(bytes.length * 2);
		// 将字节数组中每个字节拆解成2位16进制整数
		for (int i = 0; i < bytes.length; i++) {
			sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
			sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
		}
		return sb.toString();
	}

	/*
	 * 将16进制数字解码成字符串,适用于所有字符(包括中文)
	 */
	public static String decode(String bytes) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream(
				bytes.length() / 2);
		// 将每2位16进制整数组装成一个字节
		for (int i = 0; i < bytes.length(); i += 2)
			baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString
					.indexOf(bytes.charAt(i + 1))));
		return new String(baos.toByteArray());
	}

	public static String byte2HexStr(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = (Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
			// if (n<b.length-1) hs=hs+":";
		}
		return hs.toUpperCase();
	}

	public static String byteHexStr(byte b) {
		String hs = "";
		String stmp = "";
		// /for (int n = 0; n < b.length; n++) {
		stmp = (Integer.toHexString(b & 0XFF));
		if (stmp.length() == 1)
			hs = "0" + stmp;
		else
			hs = stmp;
		// if (n<b.length-1) hs=hs+":";
		// }
		return hs.toUpperCase();
	}

	public static String byte2HexStrByi(byte[] b, int start, int end) {
		String hs = "";
		String stmp = "";
		for (int n = start; n < end; n++) {
			stmp = (Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + decode("0" + stmp);
			else
				hs = hs + decode(stmp);
			// if (n<b.length-1) hs=hs+":";
		}
		return hs.toUpperCase();
	}
}

 

##### 调用函数,取得净重值 #####

public double getSerialPortNetWeight() {
		double netWeight = 0;
		SerialConnUtils serialConnUtils = null;
		try {
			//调用串口通讯工具类
			serialConnUtils = new SerialConnUtils(parameters);
			//打开连接
			serialConnUtils.openConnection();
			//发送指令,并取得返回值
			netWeight = serialConnUtils.sendSerialCommand();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			//释放资源
			serialConnUtils.closeConnection();
		}
		return netWeight;
	}

 

 

5、在串口监听工具配合下进行软件调试

 

129     [00000000]  IRP_MJ_CREATE                   Port Opened - javaw.exe
130     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
131     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
132     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
133     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
134     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
135     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
136     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
137     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
138     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
139     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
140     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
141     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
142     [00000000]  IRP_MJ_WRITE                    Length: 0006, Data: 02 41 44 30 35 03 
143     [00000013]  IRP_MJ_READ                     Length: 0014, Data: 02 41 44 2B 30 30 30 35 36 36 31 31 41 03 
144     [00001356]  IRP_MJ_CLOSE                    Port Closed
145     [00000000]  IRP_MJ_CREATE                   Port Opened - javaw.exe
146     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
147     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
148     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
149     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
150     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
151     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
152     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
153     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
154     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
155     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
156     [00000000]  IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 4800
157     [00000000]  IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
158     [00000000]  IRP_MJ_WRITE                    Length: 0006, Data: 02 41 44 30 35 03 
159     [00000013]  IRP_MJ_READ                     Length: 0014, Data: 02 41 44 2B 30 30 30 36 39 36 31 31 36 03 
160     [00000349]  IRP_MJ_CLOSE                    Port Closed

 

Length:0006,      Data:02 41 44 30 35 03    为发送的十六进制指令

Length:0014,      Data:02 41 44 2B 30 30 30 36 39 36 31 31 36 03 为返回的十六进制内容

 

三、总结:调试过程中,串口监听工具起着很重要的作用。

你可能感兴趣的:(java串口编程-读取称重仪表中净重)