java串口通讯实例

小咪咪 2022-07-30 14:29 310阅读 0赞

现在一般的电脑都没有串口端口的了,所以还是用虚拟的串口来做测试吧。

我们用 VSPD(Virtual Serial Port Driver) 这个软件建立两个虚拟串口,COM2和COM3,名字随便起,VSPD对虚拟串口的序号没有限制,理论上可以创建无数个。

串口通信类如下:

  1. package org.serial;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.util.Enumeration;
  8. import java.util.TooManyListenersException;
  9. import javax.comm.CommPortIdentifier;
  10. import javax.comm.PortInUseException;
  11. import javax.comm.SerialPort;
  12. import javax.comm.SerialPortEvent;
  13. import javax.comm.SerialPortEventListener;
  14. /**
  15. * @项目名称 :illegalsms
  16. * @文件名称 :SerialPort.java
  17. * @所在包 :org.serial
  18. * @功能描述 :
  19. * 串口类
  20. * @创建者 :集成显卡 1053214511@qq.com
  21. * @创建日期 :2012-9-13
  22. * @修改记录 :
  23. */
  24. public class DSerialPort implements Runnable, SerialPortEventListener {
  25. private String appName = "串口通讯测试[集成显卡2012]";
  26. private int timeout = 2000;//open 端口时的等待时间
  27. private int threadTime = 0;
  28. private CommPortIdentifier commPort;
  29. private SerialPort serialPort;
  30. private InputStream inputStream;
  31. private OutputStream outputStream;
  32. /**
  33. * @方法名称 :listPort
  34. * @功能描述 :列出所有可用的串口
  35. * @返回值类型 :void
  36. */
  37. @SuppressWarnings("rawtypes")
  38. public void listPort(){
  39. CommPortIdentifier cpid;
  40. Enumeration en = CommPortIdentifier.getPortIdentifiers();
  41. System.out.println("now to list all Port of this PC:" +en);
  42. while(en.hasMoreElements()){
  43. cpid = (CommPortIdentifier)en.nextElement();
  44. if(cpid.getPortType() == CommPortIdentifier.PORT_SERIAL){
  45. System.out.println(cpid.getName() + ", " + cpid.getCurrentOwner());
  46. }
  47. }
  48. }
  49. /**
  50. * @方法名称 :selectPort
  51. * @功能描述 :选择一个端口,比如:COM1
  52. * @返回值类型 :void
  53. * @param portName
  54. */
  55. @SuppressWarnings("rawtypes")
  56. public void selectPort(String portName){
  57. this.commPort = null;
  58. CommPortIdentifier cpid;
  59. Enumeration en = CommPortIdentifier.getPortIdentifiers();
  60. while(en.hasMoreElements()){
  61. cpid = (CommPortIdentifier)en.nextElement();
  62. if(cpid.getPortType() == CommPortIdentifier.PORT_SERIAL
  63. && cpid.getName().equals(portName)){
  64. this.commPort = cpid;
  65. break;
  66. }
  67. }
  68. openPort();
  69. }
  70. /**
  71. * @方法名称 :openPort
  72. * @功能描述 :打开SerialPort
  73. * @返回值类型 :void
  74. */
  75. private void openPort(){
  76. if(commPort == null)
  77. log(String.format("无法找到名字为'%1$s'的串口!", commPort.getName()));
  78. else{
  79. log("端口选择成功,当前端口:"+commPort.getName()+",现在实例化 SerialPort:");
  80. try{
  81. serialPort = (SerialPort)commPort.open(appName, timeout);
  82. log("实例 SerialPort 成功!");
  83. }catch(PortInUseException e){
  84. throw new RuntimeException(String.format("端口'%1$s'正在使用中!",
  85. commPort.getName()));
  86. }
  87. }
  88. }
  89. /**
  90. * @方法名称 :checkPort
  91. * @功能描述 :检查端口是否正确连接
  92. * @返回值类型 :void
  93. */
  94. private void checkPort(){
  95. if(commPort == null)
  96. throw new RuntimeException("没有选择端口,请使用 " +
  97. "selectPort(String portName) 方法选择端口");
  98. if(serialPort == null){
  99. throw new RuntimeException("SerialPort 对象无效!");
  100. }
  101. }
  102. /**
  103. * @方法名称 :write
  104. * @功能描述 :向端口发送数据,请在调用此方法前 先选择端口,并确定SerialPort正常打开!
  105. * @返回值类型 :void
  106. * @param message
  107. */
  108. public void write(String message) {
  109. checkPort();
  110. try{
  111. outputStream = new BufferedOutputStream(serialPort.getOutputStream());
  112. }catch(IOException e){
  113. throw new RuntimeException("获取端口的OutputStream出错:"+e.getMessage());
  114. }
  115. try{
  116. outputStream.write(message.getBytes());
  117. log("信息发送成功!");
  118. }catch(IOException e){
  119. throw new RuntimeException("向端口发送信息时出错:"+e.getMessage());
  120. }finally{
  121. try{
  122. outputStream.close();
  123. }catch(Exception e){
  124. }
  125. }
  126. }
  127. /**
  128. * @方法名称 :startRead
  129. * @功能描述 :开始监听从端口中接收的数据
  130. * @返回值类型 :void
  131. * @param time 监听程序的存活时间,单位为秒,0 则是一直监听
  132. */
  133. public void startRead(int time){
  134. checkPort();
  135. try{
  136. inputStream = new BufferedInputStream(serialPort.getInputStream());
  137. }catch(IOException e){
  138. throw new RuntimeException("获取端口的InputStream出错:"+e.getMessage());
  139. }
  140. try{
  141. serialPort.addEventListener(this);
  142. }catch(TooManyListenersException e){
  143. throw new RuntimeException(e.getMessage());
  144. }
  145. serialPort.notifyOnDataAvailable(true);
  146. log(String.format("开始监听来自'%1$s'的数据--------------", commPort.getName()));
  147. if(time > 0){
  148. this.threadTime = time*1000;
  149. Thread t = new Thread(this);
  150. t.start();
  151. log(String.format("监听程序将在%1$d秒后关闭。。。。", threadTime));
  152. }
  153. }
  154. /**
  155. * @方法名称 :close
  156. * @功能描述 :关闭 SerialPort
  157. * @返回值类型 :void
  158. */
  159. public void close(){
  160. serialPort.close();
  161. serialPort = null;
  162. commPort = null;
  163. }
  164. public void log(String msg){
  165. System.out.println(appName+" --> "+msg);
  166. }
  167. /**
  168. * 数据接收的监听处理函数
  169. */
  170. @Override
  171. public void serialEvent(SerialPortEvent arg0) {
  172. switch(arg0.getEventType()){
  173. case SerialPortEvent.BI:/*Break interrupt,通讯中断*/
  174. case SerialPortEvent.OE:/*Overrun error,溢位错误*/
  175. case SerialPortEvent.FE:/*Framing error,传帧错误*/
  176. case SerialPortEvent.PE:/*Parity error,校验错误*/
  177. case SerialPortEvent.CD:/*Carrier detect,载波检测*/
  178. case SerialPortEvent.CTS:/*Clear to send,清除发送*/
  179. case SerialPortEvent.DSR:/*Data set ready,数据设备就绪*/
  180. case SerialPortEvent.RI:/*Ring indicator,响铃指示*/
  181. case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,输出缓冲区清空*/
  182. break;
  183. case SerialPortEvent.DATA_AVAILABLE:/*Data available at the serial port,端口有可用数据。读到缓冲数组,输出到终端*/
  184. byte[] readBuffer = new byte[1024];
  185. String readStr="";
  186. String s2 = "";
  187. try {
  188. while (inputStream.available() > 0) {
  189. inputStream.read(readBuffer);
  190. readStr += new String(readBuffer).trim();
  191. }
  192. s2 = new String(readBuffer).trim();
  193. log("接收到端口返回数据(长度为"+readStr.length()+"):"+readStr);
  194. log(s2);
  195. } catch (IOException e) {
  196. }
  197. }
  198. }
  199. @Override
  200. public void run() {
  201. try{
  202. Thread.sleep(threadTime);
  203. serialPort.close();
  204. log(String.format("端口''监听关闭了!", commPort.getName()));
  205. }catch(Exception e){
  206. e.printStackTrace();
  207. }
  208. }
  209. }

