java串口通信
/t2bbs20930/blog/item/b2e0f8226f96bda34723e8bf.html
Java提供了 CommunicationAPI(包含于包中)用于通过与机器无关的方式,控制各种外部设备。Communications API,是标准的Java的扩展部分,它在JavaAPI中是没有附带的。因此,必须先在SUN公司网站的Java站点(www.)上下载这个扩展类库。
1.1Communications API 简介
Communications API 的核心是抽象的CommPort类及其两个子类:SerialPort类和ParallePort类。其中,SerialPort类是用于串口通信的类,ParallePort类是用于并行口通信的类。CommPort类还提供了常规的通信模式和方法,例如:getInputStream( )方法和getOutputStream( )方法,专用于与端口上的设备进行通信。
然而,这些类的构造方法都被有意的设置为非公有的(non-public)。所以,不能直接构造对象,而是先通过静态的PortIdentifiers()获得端口列表;再从这个端口列表中选择所需要的端口,并调用CommPortIdentifer对象的Open( )方法,这样,就能得到一个CommPort对象。当然,还要将这个CommPort对象的类型转换为某个非抽象的子类,表明是特定的通讯设备。该子类可以是SerialPort
类和ParallePort类中的一个。下面将分别对CommPort类,CommPortIdentifier类,串口类SerialPort进行详细的介绍。
1.2 CommPortIdentifier类
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) 打开端口,两个参数:程序名称,延迟时间(毫秒数)
1.3 SerialPort类
SerialPort关于串口参数的静态成员变量
成员变量 说明 成员变量 说明 成员变量 说明
DATABITS_5 数据位为5 STOPBITS_2 停止位为2 PARITY_ODD 奇检验
DATABITS_6 数据位为6 STOPBITS_1 停止位为1 PARITY_MARK 标记检验
DATABITS_7 数据位为7 STOPBITS_1_5 停止为1.5 PARITY_NONE 空格检验
DATABITS_8 数据位为8 PARITY_EVEN 偶检验 PARITY_SPACE 无检验
SerialPort对象的关于串口参数的函数
方法 说明 方法 说明
getBaudRate() 得到波特率 getParity() 得到检验类型
getDataBits() 得到数据位数
getStopBits() 得到停止位数
tSerialPortParams(int, int, int, int) 设置串口参数依次为(波特率,数据位,停止位,奇偶检验) 短歌行原文及翻译
SerialPort关于事件的静态成员变量
英语专业就业方向成员变量 说明 成员变量 说明
BI Break interrupt中断 FE Framing error错误
CD Carrier detect载波侦听 OE Overrun error错误
CTS Clear to nd清除以传送 PE Parity error奇偶检验错误
DSR Data t ready数据备妥 RI Ring indicator响铃侦测
DATA_AVAILABLE 串口中的可用数据 OUTPUT_BUFFER_EMPTY 输出缓冲区空
SerialPort中关于事件的方法
方法 说明 方法 说明 方法 说明
isCD() 是否有载波 isCTS() 是否清除以传送 isDSR() 数据是否备妥
isDTR() 是否数据端备妥 isRI() 是否响铃侦测 isRTS() 是否要求传送
addEventListener(SerialPortEventListener) 向SerialPort对象中添加串口事件监听器
removeEventListener() 移除SerialPort对象中的串口事件监听器
notifyOnBreakInterrupt(boolean) 设置中断事件true有效,fal无效
notifyOnCarrierDetect(boolean) 设置载波监听事件true有效,fal无效
notifyOnCTS(boolean) 设置清除发送事件true有效,fal无效
notifyOnDataAvailable(boolean) 设置串口有数据的事件true有效,fal无效
notifyOnDSR(boolean) 设置数据备妥事件true有效,fal无效
notifyOnFramingError(boolean) 设置发生错误事件true有效,fal无效
notifyOnOutputEmpty(boolean) 设置发送缓冲区为空事件true有效,fal无效
notifyOnParityError(boolean) 设置发生奇偶检验错误事件true有效,fal无效
notifyOnRingIndicator(boolean) 设置响铃侦测事件true有效,fal无效
getEventType() 得到发生的事件类型返回值为int型
ndBreak(int) 设置中断过程的时间,参数为毫秒值
tRTS(boolean) 设置或清除RTS位
tDTR(boolean) 设置或清除DTR位
SerialPort中的其他常用方法
方法 说明
clo() 关闭串口
getOutputStream() 得到OutputStream类型的输出流
getInputStream() 得到InputStream类型的输入流
嵌入式系统或传感器网络的很多应用和测试都需要通过PC机与嵌入式设备或传感器节点进行通信。其中,最常用的接口就是RS-232串口和并口(鉴于USB接口的复杂性以及不需要很大的数据传输量,USB接口用在这里还是显得过于奢侈,况且目前除了SUN有一个支持USB的包之外,我还没有看到其他直接支持USB的Java类库)。SUN的CommAPI分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。RS-232-C(又称EIA RS-232-C,以下简称RS232)是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。RS232是一个全双工的通讯协议,它可以同时进行数据接收和发送的工作。
1 常见的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平台下的使用。
串口包的安装(Windows下)
到SUN的网站下载javacomm20-win32.zip,包含的东西如下所示:
按照其使用说明(Readme.html)的说法,要想使用串口包进行串口通信,除了设置好环境变量之外,还要将win32com.dll复制到\bin目录下;将comm.jar复制到\lib;把properties也同样拷贝到\lib 目录下。然而在真正运行使用串口包的时候,仅作这些是不够的。因为通常当运行“java MyApp”的时候,是由JRE下的虚拟机启动MyApp的。而我们只复制上述文件到JDK相应目录下,所以应用程序将会提示找不到串口。解决这个问题的方法很简单,我们只须将上面提到的文件放到JRE相应的目录下就可以了。
值得注意的是,在网络应用程序中使用串口API的时候,还会遇到其他更复杂问题。有兴趣的话,你可以查看CSDN社区中“关于网页上Applet用javacomm20读取客户端串口的问题”的帖子。
2 串口API概览
2.CommPort
这是用于描述一个被底层系统支持的端口的抽象类。它包含一些高层的IO控制方法,这些方法对于所有不同的通讯端口来说是通用的。 SerialPort 和ParallelPort都是它的子类,前者用于控制串行端口而后者用于控这并口,二者对于各自底层的物理端口都有不同的控制方法。这里我们只关心 SerialPort。
2.CommPortIdentifier
这个类主要用于对串口进行管理和设置,是对串口进行访问控制的核心类。主要包括以下方法
确定是否有可用的通信端口
为IO操作打开通信端口
决定端口的所有权
处理端口所有权的争用
管理端口所有权变化引发的事件(Event)
2.SerialPort
这个类用于描述一个RS-232串行通信端口的底层接口,它定义了串口通信所需的最小功能集。通过它,用户可以直接对串口进行读、写及设置工作。
2.4 串口API实例
大段的文字怎么也不如一个小例子来的清晰,下面我们就一起看一下串口包自带的例子---SerialDemo中的一小段代码来加深对串口API核心类的使用方法的认识。
2.4.1 列举出本机所有可用串口
void listPortChoices() {
CommPortIdentifier portId;
Enumeration en = PortIdentifiers();
// iterate through the ports.
while (en.hasMoreElements()) {
portId = (CommPortIdentifier) en.nextElement();
if (portId.
getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.Name());
}
}
portChoice.PortName());
}
以上代码可以列举出当前系统所有可用的串口名称,我的机器上输出的结果是COM1和COM3。
2.4.2 串口参数的配置
串口一般有如下参数可以在该串口打开以前配置进行配置:
包括波特率,输入/输出流控制,数据位数,停止位和齐偶校验。
SerialPort sPort;
try {
sPort.tSerialPortParams(BaudRate,Databits,Stopbits,Parity);
//设置输入/输出控制流
sPort.tFlowControlMode(FlowControlIn | FlowControlOut);
} catch (UnsupportedCommOperationException e) {}
2.4.3 串口的读写
对串口读写之前需要先打开一个串口:
CommPortIdentifier portId = PortIdentifier(PortName);威胁英语
try {
SerialPort sPort = (SerialPort) portId.open("串口所有者名称", 超时等待时间);
} catch (PortInUException e) {//如果端口被占用就抛出这个异常
throw new Message());
yes man }
//用于对串口写数据
OutputStream os = new OutputStream());
os.write(int data);
//用于从串口读数据牛津字典
InputStream is = new InputStream());
int receivedData = is.read();
读出来的是int型,你可以把它转换成需要的其他类型。
这里要注意的是,由于Java语言没有无符号类型,即所有的类型都是带符号的,在由byte到int的时候应该尤其注意。因为如果byte的最高位是1,则转成int类型时将用1来占位。这样,原本是10000000的byte类型的数变成int型就成了1111111110000000,这是很严重的问题,应该注意避免。
Comm API基础
我无意于在此详细描述Comm API每个类和接口的用法,但我会介绍Comm API的类结构和几个重要的API用法。
所有的comm API位于包下面。从Comm API的javadoc来看,它介绍给我们的只有区区以下13个类或接口:
Java代码
CommDriver
CommPort
ParallelPort
SerialPort
CommPortIdentifier
CommPortOwnershipListener
ParallelPortEvent
SerialPortEvent
ParallelPortEventListener (extends java.util.EventListener)
SerialPortEventListener (extends java.util.EventListener)
NoSuchPortException
英语包过 PortInUException
UnsupportedCommOperationException
CommDriver
CommPort
P
arallelPort
SerialPort
CommPortIdentifier
CommPortOwnershipListener
ParallelPortEvent
ici SerialPortEvent
ParallelPortEventListener (extends java.util.EventListener)
SerialPortEventListener (extends java.util.EventListener)
NoSuchPortException
PortInUException
UnsupportedCommOperationException
下面讲解一下几个主要类或接口。
1.枚举出系统所有的RS232端口
在开始使用RS232端口通讯之前,我们想知道系统有哪些端口是可用的,以下代码列出系统中所有可用的RS232端口:
Java代码
Enumeration en = PortIdentifiers();
CommPortIdentifier portId;
while (en.hasMoreElements())
{
portId = (CommPortIdentifier) en.nextElement();
/*如果端口类型是串口,则打印出其端口信息*/
if (PortType() == CommPortIdentifier.PORT_SERIAL)
在线英汉
{
System.out.Name());
}
}
Enumeration en = PortIdentifiers();
CommPortIdentifier portId;
while (en.hasMoreElements())
{
portId = (CommPortIdentifier) en.nextElement();
/*如果端口类型是串口,则打印出其端口信息*/
if (PortType() == CommPortIdentifier.PORT_SERIAL)
{
System.out.Name());
}
}
在我的电脑上以上程序输出以下结果:
COM1
COM2
CommPortIdentifier类的getPortIdentifiers方法可以找到系统所有的串口,每个串口对应一个CommPortIdentifier类的实例。
workout>sweaters 2.打开端口
如果你使用端口,必须先打开它。
Java代码
try{
CommPort rialPort = portId.open("My App", 60);
/*从端口中读取数据*/
InputStream input = InputStream();
ad(...);
/*往端口中写数据*/
OutputStream output = OutputStream();
output.write(...)
...
}catch(PortInUException ex)
{ ... }
try{
CommPort rialPort = portId.open("My App", 60);
/*从端口中读取数据*/
InputStream input = InputStream();
ad(...);
/*往端口中写数据*/
OutputStream output = OutputStream();
output.write(...)
...
}catch(PortInUException ex)
{ ... }
通过CommPortIdentifier的open方法可以返回一个CommPort对象。open方法有两