【Java上位机】(一)串口通信
来源:互联网 发布:软件测试平台 编辑:程序博客网 时间:2024/06/05 09:46
一、串口通信简介
在开发嵌入式系统时常需要PC与单片机通信,其中串口通信最为常用。常见的串行接口有RS-232、USB等。USB的复杂性在简单的通信中显得过于奢侈,所以由美国电子工业协会(EIA)在1970年联合贝尔及众多计算机厂家共同制定的用于串行通信的标准RS-232被广泛用于单片机与PC通信,RS-232是一个全双工的通讯协议,它可以同时进行数据接收和发送的工作。
1 常见的Java串口通信包
Sun公司曾推出过comm2.0.jar和comm3.0.jar。但是由于其不支持64位系统,以及长时间没有更新,所以现在常用RXTX串口通信包。它不仅支持64位多平台系统,而且其API与comm。
2 RXTX串口通信包的安装
下载串口通信包RXTX。•复制 rxtxParallel.dll 到 c:/Program Files/Java/jre1.6.0_01/bin/•复制 rxtxSerial.dll 到 c:/Program Files/Java/jre1.6.0_01/bin/•复制 RXTXcomm.jar 到 c:/Program Files/Java/jre1.6.0_01/lib/ext/
二、串口API方法及属性概览
接口:
CommDriver可负载设备(the loadable device)驱动程序接口的一部分CommPortOwnershipListener传递各种通讯端口的所有权事件ParallelPortEventListener传递并行端口事件SerialPortEventListener传递串行端口事件
类:
CommPort通讯端口CommPortIdentifier通讯端口管理ParallelPort并行通讯端口ParallelPortEvent并行端口事件SerialPortRS-232串行通讯端口SerialPortEvent 串行端口事件
异常类:
NoSuchPortException当驱动程序不能找到指定端口时抛出PortInUseException当碰到指定端口正在使用中时抛出UnsupportedCommOperationException驱动程序不允许指定操作时抛出
类的详细介绍:
CommPortIdentifier类
这个类主要用于对通信端口进行管理和设置,是对端口进行访问控制的核心类,主要包括以下方法:
addPortName(String,int, CommDriver) 添加端口名到端口列表里addPortOwnershipListener(CommPortOwnershipListener)添加端口拥有的监听器removePortOwnershipListener(CommPortOwnershipListener)移除端口拥有的监听器getCurrentOwner()获取当前占有端口的对象或应用程序 getName()获取端口名称 getPortIdentifier(CommPort)获取指定打开的端口的CommPortIdentifier类型对象getPortIdentifier(String)获取以参数命名的端口的CommPortIdentifier类型对象getPortIdentifiers()获取系统中的端口列表 getPortType()获取端口的类型 isCurrentlyOwned()判断当前端口是否被占用 open(FileDescriptor)用文件描述的类型打开端口 open(String,int) 打开端口,两个参数:程序名称,延迟时间(毫秒数)
SerialPort类
这个类用于描述一个RS-232串行通信端口的底层接口,它定义了串口通信所需的最小功能集。通过它,用户可以直接对串口进行读、写及设置工作。
SerialPort类中关于串口参数的静态成员变量说明:
DATABITS_5 数据位为5DATABITS_6 数据位为6DATABITS_7 数据位为7 DATABITS_8 数据位为8 PARITY_NONE 空格检验 PARITY_ODD 奇检验 PARITY_EVEN 偶检验 PARITY_MARK 标记检验 PARITY_SPACE 无检验 STOPBITS_1 停止位为1 STOPBITS_2 停止位为2 STOPBITS_1_5 停止位为1.5
SerialPort类中关于串口参数的方法说明:
getBaudRate()得到波特率 getParity()得到检验类型 getDataBits()得到数据位数 getStopBits()得到停止位数 setSerialPortParams(int,int, int, int) 设置串口参数依次为(波特率,数据位,停止位,奇偶检验)
SerialPort类中关于事件的静态成员变量说明:
BI Break interrupt 通讯中断FE Framing error 帧错误CD Carrier detect 载波侦听OE Overrun error 溢位错误CTS Clear to send 清除发送PE Parity error 奇偶检验错误 DSR Data set ready 数据设备准备好RI Ring indicator 响铃侦测 DATA_AVAILABLE 串口中的可用数据OUTPUT_BUFFER_EMPTY 输出缓冲区已清空
SerialPort类中关于事件的方法说明:
isCD()是否有载波 isCTS()是否清除以传送isDSR()数据是否备妥 isDTR()是否数据端备妥isRI()是否响铃侦测isRTS()是否要求传送 addEventListener(SerialPortEventListener)向SerialPort对象中添加串口事件监听器removeEventListener()移除SerialPort对象中的串口事件监听器 notifyOnBreakInterrupt(boolean)设置中断事件true有效,false无效notifyOnCarrierDetect(boolean)设置载波监听事件true有效,false无效notifyOnCTS(boolean)设置清除发送事件true有效,false无效 notifyOnDataAvailable(boolean)设置串口有数据的事件true有效,false无效notifyOnDSR(boolean)设置数据备妥事件true有效,false无效 notifyOnFramingError(boolean)设置发生错误事件true有效,false无效notifyOnOutputEmpty(boolean)设置发送缓冲区为空事件true有效,false无效notifyOnParityError(boolean)设置发生奇偶检验错误事件true有效,false无效notifyOnRingIndicator(boolean)设置响铃侦测事件true有效,false无效getEventType()得到发生的事件类型返回值为int型 sendBreak(int)设置中断过程的时间,参数为毫秒值 setRTS(boolean)设置或清除RTS位 setDTR(boolean)设置或清除DTR位
SerialPort中的其他常用方法说明:
close()关闭串口getOutputStream()得到OutputStream类型的输出流 getInputStream()得到InputStream类型的输入流
三、样例代码
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;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Enumeration;import java.util.Timer;import java.util.TimerTask;import java.util.TooManyListenersException;import javax.print.attribute.standard.PrinterMessageFromOperator;import com.sun.glass.ui.TouchInputSupport;public class SerialRead implements SerialPortEventListener{ protected static CommPortIdentifier portid = null; //通讯端口标识符 protected static SerialPort comPort = null; //串行端口 protected int BAUD = 9600; //波特率 protected int DATABITS = SerialPort.DATABITS_8;; //数据位 protected int STOPBITS = SerialPort.STOPBITS_1; //停止位 protected int PARITY = SerialPort.PARITY_NONE; //奇偶检验 private static OutputStream oStream; //输出流 private static InputStream iStream; //输入流 /** * 读取所有串口名字 */ private 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) { System.out.println(portId.getName()); } } } /** * 设置串口号 */ private void setSerialPortNumber(String port) { try { portid = CommPortIdentifier.getPortIdentifier(port); if(portid.isCurrentlyOwned()){ System.out.println("端口在使用"); }else{ comPort = (SerialPort) portid.open(this.getClass().getName(), 1000); } } catch (PortInUseException e) { System.out.println("端口被占用"); e.printStackTrace(); } catch (NoSuchPortException e) { System.out.println("端口不存在"); e.printStackTrace(); } try { iStream = comPort.getInputStream(); //从COM1获取数据 oStream = comPort.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } try { comPort.addEventListener(this); //给当前串口增加一个监听器 comPort.notifyOnDataAvailable(true); //当有数据是通知 } catch (TooManyListenersException e) { e.printStackTrace(); } try { //设置串口参数依次为(波特率,数据位,停止位,奇偶检验) comPort.setSerialPortParams(this.BAUD, this.DATABITS, this.STOPBITS, this.PARITY); } catch (UnsupportedCommOperationException e) { System.out.println("端口操作命令不支持"); e.printStackTrace(); } try { //# testData String testData = "1"; oStream.write(testData.getBytes()); // iStream.close(); // comPort.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void serialEvent(SerialPortEvent event) { 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:// 当有可用数据时读取数据,并且给串口返回数据 try { StringBuilder buf = new StringBuilder(128); while(iStream.available() > 0) { System.out.println("接收数据:"+((byte) iStream.read())); } } catch (IOException e) { } break; } }}
四、总结
在编写单片机端的时候,发送指令之后要加一个延时,等待底层数据传输完后再读取,否则数据会不完整。
Java在串口通信上位机中并不常用,但因其跨平台的通用性,在一些工程应用中也有Java的一席之地。
由于Sun没有为Linux提供JavaComm的参考实现,人们为java和linux开发了RxTx。后来RxTx被移植到了其他平台。最新版本的RxTx已知可运行在100种以上平台,包括Linux,Windows, Mac OS, Solaris 和其他操作系统。 RxTx可以独立于JavaComm API使用,也可以作为所谓的JavaCommAPI服务者。如果采用后者还需要一个称为JCL的封装包。JCL和RxTx通常与Linux/Java发行版打包在一起,或者JCL完全与代码集成在一起。所以,在一个个地下载他们之前,看一看Linux发行版的CD是值得的。
由于Sun对JavaComm的有限的支持和不适当的文档,放弃JavaCommAPI,转而直接使用RxTx而不是通过JCL封装包似乎成为了一种趋势。然而RxTx的文档是很稀少的。特别是RxTx开发者喜欢将他们的版本和包内容弄得一团糟(例如使用或未使用集成的JCL)。从1.5版本开始,RxTx包含了公共JavaComm类的替代类。由于法律原因,他们没有在java.comm包中,而是在gnu.io包下。然而现存的两个版本的打包内容有很大差别。
·RxTx 2.1 这个版本的RxTx包含了一个完整的代替java.comm的gnu.io包。它应该源自于RxTx 1.5,这是支持gnu.io的起始版本。
·RxTx 2.0, 为了能在JavaComm通用版本下有不同的提供者,不同于JavaComm包下的那个。然而,如果你只想用gnu.io替换包,那么你只需要将一个JavaComm应用转换成RxTx应用。
使用RxTx 2.0作为JavaComm接口的实现将应用移植到RxTx 2.1环境上 上面的第一项在前面已经解释,第二项也相当简单。对于需要将JavaComm应用移植到RxTx 2.1上来的人,只需要将应用源代码中所有对“java.comm”包的引用换成“gnu.io”包,如果原始的JavaComm应用编写恰当,这里就没有其他的事情需要去做。
在Unix平台上,RxTx2.1甚至提供了工具“contrib/ChangePackage.sh”去在源代码树形结构中执行全局的替换,这样的替换在其他的平台很容易使用支持重构功能的IDE(集成开发环境)来完成。
- 【Java上位机】(一)串口通信
- 上位机串口通信
- 上位机-串口通信-C#
- mfc串口通信上位机
- java实现上位机与下位机串口通信
- 串口通信的上位机程序(openGL画图)
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- LabVIEW上位机与串口通信
- 文件的元数据信息有哪些,分别表示什么含义,如何查看?如何修改文件的时间戳信息。
- 运维笔记1
- 第四周项目3-单链表应用(1)
- Spring框架参考手册_5.0.0_中英文对照版_Part II_3.4
- HTTP响应码
- 【Java上位机】(一)串口通信
- lcd fb参数如何计算
- 常量指针与指针常量的区别
- Caffe抽取图像特征
- SQLServer BCP 导入导出数据
- 51NOD 1006 最长公共子序列 动态规划
- 八月份考题
- POJ 1947
- 温故知新(七):面向对象(一)