Java串口通信

来源:互联网 发布:护甲套淘宝 编辑:程序博客网 时间:2024/06/06 18:26

Java通信3.0 API是一个Java的扩展,有利于发展独立于平台的通信应用,如智能卡,嵌入式系统,销售点设备,金融服务设备,传真机,调制解调器,显示终端,以及机器人设备的技术。

  Java通信API(也被称为javax.comm)提供的应用程序访问到RS- 232硬件(串口)和有限的访问IEEE- 1284并行端口,SPP模式。

  Java提供了 CommunicationAPI(包含于javax.comm包中)用于通过与机器无关的方式,控制各种外部设备。Communications API,是标准的Java的扩展部分,它在JavaAPI中是没有附带的。  
  目前3.0可用于Sparc结构下的Solaris系统x86以及x86下的Linux系统的API的实现。 

  Windows版本只能用较老的版本了,完整的2.0版本地址:/data/attachment/portal/et2/201202/ET23102201202161358031.zip

成功下载解压后,目录下有3文件:

comm.jar:拷贝到%JAVA_HOME%\jre\lib\ext

javax.comm.properties:拷贝到%JAVA_HOME%\jre\lib\

win32com.dll:拷贝到%JAVA_HOME%\jre\lib\ext

注:%JAVA_HOME%jdk的路径

  Java的这个扩展类就不做详细介绍了,网上可以搜索到很多相关资料。下面我所做的是一个基于JAVA读取蓝牙GPS接收器中的数据。在我们下载的完整的2.0版本的API中的samples中提供了一些简单的实例,这里我采用了其中的SerialDemo,这个实例做了一个UI窗口,可以显示获取到的信息,设置各个参数,打开/关闭端口等功能。可以说这个实例将我所要做的大部分主要功能都已做好,我只需在这个实例的基础上来获得坐标位置并保存即可。

 

以下只截取部分主要代码:

1. 列举出本机所有可用串口

void listPortChoices() {
CommPortIdentifier portId;
Enumeration en = CommPortIdentifier.getPortIdentifiers();
// iterate through the ports.
while (en.hasMoreElements()) {
portId = (CommPortIdentifier) en.nextElement();
//如果端口的类型是串行口的话,将端口的名称添加到下拉框中。
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
portChoice.addItem(portId.getName());
}
}
//设置下拉框的选择项
portChoice.select(parameters.getPortName());
}


2. 打开连接

 

public void openConnection() throws SerialConnectionException {
//获取一个要打开的端口CommPortIdentifier对象。
try {
portId = CommPortIdentifier.getPortIdentifier(parameters.getPortName());
} catch (NoSuchPortException e) {
throw new SerialConnectionException(e.getMessage());
}
// 打开CommPortIdentifier对象代表端口。
//公开征集一个比较长的30秒超时,让不同的应用程序reliquish的端口,如果用户想要的。

try {
sPort = (SerialPort)portId.open("SerialDemo", 30000);
} catch (PortInUseException e) {
throw new SerialConnectionException(e.getMessage());
}

// Set the parameters of the connection. If they won't set, close the
// port before throwing an exception.
//设置连接参数。如果他们将不会设置,在抛出异常之前关闭该端口。
try {
setConnectionParameters();
} catch (SerialConnectionException e) {
sPort.close();
throw e;
}
//打开连接的输入和输出流。如果他们不打开,关闭端口抛出异常前。
try {
os = sPort.getOutputStream();
is = sPort.getInputStream();
} catch (IOException e) {
sPort.close();
throw new SerialConnectionException("Error opening i/o streams");
}
//创建一个新的KeyHandler响应messageAreaOut。添加KeyHandler keyListener messageAreaOut。
keyHandler = new KeyHandler(os);
messageAreaOut.addKeyListener(keyHandler);
//为串行端口添加一个事件侦听器。
try {
sPort.addEventListener(this);
} catch (TooManyListenersException e) {
sPort.close();
throw new SerialConnectionException("too many listeners added");
}
//notifyOnDataAvailable设置为true,允许事件驱动的输入。
sPort.notifyOnDataAvailable(true);
//设置notifyOnBreakInterrup允许事件驱动的中断处理。
sPort.notifyOnBreakInterrupt(true);
//设置接收超时,允许打破轮询循环在输入处理。
try {
sPort.enableReceiveTimeout(30);
} catch (UnsupportedCommOperationException e) {
}
//添加所有权监听器,让所有权的事件处理。
portId.addPortOwnershipListener(this);
open = true;
}