运行测试:

  1. public static void main(String[] args) {
  2. DSerialPort sp = new DSerialPort();
  3. sp.listPort();
  4. sp.selectPort(PORT_NAME);
  5. sp.write("210.36.16.166");
  6. sp.write("2");
  7. sp.startRead(120);
  8. }

上面代码中的 PORT_NAME=”COM2”;

效果如下:

1.用 串口测试工具(附件中有) 打开COM3:

1347614113_9771.jpg

这个是和COM2 连通的

如果在java程序中调用COM2,发送数据,那么COM3会收到,在COM3 中发送的数据,java可以监听到。

2.运行java的main程序:

1347614153_5528.jpg

COM3中收到了信息:

1347614184_9591.jpg

从COM3中得到数据:

1347614211_4460.jpg

发表评论

表情:
评论列表 (有 0 条评论,310人围观)

还没有评论,来说两句吧...

相关阅读

    相关 串口通讯介绍

    串口通讯的物理连接和传输协议,是学习单片机串口编程的基础。 本文参照《深入浅出玩转51单片机》和《零死角玩转STM32》书籍,对通讯以及串口一些基本概念做了详解。 1. 串

    相关 java串口通讯实例

    现在一般的电脑都没有串口端口的了,所以还是用虚拟的串口来做测试吧。 我们用 VSPD(Virtual Serial Port Driver) 这个软件建立两个虚拟串口,COM

    相关 串口通讯之 CRC校验

    一、CRC16简介       循环冗余码CRC检验技术广泛应用于测控及通信领域。CRC计算可以靠专用的硬件来实现,但是对于低成本的微控制器系统,在没有硬件支持下实现CRC