博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 获取温度_Java利用RXTX串口通信工具类获取DS18B20温度传感器的温度值
阅读量:6485 次
发布时间:2019-06-23

本文共 4582 字,大约阅读时间需要 15 分钟。

环境:Windows10,Eclipse4.5.2,JDK1.7

设备:DS18B20温度传感器(4线,485接口),USB转485接口转换器,笔记本电脑

注意点:RTU传输,使用的是字节,那么在程序中常会遇到传给设备的字节无法用byte表示,可能会溢出(例如校验值),所以也可以用int值传入,效果相同。

MyTwoWaySerialComm.java   [核心类]

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Scanner;

import gnu.io.CommPort;

import gnu.io.CommPortIdentifier;

import gnu.io.SerialPort;

/**

* 双向串行通信类

* @author 都颜汗

*

*/

public class MyTwoWaySerialComm {

/**

* 端口连接

* @param portName

* @throws Exception

*/

void connect(String portName) throws Exception {

// 通过端口名获取端口标志对象

CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);

// 检测当前端口是否已有所属(即检测是否被占用)

boolean isOwned = portIdentifier.isCurrentlyOwned();

// 若已经被占用

if(isOwned)

{

System.out.println("当前端口已经被占用");

}

// 若当前端口可用

else {

// 打开通信端口 (注意:这里使用应用名,和打开超时时间,单位ms),打开后获取通信端口对象

CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);

// 判断当前这个端口对象commPort是否是串行端口类的对象,注意:这里如果没有获取到commPort对象 一样会返回false

if(commPort instanceof SerialPort)

{

// 如果是串行端口(电脑上除了串行端口,还有并行端口),则转换成串行端口对象

SerialPort serialPort = (SerialPort)commPort;

// 设置端口参数(波特率,数据位,停止位,奇偶性[校验])

serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

// 获取当前串口(串行端口)的输入输出流

InputStream is = serialPort.getInputStream();

OutputStream os = serialPort.getOutputStream();

// 利用上面的输入输出流创建两个单独的线程进行报文的传送与接收

(new Thread(new SerialReadThreadBody(is))).start();

(new Thread(new SerialWriteThreadBody(os))).start();

}

// 否则当前端口不是串行端口,或者串口打开失败

else {

System.out.println("当前端口不是串行端口,或发生未知错误,导致串口打开失败!");

}

}

}

/**

* 创建一个串读线程体内部类

* 作用:从设备读报文到上位机

* @author 都颜汗

*

*/

