最近在做传感器数据采集的工作,底层是基于Zigbee的无线传感网络,所有数据采集到Zigbee协调器上然后通知上位机数据采集完成,上位机通过USB转串口去读取数据就可以了。那么问题来了,如何进行串口通讯呢?老板说你用Java写个程序好了嘛,用Java写串口程序也是醉了。实验室也没别人写了,所以就让我写了。当我听到要让我用Java写串口通讯程序的时候我本来是拒绝的,然后。。。就没有然后了。。就只能写了。

网上看了一下,最后用了一个开源的Java串口通讯库RXTX做串口通讯,下面记录一下RXTX的使用方法。

环境配置

RXTX做串口通讯,有一个jar包(RXTXcomm.jar)和一个rxtxSerial.dll(Windows环境下)或者librxtxSerial.so(Linux环境下),因为开发是在Windows上,但是工作是在Linux上,所以两个都用到了。

Windows环境下

文档里是这么写的

Copy rxtxSerial.dll ---> <JAVA_HOME>\jre\bin

但是这个做了之后并不能用,会有一些很奇怪的问题,不知道是不是我的Java环境配置有问题还是怎么了,我是把dll文件copy到了C:\Windows\System32,然后一切正常,一直很奇怪,为什么要cp到<JAVA_HOME>\jre\bin呢?求解答!

Linux环境下

Copy librxtxSerial.so ---> <JAVA_HOME>/jre/lib/i386/

or

Copy librxtxSerial.so ---> <JAVA_HOME>/jre/lib/x86_64/

这个按照文档没问题。

小问题

我用的是rxtx-2.2pre2版本的,文档里有写运行时会报版本不匹配的WARNING,实际使用中的确也是这样的,不过目前还没有别的问题,不影响使用。

常用方法

1.查找端口


  1. /**
  2. * 查找所有可用端口
  3. *
  4. * @return 所有端口列表
  5. */
  6. public static final ArrayList<String> findPort() {
  7. Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();//获得所有串口
  8. ArrayList<String> portNameList = new ArrayList<>();
  9. //串口名字添加到List并返回
  10. while (portList.hasMoreElements()) {
  11. String portName = portList.nextElement().getName();
  12. portNameList.add(portName);
  13. }
  14. return portNameList;
  15. }

2.打开端口


  1. /**
  2. * 打开串口
  3. *
  4. * @param portName 端口名称
  5. * @param baudrate 波特率
  6. * @return 串口对象
  7. */
  8. public static final SerialPort openPort(String portName, int baudrate) {
  9. try {
  10. //通过端口名识别端口
  11. CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
  12. //打开端口,并给端口名字和一个timeout
  13. CommPort commPort = portIdentifier.open(portName, 2000);
  14. //判断是不是串口
  15. if (commPort instanceof SerialPort) {
  16. SerialPort serialPort = (SerialPort) commPort;
  17. try {
  18. //设置一下串口的波特率等参数
  19. serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
  20. } catch (UnsupportedCommOperationException e) {
  21. LOGGER.error("Set Serialport Parameters failure", e);
  22. }
  23. System.out.println("Open " + portName + " sucessfully !");
  24. return serialPort;
  25. } else {
  26. LOGGER.error("This port is not a serialport");
  27. return null;
  28. }
  29. } catch (NoSuchPortException | PortInUseException e) {
  30. LOGGER.error("There is no " + portName + "or it's occupied!", e);
  31. return null;
  32. }
  33. }

3.发送数据


  1. /**
  2. * 发送数据
  3. *
  4. * @param serialPort 串口对象
  5. * @param order 命令字节
  6. */
  7. public void sendToPort(SerialPort serialPort, byte[] order) {
  8. try {
  9. OutputStream out = serialPort.getOutputStream();
  10. out.write(order);
  11. out.flush();
  12. out.close();
  13. } catch (IOException e) {
  14. LOGGER.error("Send to SerialPort failure", e);
  15. }
  16. }

4.读取数据


  1. /**
  2. * 读取数据
  3. *
  4. * @return 字节ArrayList
  5. */
  6. public byte[] readFromPort(InputStream inStream) {
  7. byte[] bytes = null;
  8. try {
  9. while (true) {
  10. //获取buffer里的数据长度
  11. int bufflenth = inStream.available();
  12. if (0 == bufflenth) {
  13. break;
  14. }
  15. bytes = new byte[bufflenth];
  16. inStream.read(bytes);
  17. }
  18. } catch (IOException e) {
  19. LOGGER.error("Read Data Failure", e);
  20. }
  21. return bytes;
  22. }

监听器

1.实现监听器

继承SerialPortEventListener然后重写serialEvent,然后再各个对应case里面写代码就好啦。


  1. public class TestExample implements SerialPortEventListener {
  2. @Override
  3. public void serialEvent(SerialPortEvent serialPortEvent) {
  4. switch (serialPortEvent.getEventType()) {
  5. case SerialPortEvent.BI: // 10通讯中断
  6. case SerialPortEvent.OE: // 7溢位错误
  7. case SerialPortEvent.FE: // 9帧错误
  8. case SerialPortEvent.PE: // 8奇偶校验错
  9. case SerialPortEvent.CD: // 6载波检测
  10. case SerialPortEvent.CTS: // 3清除发送
  11. case SerialPortEvent.DSR: // 4数据设备准备好
  12. case SerialPortEvent.RI: // 5振铃指示
  13. case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2输出缓冲区已清空
  14. case SerialPortEvent.DATA_AVAILABLE: // 1读到可用数据时激活
  15. }
  16. }
  17. }

