Java程序與串口的通信實現及調試


串口通信原理

  1. 串口通信指串口按位(bit)發送和接收字節。盡管比按字節(byte)的並行通信慢,但是串口可以在使用一根線發送數據的同時用另一根線接收數據。
  2. 串口是計算機上一種非常通用的設備通信協議(不要與通用串行總線Universal SerialBus或者USB混淆)
  3. 典型地,串口用於ASCII碼字符的傳輸。通信使用3根線完成:(1)地線,(2)發送,(3)接收。由於串口通信是異步的,端口能夠在一根線上發送數據同時在另一根線上接收數據。其他線用於握手,但是不是必須的。串口通信最重要的參數是比特率、數據位、停止位和奇偶校驗。對於兩個進行通信的端口,這些參數必須匹配
  4. RS-232(ANSI/EIA-232標准)是IBM-PC及其兼容機上的串行連接標准、RS-422(EIA RS-422-AStandard)是Apple的Macintosh計算機的串口連接標准。RS-485(EIA-485標准)是RS-422的改進。

在一台電腦完成串口通信及調試所需的准備工作

由於筆記本或台式機上基本上都沒有成對的串口提供給我們調試使用,我們就需要下載虛擬串口軟件來實現串口調試。

  1. 下載虛擬串口軟件http://pan.baidu.com/s/1hqhGDbI(這里提供的還是比較好用)。下載安裝完成后先不要急着運行,把壓縮包中的vspdctl.dll文件復制到安裝目錄下如:我的目錄為–>D:\SoftWareInstall\Virtual Serial Port Driver 7.2 替換原有文件即可成功激活。
  2. 打開軟件添加虛擬串口,一般都是成對添加的(添加COM3、COM4)后如圖所示:這里寫圖片描述
  3. 添加完成后到設備管理器中查看,發現多了兩個虛擬串口如圖:這里寫圖片描述至此,創建虛擬串口的工作就全部完成了。
  4. 下載串口調試軟件http://pan.baidu.com/s/1c0AVaXq這里提供的是比較老的調試軟件了,但還是比較好用的哦。直接解壓點擊打開就ok了。
  5. 可以直接先打開兩個調試窗口,分別用來表示COM3和COM4串口。兩個串口的參數一定要設置的一樣才可以正常的收發數據。(若調試可以正常收發數據后,可以關掉一個調試器,而用java程序代替)如圖:這里寫圖片描述

java程序代碼編寫

這一部分將是我們的重點,要與串口通信首先要在項目添加RXTXcomm.jar包(放在項目中的lib目錄下,並添加到build Path中)(win64位下載地址:http://pan.baidu.com/s/1o6zLmTc);另外,還需要將解壓后的rxtxParallel.dll和rxtxSerial.dll兩個文件放在%JAVA_HOME%/jre/bin目錄下,這樣該包才能被正常的加載和調用。

程序代碼解析:

package comm; import java.io.*; import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import gnu.io.*; public class ContinueRead extends Thread implements SerialPortEventListener { // SerialPortEventListener // 監聽器,我的理解是獨立開辟一個線程監聽串口數據 static CommPortIdentifier portId; // 串口通信管理類 static Enumeration<?> portList; // 有效連接上的端口的枚舉 InputStream inputStream; // 從串口來的輸入流 static OutputStream outputStream;// 向串口輸出的流 static SerialPort serialPort; // 串口的引用 // 堵塞隊列用來存放讀到的數據 private BlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>(); @Override /** * SerialPort EventListene 的方法,持續監聽端口上是否有數據流 */ public void serialEvent(SerialPortEvent event) {// switch (event.getEventType()) { case SerialPortEvent.BI: case SerialPortEvent.OE: case SerialPortEvent.FE: case SerialPortEvent.PE: case SerialPortEvent.CD: case SerialPortEvent.CTS: case SerialPortEvent.DSR: case SerialPortEvent.RI: case SerialPortEvent.OUTPUT_BUFFER_EMPTY: break; case SerialPortEvent.DATA_AVAILABLE:// 當有可用數據時讀取數據 byte[] readBuffer = new byte[20]; try { int numBytes = -1; while (inputStream.available() > 0) { numBytes = inputStream.read(readBuffer); if (numBytes > 0) { msgQueue.add(new Date() + "真實收到的數據為:-----" + new String(readBuffer)); readBuffer = new byte[20];// 重新構造緩沖對象,否則有可能會影響接下來接收的數據 } else { msgQueue.add("額------沒有讀到數據"); } } } catch (IOException e) { } break; } } /** * * 通過程序打開COM4串口,設置監聽器以及相關的參數 * * @return 返回1 表示端口打開成功,返回 0表示端口打開失敗 */ public int startComPort() { // 通過串口通信管理類獲得當前連接上的串口列表 portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { // 獲取相應串口對象 portId = (CommPortIdentifier) portList.nextElement(); System.out.println("設備類型:--->" + portId.getPortType()); System.out.println("設備名稱:---->" + portId.getName()); // 判斷端口類型是否為串口 if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { // 判斷如果COM4串口存在,就打開該串口 if (portId.getName().equals("COM4")) { try { // 打開串口名字為COM_4(名字任意),延遲為2毫秒 serialPort = (SerialPort) portId.open("COM_4", 2000); } catch (PortInUseException e) { e.printStackTrace(); return 0; } // 設置當前串口的輸入輸出流 try { inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); } catch (IOException e) { e.printStackTrace(); return 0; } // 給當前串口添加一個監聽器 try { serialPort.addEventListener(this); } catch (TooManyListenersException e) { e.printStackTrace(); return 0; } // 設置監聽器生效,即:當有數據時通知 serialPort.notifyOnDataAvailable(true); // 設置串口的一些讀寫參數 try { // 比特率、數據位、停止位、奇偶校驗位 serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { e.printStackTrace(); return 0; } return 1; } } } return 0; } @Override public void run() { // TODO Auto-generated method stub try { System.out.println("--------------任務處理線程運行了--------------"); while (true) { // 如果堵塞隊列中存在數據就將其輸出 if (msgQueue.size() > 0) { System.out.println(msgQueue.take()); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { ContinueRead cRead = new ContinueRead(); int i = cRead.startComPort(); if (i == 1) { // 啟動線程來處理收到的數據 cRead.start(); try { String st = "哈哈----你好"; System.out.println("發出字節數:" + st.getBytes("gbk").length); outputStream.write(st.getBytes("gbk"), 0, st.getBytes("gbk").length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { return; } } } 

 

java程序與串口通信調試

程序調試截圖:這里寫圖片描述

總結

  1. 串口通信在很多地方都要用到,特別是嵌入式開發、短信模塊開發以及為各種硬件產品定制軟件等都需要用到。其中最經常用的通信協議為RS-232通信協議,要想成為真正的串口通信開發高手就需要全面的了解串口的通信協議(本人還是菜鳥一枚。。。希望高手指點)。
  2. 串口通信的另一個重點在於接收到數據后,如何判斷數據的類型以及有效數據的提取等,這些都需要根據相應的協議進行代碼編寫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM