如何用 Java 语言向串口读写数据_第1页
如何用 Java 语言向串口读写数据_第2页
如何用 Java 语言向串口读写数据_第3页
如何用 Java 语言向串口读写数据_第4页
如何用 Java 语言向串口读写数据_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.如何用 Java 语言向串口读写数据串口 , RS-232-C(又称 EIA RS-232-C ,以下简称 RS232)是在 1970年由美国电子工业协会(EIA) 联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。RS232 是一个全双工的通讯协议,它可以同时进行数据接收和发送的工作。串口是计算机上一种非常通用设备通信的协议。以前,大多数计算机包含两个基于 RS232 的串口。串口同时也是仪器仪表设备通用的通信协议;很多 GPIB 兼容的设备也带有RS-232 口。同时,串口通信协议也可以用于获取远程采集的数据。串口通信的概念非常简单,串口 按位 (bit) 发

2、送和接收字节 。尽管比按字节 (byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。 它很简单并且能够实现远距离通信。比如 IEEE488 定义并行通行状态时, 规定设备线总常不得超过 20 米,并且任意两个设备间的长度不得超过 2 米;而对于串口而言,长度可达1200 米。说到串口,也许很多人都要怀疑,这都什么年代了,USB设备已经如此普及了, 谁还能想起这个老掉牙的通信端口呀?其实,在现实生活中,串口正因为它老,才会在实际使用中经常用到它。举个简单的例子: 工业制造及其设备与计算机之间的通讯、还有在各种电子工厂测试设备的过程中,都无一例外使用的串口。因为它可以

3、不用像 USB 设备一样必须有软件驱动的支持才可以进行工作。.Java对串口通信的支持常见的 Java串口包SUN 的 CommAPI 分别提供了对常用的 RS232 串行端口和 IEEE1284 并行端口通讯的支持。 目前,常见的 Java串口包有 SUN在 1998 年发布的串口通信 API : comm2.0.jar(Windows 下 )、comm3.0.jar(Linux/Solaris);IBM 的串口通信 API 以及一个开源的实现。鉴于在 Windows 下 SUN 的 API 比较常用以及 IBM 的实现和 SUN 的在 API 层面都是一样的,那个开源的实现又不像两家大厂的

4、产品那样让人放心, 这里就只介绍SUN 的串口通信 API在 Windows 平台下的使用。串口包的安装 (Windows 下)到 SUN 的网站下载 javacomm20-win32.zip ,包含的东西如下所示:.按照其使用说明 (Readme.html)的说法,要想使用串口包进行串口通信, 除了设置好环境变量之外, 还要将 win32com.dll 复制到 bin 目录下 ;将 comm.jar 复制到 lib; 把 perties 也同样拷贝到 lib 目录下。然而在真正运行使用串口包的时候,仅作这些是不够的。因为通常当运行“ java MyApp ”的时候

5、,是由 JRE 下的虚拟机启动 MyApp 的。而我们只复制上述文件到 JDK相应目录下, 所以应用程序将会提示找不到串口。 解决这个问题的方法很简单,我们只须将上面提到的文件放到 JRE 相应的目录下就可以了。串口 API 介绍m.CommPort这是用于描述一个被底层系统支持的端口的抽象类。 它包含一些高层的 IO 控制方法,这些方法对于所有不同的通讯端口来说是通用的。 SerialPort 和 ParallelPort 都是它的子类,前者用于控制串行端口而后者用于控这并口,二者对于各自底层的物理端口都有不同的控制方法。这里我们只关心SerialPort。javax.co

6、mm.CommPortIdentifier.这个类主要用于对串口进行管理和设置, 是对串口进行访问控制的核心类。主要包括以下方法确定是否有可用的通信端口为 IO 操作打开通信端口决定端口的所有权处理端口所有权的争用管理端口所有权变化引发的事件 (Event) m.SerialPort这个类用于描述一个 RS-232 串行通信端口的底层接口,它定义了串口通信所需的最小功能集。 通过它,用户可以直接对串口进行读、写及设置工作。串口 API 实例压缩包中除了api,还包括了几个小例子,下面我们就一起看.一下串口包自带的例子-SerialDemo 中的一小段代码来加深对串口 API

7、核心类的使用方法的认识。列举出本机所有可用串口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.o

8、ut.println(portId.getName();.portChoice.select(parameters.getPortName();以上代码可以列举出当前系统所有可用的串口名称, 我的机器上输出的结果是 COM1 和 COM3 。串口参数的配置串口一般有如下参数可以在该串口打开以前配置进行配置:包括波特率,输入 /输出流控制,数据位数,停止位和奇偶校验。.SerialPort sPort;try sPort.setSerialPortParams(BaudRate,Databits,Stopbits,Parity);/设置输入 /输出控制流sPort.setFlowControlM

9、ode(FlowControlIn | FlowControlOut); catch (UnsupportedCommOperationException e) 串口的读写对串口读写之前需要先打开一个串口:CommPortIdentifierportId=CommPortIdentifier.getPortIdentifier(PortName);try SerialPort sPort = (SerialPort) portId.open( 串口所有者名称 ,.超时等待时间 ); catch (PortInUseException e) / 如果端口被占用就抛出这个异常throw new S

10、erialConnectionException(e.getMessage();/用于对串口写数据OutputStreamos=newBufferedOutputStream(sPort.getOutputStream();os.write(int data);/用于从串口读数据InputStreamis=newBufferedInputStream(sPort.getInputStream();int receivedData = is.read();.读出来的是 int 型,你可以把它转换成需要的其他类型。这里要注意的是,由于 Java 语言没有无符号类型,即所有的类型都是带符号的,在由

11、byte 到 int 的时候应该尤其注意。因为如果 byte 的最高位是 1,则转成 int 类型时将用 1 来占位。这样,原本是 10000000 的 byte 类型的数变成 int 型就成了1111111110000000,这是很严重的问题,应该注意避免。串口通信的通用模式及其问题下面开始我们本次的重点-串口应用的研究。由于向串口写数据很简单,所以这里我们只关注于从串口读数据的情况。通常,串 口 通 信 应 用 程 序 有 两 种 模 式 , 一 种 是 实 现SerialPortEventListener 接口,监听各种串口事件并作相应处理;另一种就是建立一个独立的接收线程专门负责数据的

12、接收。 由于这两种方法在某些情况下存在很严重的问题, 所以我的实现是采用第三种方法来解决这个问题。事件监听模型现在我们来看看事件监听模型是如何运作的:.首 先 需 要 在 你 的 端 口 控 制 类 ( 例 如SManager) 加 上“implements SerialPortEventListener”在初始化时加入如下代码:try SerialPort sPort.addEventListener(SManager); catch (TooManyListenersException e) sPort.close();throw new SerialConnectionException

13、(too many listeners added);sPort.notifyOnDataAvailable(true);覆写 public void serialEvent(SerialPortEvent e)方法,在其中.对如下事件进行判断:BI - 通讯中断 .CD -载波检测 .CTS -清除发送 .DATA_AVAILABLE - 有数据到达 .DSR -数据设备准备好 .FE -帧错误 .OE -溢位错误 .OUTPUT_BUFFER_EMPTY - 输出缓冲区已清空.PE -奇偶校验错 .RI -振铃指示 .一般最常用的就是 DATA_A VAILABLE- 串口有数据到达事件。

14、也就是说当串口有数据到达时, 你可以在 serialEvent 中接收并处理所收到的数据。 然而在我的实践中, 遇到了一个十分严重的问题。首先描述一下我的实验: 我的应用程序需要接收传感器节点从串口发回的查询数据, 并将结果以图标的形式显示出来。 串口设定的波特率是 115200,串口每隔 128 毫秒返回一组数据 (大约是 30 字节左右 ),周期 (即持续时间 )为 31 秒。实测的时候在一个周期内应该返回 4900 多个字节,而用事件监听模型我最多只能收到不到 1500 字节,不知道这些字节都跑哪里去了,也不清楚到底丢失的是那部分数据。 值得注意的是, 这是我将 serialEvent(

15、) 中所有处理代码都注掉, 只剩下打印代码所得的结果。 数据丢失的如此严重是我所不能忍受的,于是我决定采用其他方法。串口读数据的线程模型这个模型顾名思义, 就是将接收数据的操作写成一个线程的形式 :public void startReadingDataThread() .Thread readDataProcess = new Thread(new Runnable() public void run() while (newData != -1) try newData = is.read();System.out.println(newData);/其他的处理过程 . catch (IO

16、Exception ex) System.err.println(ex); return;.readDataProcess.start();在我的应用程序中,我将收到的数据打包放到一个缓存中,然后启动另一个线程从缓存中获取并处理数据。 两个线程以生产者消费者模式协同工作,数据的流向如下图所示:这样,我就圆满解决了丢数据问题。然而,没高兴多久我就又发现了一个同样严重的问题:虽然这回不再丢数据了,可是原本一个周期 (31 秒)之后,传感器节电已经停止传送数据了,但我的串口线程依然在努力的执行读串口操作,在控制台也可以看见收到的数据仍在不断的打印。原来,由于传感器节点发送的数据过快,而我的接收线程处

17、理不过来,所以 InputStream 就先把已到达却还没处理的字节缓存起来, 于是就导致了明明传感器节点已经不再发数据了, 而控制台却还能看见数据不断打印这一奇怪.的现象。唯一值得庆幸的是最后收到数据确实是4900 左右字节,没出现丢失现象。 然而当处理完最后一个数据的时候已经快 1 分半钟了,这个时间远远大于节点运行周期。 这一延迟对于一个实时的显示系统来说简直是灾难 !后来我想,是不是由于两个线程之间的同步和通信导致了数据接收缓慢呢?于是我在接收线程的代码中去掉了所有处理代码,仅保留打印收到数据的语句,结果依然如故。看来并不是线程间的通信阻碍了数据的接收速度, 而是用线程模型导致了对于发

18、送端数据发送速率过快的情况下的数据接收延迟。 这里申明一点,就是对于数据发送速率不是如此快的情况下前面者两种模型应该还是好用的,只是特殊情况还是应该特殊处理。第三种方法TinyOS 中有一部分是和我的应用程序类似的串口通信部分,于是我下载了它的1.x 版的 Java代码部分, 参考了它的处理方法。解决问题的方法说穿了其实很简单,就是从根源入手。根源不就是接收线程导致的吗,那好,我就干脆取消接收线程和作为中介的共享缓存, 而直接在处理线程中调用串口读数据的方法来解决问题,于是程序变成了这样:.public byte getPack()while (true) / PacketLength 为数据包长度byte msgPack = new bytePacketLength;for(int i = 0; i PacketLength; i+)if( (newData = is.read() != -

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论