查看: 1805|回复: 0

[Java代码] Java实现的串口通信功能示例

发表于 2018-2-25 08:00:00

本文实例讲述了Java实现的串口通信功能。分享给大家供大家参考,具体如下:

用Java实现串口通信(windows系统下),需要用到sun提供的串口包 javacomm20-win32.zip。其中要用到三个文件,配置如下:

1.comm.jar放置到 JAVA_HOME/jre/lib/ext;
2.win32com.dll放置到 JAVA_HOME/bin;
3.javax.comm.properties 两个地方都要放
jre/lib(也就是在JAVA文件夹下的jre)
JAVA_HOME/jre/lib

说一下我应用的环境。电子秤称重时,计算机通过串口给称重控制显示器发送一次命令“R”,控制显示器则发送一次重量数据给串口,计算机再读取将数据显示在网页上。这样就构成了一个实时称重系统。

读写串口的代码如下:

  1. package com.chengzhong.tools;
  2. import java.io.*;
  3. import javax.comm.CommPortIdentifier;
  4. import javax.comm.*;
  5. /**
  6. *
  7. * This bean provides some basic functions to implement full duplex
  8. * information exchange through the serial port.
  9. *
  10. */
  11. public class SerialBean
  12. {
  13. public static String PortName;
  14. public static CommPortIdentifier portId;
  15. public static SerialPort serialPort;
  16. public static OutputStream out;
  17. public static InputStream in;
  18. //保存读数结果
  19. public static String result="";
  20. public static int openSignal=1;
  21. /**
  22. *
  23. * Constructor
  24. *
  25. * @param PortID the ID of the serial to be used. 1 for COM1,
  26. * 2 for COM2, etc.
  27. *
  28. */
  29. public SerialBean(int PortID)
  30. {
  31. PortName = "COM" +PortID;
  32. }
  33. /**
  34. *
  35. * This function initialize the serial port for communication. It starts a
  36. * thread which consistently monitors the serial port. Any signal captured
  37. * from the serial port is stored into a buffer area.
  38. *
  39. */
  40. public int Initialize()
  41. {
  42. openSignal=1;
  43. try
  44. {
  45. portId = CommPortIdentifier.getPortIdentifier(PortName);
  46. try
  47. {
  48. serialPort = (SerialPort)
  49. portId.open("Serial_Communication", 2000);
  50. } catch (PortInUseException e)
  51. {
  52. if(!SerialBean.portId.getCurrentOwner().equals("Serial_Communication"))
  53. {
  54. openSignal=2; //该串口被其它程序占用
  55. }else if(SerialBean.portId.getCurrentOwner().equals("Serial_Communication")){
  56. openSignal=1;
  57. return openSignal;
  58. }
  59. return openSignal;
  60. }
  61. //Use InputStream in to read from the serial port, and OutputStream
  62. //out to write to the serial port.
  63. try
  64. {
  65. in = serialPort.getInputStream();
  66. out = serialPort.getOutputStream();
  67. } catch (IOException e)
  68. {
  69. openSignal=3; //输入输出流错误
  70. return openSignal;
  71. }
  72. //Initialize the communication parameters to 9600, 8, 1, none.
  73. try
  74. {
  75. serialPort.setSerialPortParams(9600,
  76. SerialPort.DATABITS_8,
  77. SerialPort.STOPBITS_1,
  78. SerialPort.PARITY_NONE);
  79. } catch (UnsupportedCommOperationException e)
  80. {
  81. openSignal=4; //参数不正确
  82. return openSignal;
  83. }
  84. } catch (NoSuchPortException e)
  85. {
  86. portId=null;
  87. openSignal=5; //没有该串口
  88. return openSignal;
  89. }
  90. // when successfully open the serial port, create a new serial buffer,
  91. // then create a thread that consistently accepts incoming signals from
  92. // the serial port. Incoming signals are stored in the serial buffer.
  93. // return success information
  94. return openSignal;
  95. }
  96. /**
  97. *
  98. * This function returns a string with a certain length from the incoming
  99. * messages.
  100. *
  101. * @param Length The length of the string to be returned.
  102. *
  103. */
  104. public static void ReadPort()
  105. {
  106. SerialBean.result="";
  107. int c;
  108. try {
  109. if(in!=null){
  110. while(in.available()>0)
  111. {
  112. c = in.read();
  113. Character d = new Character((char) c);
  114. SerialBean.result=SerialBean.result.concat(d.toString());
  115. }
  116. }
  117. } catch (IOException e) {
  118. // TODO Auto-generated catch block
  119. e.printStackTrace();
  120. }
  121. }
  122. /**
  123. *
  124. * This function sends a message through the serial port.
  125. *
  126. * @param Msg The string to be sent.
  127. *
  128. */
  129. public static void WritePort(String Msg)
  130. {
  131. try
  132. {
  133. if(out!=null){
  134. for (int i = 0; i < Msg.length(); i++)
  135. out.write(Msg.charAt(i));
  136. }
  137. } catch (IOException e) {
  138. return;
  139. }
  140. }
  141. /**
  142. *
  143. * This function closes the serial port in use.
  144. *
  145. */
  146. public void ClosePort()
  147. {
  148. serialPort.close();
  149. }
  150. }
复制代码

这样通过 SerialBean.result 就可得到读数结果。