public class SerialReadThreadBody implements Runnable {

private InputStream is;

// 创建一个构造,用于获取输入流对象

public SerialReadThreadBody(InputStream is) {

this.is = is;

}

@Override

public void run() {

// 操作:从输入流中读取报文,传给上位机,显示出来

byte[] buf = new byte[1024];

int len = -1;

try {

String temperatureHexStr = "";

while((len = this.is.read(buf)) > -1)

{

if(len == 1)

System.out.println("当前默认地址:" + SerialCommUtils.byte2HexStr(buf[0]));

else

for(int i = 0; i < len; i++)

{

System.out.print(SerialCommUtils.byte2HexStr(buf[i]) + " ");

if(i == 2 || i == 3)

{

temperatureHexStr += SerialCommUtils.byte2HexStr(buf[i]);

}

if(i == len-1)

{

// 打印温度

System.out.println("\n当前获取到的温度是:" + SerialCommUtils.hexStr2Integer(temperatureHexStr)*0.1 + "°C");

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 创建一个串写线程体内部类

* 作用:从上位机写报文到设备

* @author 都颜汗

*

*/

public class SerialWriteThreadBody implements Runnable {

OutputStream os;

public SerialWriteThreadBody(OutputStream os) {

this.os = os;

}

// 0 3 0 0 0 2 197 218

@Override

public void run() {

// 操作:从输出流中将报文传给设备,然后设备做出响应,单独通过串读线程将结果返回给上位机

try {

Scanner sc = new Scanner(System.in);

String input = "";

while(!(input = sc.next().trim()).equals(""))

{

this.os.write(SerialCommUtils.hexStr2Integer(input));

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

public static void main (String[] args)

{

try {

new MyTwoWaySerialComm().connect("COM4");

} catch (Exception e) {

e.printStackTrace();

}

}

}

SerialCommUtils.java  [对输入输出进行处理的工具类]

/**

* 串行通信工具类

* @author 都颜汗

*

*/

public class SerialCommUtils {

/**

* 将一个十六进制字符串转换成一个十进制数值

* @param hexStr 十六进制字符串,每个字符串包含两个十六进制字符,每个字符串表示一个字节

* @return 十进制整数

*/

public static int hexStr2Integer(String hexStr) {

// 先获取字符串长度

int len = hexStr.length();

int sum = 0;

// 从高位到低位挨个儿计算

for(int i = 0; i < len; i++)

{

// 获取当前位的十六进制数对应的十进制值

int curNum = SerialCommUtils.hexChar2Integer(hexStr.charAt(i));

sum += curNum * Math.pow(16, len-i-1);

}

return sum;

}

/**

* 将一个十六进制字符转换成一个十进制数值

* @param c 一个十六进制字符

* @return c这个十六进制字符对应的十进制整数

*/

public static int hexChar2Integer(char c){

if(c >= '0' && c <= '9')

{

return c-48;

}

else if((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))

{

if(c >= 'a')

return c-87;

else

return c-55;

}

return -1;

}

/**

* 将一个十进制数值转成一个十六进制字符

* @param n 是一个十进制数值,合理范围为0~15

* @return返回一个十六进制字符

*/

public static char int2HexChar(int n)

{

if(n <=9 && n >= 0)

{

return (char)(n+48);

}

else if(n > 9 && n <= 15)

{

switch (n) {

case 10: return 'A';

case 11: return 'B';

case 12: return 'C';

case 13: return 'D';

case 14: return 'E';

case 15: return 'F';

default:

break;

}

}

return '■';

}

/**

* 将一个字节转换成一个字符串

* @param n 是待转换的字节

* @return返回一个包含两个十六进制字符的字符串

*/

public static String byte2HexStr(byte b)

{

// 首先,从设备返回的字节可能是个负值,先将其转换成一个不带符号的正值,放到int中保存

int tmp = b & 0xFF; // 这里利用按位与操作

int before = tmp/16;

int after = tmp%16;

String ret = "" + SerialCommUtils.int2HexChar(before) + SerialCommUtils.int2HexChar(after);

return ret;

}

}

程序运行示例:

0818b9ca8b590ca3270a3433284dd417.png

本文参考文档&资源:

转载地址:http://olnuo.baihongyu.com/

你可能感兴趣的文章
ZOJ 2412 Farm Irrigation
查看>>
C++语言基础(19)-模板的显式具体化
查看>>
[轉]JavaScript获取HTML DOM父,子,临近节点
查看>>
深入理解JavaScript系列(18):面向对象编程之ECMAScript实现
查看>>
如何改变Android tab 的高度和字体大小
查看>>
hdu 2853
查看>>
VS2013 MVC Web项目使用内置的IISExpress支持局域网内部机器(手机、PC)访问、调试...
查看>>
Vue.js常用指令:v-show和v-if
查看>>
java自定义接口
查看>>
Codeforces Round #152 (Div. 2) B题 数论
查看>>
马云马化腾等大佬,是如何看待区块链的?
查看>>
10倍于行业增速!海尔冰箱套圈引领
查看>>
Java集合总结【面试题+脑图】,将知识点一网打尽!
查看>>
java基础(十) 数组类型
查看>>
小程序 Canvas绘图不同尺寸设备 UI兼容的两个解决方案
查看>>
产品规划,你通常规划多久的时间线?
查看>>
Android-MVP架构
查看>>
HTML5前端教程分享:CSS浏览器常见兼容问题
查看>>
Material Design之AppBarLayout
查看>>
让mysql不能为空的字段为空时也能插入
查看>>