2.给串口添加监听器


  1. /**
  2. * 添加监听器
  3. *
  4. * @param port 串口对象
  5. * @param listener 串口监听器
  6. */
  7. public static void addListener(SerialPort port, SerialPortEventListener listener) {
  8. try {
  9. // 给串口添加监听器
  10. port.addEventListener(listener);
  11. // 设置当有数据到达时唤醒监听接收线程
  12. port.notifyOnDataAvailable(true);
  13. port.notifyOnBreakInterrupt(true);
  14. System.out.println("Add listeners to " + port.getName() + " sucessfully !");
  15. } catch (TooManyListenersException e) {
  16. LOGGER.error("There is too many listeners !", e);
  17. }
  18. }

TIP

** 一定记得从串口发指令取数据之后加一个延时,等待底层数据传输完成再去buffer里面取,不然很大可能数据包不完整。 **

Java利用Rxtx进行串口通讯的更多相关文章

  1. ProtocolBuffers (二) android与PC,C#与Java 利用protobuf 进行无障碍通讯【Socket】

    protobuf 是什么?   Protocol buffers是一种编码方法构造的一种有效而可扩展的格式的数据. 谷歌使用其内部几乎RPC协议和文件格式的所有协议缓冲区. 参考文档 http://c ...

  2. 基于RXTX的串口通讯 windows64位系统可用

    项目地址 http://download.csdn.net/detail/xqshishen/7739539

  3. java web下串口通讯

       最近在做java串口通讯,主要是用个人电脑通过串口从RS485读取数据,并通过crc循环冗余校验,把接收正确的数据解析,插入数据库mysql,并用SSH技术把数据库数据以表格以及图表形式显示   ...

  4. 简单的Java串口通讯应答示例

    java串口通讯第一次使用,找的资料都比较麻烦,一时没有理出头绪,自己在示例的基础上整理了一个简单的应答示例,比较简陋,但演示了java串口通讯的基本过程. package com.garfield. ...

  5. Android串口通讯

    今天在整一个项目,需要利用串口通讯在网上看了好多人的帖子才稍微整出了一点头绪. 首先串口代码就是利用谷歌自己的api,将java代码放在java/android_serialport_api目录下,如 ...

  6. 用SPCOMM 在 Delphi中实现串口通讯 转

      用Delphi 实现串口通讯,常用的几种方法为:使用控件如MSCOMM和SPCOMM,使用API函数或者在Delphi 中调用其它串口通讯程序.利用API编写串口通信程序较为复杂,需要掌握大量通信 ...

  7. 教程-Delphi MSComm 实时串口通讯

    Delphi  MSComm 实时串口通讯 MSComm控件具有丰富的与串口通信密切相关的属性,提供了对串口进行的多种操作,进而使串行通信变得十分简便.MSComm的控件属性较多,常用的属性如下:1) ...

  8. STM32F10x 学习笔记6(USART实现串口通讯 2)

    这次讲讲利用串口收发中断来进行串口通讯.STM32 上为每个串口分配了一个中断.也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断.程序需在中断处理函数中读取状态寄存器(USART_SR) ...

  9. 使用Xamarin实现串口通讯

    前几天我写了年度总结,然后有人说让我教一下他Xamarin串口通讯怎么做,其实跟java没有多大区别. 记得我刚开始接到公司这个项目的时候很懵逼,我去看了别的安卓串口工具,都不行我当时是RS232串口 ...

随机推荐

  1. javascript基础学习(十五)

    javascript之cookie 学习要点: cookie介绍 创建与获取cookie cookie的编码 cookie的生存期 cookie的路径 cookie的domain cookie的sec ...

  2. InstallShield Basic MSI工程常见问题解答[转]

    1.  问题描述:采用何种安装模式?实现方法:如果对用户界面等自定义要求不高的话,建议用Basic Msi Project,否则用InstallScript MSI Project. 2.  问题描述 ...

  3. nginx反向代理取得IP地址

    nginx反向代理后,在应用中取得的ip都是反向代理服务器的ip,取得的域名也是反向代理配置的url的域名,解决该问题,需要在nginx反向代理配置中添加一些配置信息,目的将客户端的真实ip和域名传递 ...

  4. HDU 1312:Red and Black(DFS搜索)

      HDU 1312:Red and Black Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & ...

  5. C# 取小数点

    1.Math.Round(0.333333,2);//按照四舍五入的国际标准2. double dbdata=0.335333; string str1=String.Format("{0: ...

  6. Unix中$$、$@、$#、$*的意思

    $$: 表示当前命令进程的PID $#: 表示参数的个数 $@ 和 $* : 都表示输出所有的参数 区别: $*:表示合并为一个参数  “$1 $2 $3 $n” $@:表示分解为多个参数 “$1” ...

  7. struct和typedef struct的用法

    我首先想到的去MSDN上看看sturct到底是什么东西,虽然平时都在用,但是每次用的时候都搞不清楚到底这两个东西有什么区别,既然微软有MSDN,我们为什么不好好利用呢,下面是摘自MSDN中的一段话: ...

  8. 构建高可用web站点学习(二)

    web站点的缓存学习 缓存在web应用里面十分常见,也有各种各样的缓存,从请求开始一直到代码处理的阶段都可以采取缓存.下面就逐一介绍: 一.客户端缓存(浏览器和http方面) 前端页面缓存主要遵循ht ...

  9. iPhone之为UIView设置阴影(CALayer的shadowColor,shadowOffset,shadowOpacity,shadowRadius,shadowPath属性)

    效果图: 以下代码实现: 第一个图片的代码 //加阴影--任海丽编辑 _imageView.layer.shadowColor = [UIColor blackColor].CGColor;//sha ...

  10. 【博弈论】HDU 5754 Life Winner Bo

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5754 题目大意: 4种棋子,象棋中的 1王,2车,3马,4后,选其一,B和G轮流走,不能往左上走,一 ...