至于把数据放到网页上,就要用到Ajax了,这里用到了一个Ajax框架dwr, dwr类Put.java 如下:

  1. package com.chengzhong.dwr;
  2. import java.io.IOException;
  3. import com.chengzhong.tools.Arith;
  4. import com.chengzhong.tools.SerialBean;
  5. public class Put {
  6. //2011.9.17
  7. public String write(){
  8. //发送指令R,仪器发送一次净重数据
  9. SerialBean.WritePort("R");
  10. //读取数据
  11. SerialBean.ReadPort();
  12. String temp=SerialBean.result.trim(); //我这里temp是形如 wn125.000kg 的数据
  13. if(!temp.equals("") && temp.length()==11)
  14. {
  15. return (change(temp)).toString();
  16. }else{
  17. return "";
  18. }
  19. }
  20. //响应开始称重
  21. public String startWeight(String num){
  22. int n=Integer.parseInt(num.trim());
  23. SerialBean SB = new SerialBean(n);
  24. SB.Initialize();
  25. return SerialBean.openSignal+""; //返回初始化信息
  26. }
  27. //响应停止称重
  28. public void endWeight(){
  29. try {
  30. //关闭输入、输出流
  31. SerialBean.in.close();
  32. SerialBean.out.close();
  33. } catch (IOException e) {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }
  37. if(SerialBean.serialPort!=null){
  38. SerialBean.serialPort.close(); //关闭串口
  39. }
  40. SerialBean.serialPort=null;
  41. SerialBean.portId=null;
  42. SerialBean.result="";
  43. }
  44. /**
  45. * 将形如 wn125.000kg 格式的重量转换为 125.000 (kg)(四舍五入,小数点后保留两位)
  46. */
  47. public String change(String source){
  48. Double result=0.0;
  49. String s1=source.substring(2,9);
  50. try{
  51. result=Double.parseDouble(s1);
  52. result=Arith.round(result,2);
  53. }catch(Exception e){
  54. e.printStackTrace();
  55. return "";
  56. }
  57. return result.toString();
  58. }
  59. }
复制代码

注:Arith.java是一个java 的高精度计算文件。

  1. package com.chengzhong.tools;
  2. import java.math.BigDecimal;
  3. /**
  4. * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
  5. * 确的浮点数运算,包括加减乘除和四舍五入。
  6. */
  7. public class Arith{
  8. //默认除法运算精度
  9. private static final int DEF_DIV_SCALE = 10;
  10. //这个类不能实例化
  11. private Arith(){
  12. }
  13. /**
  14. * 提供精确的加法运算。
  15. * @param v1 被加数
  16. * @param v2 加数
  17. * @return 两个参数的和
  18. */
  19. public static double add(double v1,double v2){
  20. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  21. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  22. return b1.add(b2).doubleValue();
  23. }
  24. /**
  25. * 提供精确的减法运算。
  26. * @param v1 被减数
  27. * @param v2 减数
  28. * @return 两个参数的差
  29. */
  30. public static double sub(double v1,double v2){
  31. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  32. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  33. return b1.subtract(b2).doubleValue();
  34. }
  35. /**
  36. * 提供精确的乘法运算。
  37. * @param v1 被乘数
  38. * @param v2 乘数
  39. * @return 两个参数的积
  40. */
  41. public static double mul(double v1,double v2){
  42. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  43. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  44. return b1.multiply(b2).doubleValue();
  45. }
  46. /**
  47. * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
  48. * 小数点以后10位,以后的数字四舍五入。
  49. * @param v1 被除数
  50. * @param v2 除数
  51. * @return 两个参数的商
  52. */
  53. public static double div(double v1,double v2){
  54. return div(v1,v2,DEF_DIV_SCALE);
  55. }
  56. /**
  57. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
  58. * 定精度,以后的数字四舍五入。
  59. * @param v1 被除数
  60. * @param v2 除数
  61. * @param scale 表示表示需要精确到小数点以后几位。
  62. * @return 两个参数的商
  63. */
  64. public static double div(double v1,double v2,int scale){
  65. if(scale<0){
  66. throw new IllegalArgumentException(
  67. "The scale must be a positive integer or zero");
  68. }
  69. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  70. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  71. return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
  72. }
  73. /**
  74. * 提供精确的小数位四舍五入处理。
  75. * @param v 需要四舍五入的数字
  76. * @param scale 小数点后保留几位
  77. * @return 四舍五入后的结果
  78. */
  79. public static double round(double v,int scale){
  80. if(scale<0){
  81. throw new IllegalArgumentException(
  82. "The scale must be a positive integer or zero");
  83. }
  84. BigDecimal b = new BigDecimal(Double.toString(v));
  85. BigDecimal one = new BigDecimal("1");
  86. return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
  87. }
  88. }
复制代码

网页页面上:

  1. <script type="text/javascript" src="/ChengZhong/dwr/engine.js"></script>
  2. <script type="text/javascript" src="/ChengZhong/dwr/util.js"></script>
  3. <script type='text/javascript' src='/ChengZhong/dwr/interface/ss.js' ></script>
  4. <script type='text/javascript' >
  5. var ID;
  6. function begin(){
  7. ID=window.setInterval('get()',500); //每隔半秒自动调用 get(),取得毛重数据填入文本框中
  8. }
  9. function get()
  10. {
  11. ss.write(readIt); //调用dwr类 Put.java 中的write方法
  12. }
  13. function readIt(Data){
  14. if(Data!=null && Data!="")
  15. {
  16. document.getElementById("mzBF").value=Data;
  17. }
  18. }
  19. </script>
复制代码

dwr的使用就不说了

更多关于java相关内容感兴趣的读者可查看本站专题:《Java Socket编程技巧总结》、《Java文件与目录操作技巧汇总》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。



回复

使用道具 举报