3. 事件侦听器监听到数据

   

 public void serialEvent(SerialPortEvent e) {
//创建一个StringBuffer和int接收输入数据。
StringBuffer inputBuffer = new StringBuffer();
int newData = http://www.cnblogs.com/southginger/archive/2011/12/07/0;
//确定事件的类型。
switch (e.getEventType()) {
//DATA_AVAILABLE端口缓冲区读取数据,直到返回-1。如果\r是代替\n收到正确的换行处理。
case SerialPortEvent.DATA_AVAILABLE:
while (newData != -1) {
try {
newData = http://www.cnblogs.com/southginger/archive/2011/12/07/is.read();
if (newData =http://www.cnblogs.com/southginger/archive/2011/12/07/= -1) {
break;
}
if ('\r' == (char)newData) {
inputBuffer.append('\n');
} else {
inputBuffer.append((char)newData);
}
} catch (IOException ex) {
System.err.println(ex);
return;
}
}
//附加收到的数据来messageAreaIn。
messageAreaIn.append(new String(inputBuffer));
//在这里我截取读入的数据,传送到ParseData()这个类中。
String inString=new String(inputBuffer);
new ParseData().parse(inString);
break;

// If break event append BREAK RECEIVED message.
//如果中断事件追加BREAK收到的消息。
case SerialPortEvent.BI:
messageAreaIn.append("\n--- BREAK RECEIVED ---\n");
}

 

4. ParseData()

import java.io.IOException;
public class ParseData {
String xString="";
String yString="";
String timeStr="";
String state="";
//分析接口
public boolean parse(String sentence)
{
String rawData = http://www.cnblogs.com/southginger/archive/2011/12/07/sentence;
try
{
if (!(rawData.length()>0))
{
return false;
}
sentence = sentence.substring(1, sentence.indexOf('*') - 1);
String[] words =getWords(sentence);
if (words[0].equals("GPGGA")) {
return parseGPGGA(words);
}else if (words[0].equals("GPRMC")) {
return false;
}else if (words[0].equals("GPGSA")) {
return false;
}else if (words[0].equals("GPGSV")) {
return false;
}else {
return false;
}
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public boolean parseGPGGA(String[] words)
{
//取经纬度
if (words[6].length() > 0)
{
timeStr=getTimeFormat(words[1]);
yString=getYformat(words[2]);
xString=getXformat(words[4]);
state=words[6];
String gpsString="时间:"+timeStr+"\n状态:"+state+"\n北纬:"+yString+"\n东经:"+xString+"\n";
try {
new FileOutput().file(gpsString);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}else {
return false;
}
}
//拆分字符串为字符串数组
public String[] getWords(String str){
String[] words=str.split(",");
return words;
}
//时间
public String getTimeFormat(String str){
int t1=Integer.parseInt(str.substring(0, 2))+8;
String t2=str.substring(2, 4);
String t3=str.substring(4, str.length());
return String.valueOf(t1)+"点"+t2+"分"+t3+"秒";
}
//东经
public String getXformat(String str){
double a1=Double.valueOf(str.substring(0, 3));
double a2=Double.valueOf(str.substring(3, str.length()));
double aa1=a2/60;
return String.valueOf(a1+aa1);
}
//北纬
public String getYformat(String str){
double b1=Double.valueOf(str.substring(0, 2));
double b2=Double.valueOf(str.substring(2, str.length()));
double bb1=b2/60;
return String.valueOf(b1+bb1);
}
}


5. FileOutput()

import java.io.*;
class FileOutput {
public void file(String str) throws IOException {
byte b[];
//获取当前类文件所在路径
String classPath=Class.class.getResource("/").getPath().substring(1);
classPath=classPath.substring(0, classPath.lastIndexOf("/"));
String parentPath=classPath.substring(0, classPath.lastIndexOf("/"));
//处理文件路径乱码问题
parentPath = java.net.URLDecoder.decode(parentPath, "utf-8");
File f = new File(parentPath + "/gpsdata.txt");
f.createNewFile();
b = str.getBytes();
//追加内容
// FileOutputStream fos = new FileOutputStream(f, true);
//覆盖内容
FileOutputStream fos = new FileOutputStream(f);
fos.write(b);
fos.close(); }
}

 

 

注:

1. UI窗口中根据设备选择设置端口及波特率,点击“Open Port”打开端口,读取数据。

2. 4种常用的 NMEA0183标准格式说明 

$GPGGA,012440.00,3202.1798,N,11849.0763,E,1,05,2.7,40.2,M,0.5,M,,*6F.. 

时间: 01+8=92440.00秒 

纬度北纬3202.1798分 

经度东经11849.0763分 

定位: 1=(定位sps模式) 0=(未定位

应用卫星数: 05个 

6 HDOP: 2.7米 

海拔: 40.2 

海拔单位: M=(

9 WGS84水准面划分: 0.5 

10 WGS84水准面划分单位 M(

11 

12 校验位: 6F 

 

 

$GPRMC,013946.00,A,3202.1855,N,11849.0769,E,0.05,218.30,111105,4.5,W,A*20.. 

01 时间013946.00秒 

02 定位状态 A=可用 V=警告(不可用

03 纬度北纬(N) 3202.1855分 

04 经度东经(E) 11849.0769分 

05 相对位移速度: 0.05 knots 

06 相对位移方向: 218.30度 

07 日期: 111105(日日月月年年

08 

09 

10 检查位

 

$GPGSA,A,3,01,03,14,20,,,,,,,,,2.6,2.5,1.0*35.. 

01 模式2: A=自动 M=手动 

02 模式1: 1=未定位 2=二维定位 3=三维定位 

03 卫星编号: 0132 

04 PDOP-位置精度稀释: (2.6) 0.5--99.9 

05 HDOP-水平经度稀释: (2.6) 0.5--99.9 

06 VDOP-垂直经度稀释: (1.0) 0.5--99.9 

07 检验位 35 

 

$GPGSV,2,1,08,01,62,160,42,03,23,189,42,06,23,049,32,14,24,150,35*78.. 

01 天空中收到讯号的卫星总数 

02 定位的卫星总数 

03 天空中卫星总数 

04 (01,62,160,42)分别是卫星编号01-32,卫星仰角00-90,卫星方位角000-359,讯号噪声比00-99dB 

以下类似(03,23,189,42) (06,23,049,32) (14,24,150,35) 

05 Checksum检查位*78

 

附加:

/**
*获得本机串行和并行端口号
*/

import javax.comm.*;
import java.util.Enumeration;
public class GpsText
{
 public static void main(String args[]){
 
   Enumeration ports;
   System.out.println("Verifying Build Environment");
   try{
    ports=CommPortIdentifier.getPortIdentifiers();
    if(ports==null){
    System.out.println("No comm ports found!");
    return;
    }
    while(ports.hasMoreElements()){
    System.out.println("Here is a prot ["+((CommPortIdentifier)ports.nextElement()).getName()+"]");
    }
  }catch(Exception e){
   System.out.println("Failed to enumerate ports ["+e.getMessage()+"]");
   e.printStackTrace();
  }
  System.out.println("Complete");
 }
}


 

原文出处:http://www.189works.com/article-41237-1.html谢谢原博主!