摘 要: 介紹了Java實現串口通信編程的技術處理。著重就串口通信的連接、數據緩沖區資源的多線程訪問控制以及數據讀取中的超時控制等問題進行了詳細討論,有效地實現了主機與下位單片機之間的數據傳遞。該通信方式已用于基于工控機的絕緣電阻檢測應用中。
關鍵詞: Java;串口通信;多線程;comm包
嵌入式系統或傳感器網絡的很多應用都需要通過PC機與嵌入式設備或傳感器節點進行通信。其中,最常用的接口就是RS-232串口。串口通信可以是上位機與下位機之間的直接串口通信,也可以是在串口上連接無線通信模塊,通過串口進行無線通信。RS-232-C是在1970年由美國電子工業協會(EIA)聯合貝爾系統、調制解調器廠家及計算機終端生產廠家共同制定的用于串行通信的標準。RS-232是一個全雙工的通信協議,它可以同時進行數據接收和發送的工作。
Java實現串口通信的編程方式通常采用SUN發布的串口通信API,它是以獨立jar包形式提供的一個標準擴展。其中包含3個文件:comm.jar提供了通信用的java API;win32com.dll提供了串口通信的本地驅動接口;javax.comm.properties是這個驅動的類配置文件。Java讀寫串口過程主要是調用javax.comm包中的API函數。在javax.comm包中,串口的讀寫操作是數據流形式,串口初始化后,通過CommPort類的getInputStream()和getOutputStream()方法即可分別取得端口的輸入流和輸出流。
串口通信應用程序有兩種模式:一種是實現SerialPortEventListener接口,通過監聽串口事件并作相應處理;另一種就是建立一個獨立的接收線程負責數據的接收。本文采用的是后一種方式。
本文的串口通信是上位工控機與下位單片機之間的通信。工控機通過觸摸屏方式來使用系統,下位單片機連接絕緣檢測筆實現絕緣電阻的檢測,并將檢測過程的結果發送給上位機。本文僅介紹主機方的Java串口通信編程處理技術,如圖1所示的虛線上方部分,包含消息接收線程、Swing事件驅動應用界面、消息緩沖區、消息分析處理程序。其中:①在圖形應用界面中通過用戶的操作來觸發事件實現與單片機的通信;②主機通過串口向單片機發送啟動檢測的消息;③單片機在收到消息后,將啟動檢測,并將傳感器獲取的數據通過串口發送給主機作為響應;④數據接收線程將收到的數據放到一個緩存中;⑤消息分析處理程序從緩存中獲取數據并進行分析處理。主機和單片機間每次通信傳送1 B。
1 串口緩沖區的控制
串口緩沖區(SerialBuffer類)實現從串口接收到的一個完整消息的封裝,本系統的消息按協議設計為11 B,其中包含消息的起始標記、識別標識和數據字節。消息緩沖區是消息接收線程和消息分析處理Bean之間的橋梁,只有在接收到一條完整的消息后才可以進行消息的分析解析。串口緩沖區安排有3個重要屬性:
(1)Content屬性:存放11 B的消息;
(2)Available屬性:標識消息是否可用;
(3)LengthNeeded屬性:統計收到的消息字節長度。
該類還定義了兩個重要方法:(1)public synchronized byte[] GetMsg():從緩沖區讀取消息;(2)public synchronized void putbyte(int c):寫一個字節到緩沖區。方法定義中均含有synchronized關鍵詞,也就是要使用這兩個方法必須取得緩沖區的對象鎖,從而實現對緩沖區這個共享資源的訪問互斥操作。
2 消息接收線程
消息接收線程(ReadSerial類)循環從串口讀取數據并將其存放到消息緩沖區中,串口無數據或緩沖區滿時它將處于資源等待狀態。以下為線程的run方法代碼:
public void run() {
try {
while (true) {
int c = ComPort.read();
//從串口讀1 B
ComBuffer.putbyte(c);
//將數據放入消息緩沖區
}
} catch (IOException e) { }
}
3 消息分析處理Bean
消息分析處理Bean(SerialBean類)是Swing界面處理程序對串口進行操作訪問的調用接口。其中封裝有3個方法:Initialize方法實現串口的初始化;ReadPort()方法從消息緩沖區讀消息并進行分析;WritePort(byte[] Msg)方法寫消息到串口。串口初始化只執行1次,包括如下工作:
(1)打開串口
portId=CommPortIdentifier.getPortIdentifier(串口名);
serialPort=(SerialPort)portId.open(“串口所有者名稱”,超時等待時間);
(2)獲取串口的輸入/輸出流
in=serialPort.getInputStream();
out=serialPort.getOutputStream();
(3)設置串口參數
serialPort.setSerialPortParams(9 600,SerialPort.
DATABITS_8,
SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
(4)創建消息緩沖區對象
SB=new SerialBuffer();
(5)創建并啟動消息接受線程
RT=new ReadSerial(SB, in);
RT.start();
4 串口通信驅動程序的裝載
串口驅動程序的裝載是實現串口初始化的前提,如果程序在Spring STS開發環境中運行,會從JDK的運行環境裝載驅動程序。這種情況下,必須事先將comm.jar拷貝到JDK安裝目錄的jre\lib\ext 目錄下,將win32com.dll 拷貝到JDK安裝目錄的jre\bin目錄下,將javax.comm.properties拷貝到JDK安裝目錄的jre\lib目錄[2]下。
如果將開發的應用導出為獨立的可運行的JAR文件,則必須將以上的3個文件安排到應用工程的src所在目錄路徑下,并在程序中用如下程序代碼進行裝載。
Import javax.comm.CommDriver;
import javax.swing.JOptionPane;
public class CurrentStatus {
public static SerialBean SB ; //消息分析處理Bean
public static void init(int n){ //n為串口編號
String driverName=“com.sun.comm.Win32Driver”;
CommDriver driver=null;
try {
System.loadLibrary(“win32com”); //裝載DLL
driver=(CommDriver)Class.forName
(driverName).newInstance();
}
catch(Exception e1){ e1.printStackTrace();}
driver.initialize(); //驅動程序初始化
SB=new SerialBean(n);
if (SB.Initialize()==-1)
JOptionPane.showMessageDialog(null,”串口初始
化錯誤”);
}
}
這樣,在程序中可通過執行init方法實現具體串口的通信初始化。例如:
CurrentStatus.init(1); //初始化串口1
5 在圖形界面中實現通信調用
在電氣設備的絕緣電阻檢測應用中,圖2為應用界面。當用戶點擊某個檢測項對應的按鈕時,通過注冊按鈕點擊事件觸發執行代碼,將通過消息分析處理Bean的WritePort方法給串口發送檢測命令,并利用循環等待讀取來自單片機的檢測結果。由于單片機在檢測過程中將發送系列檢測結果,因此,要循環讀取數據,直到超過一定時間無數據可讀或接收到結束標志的消息為止。具體工作過程如圖3所示。其中,數據庫的訪問處理采用Spring的JdbcTemplate類提供的功能實現。
本文介紹了Java實現串口通信編程的典型編程處理要點,可有效地實現上位工控機與單片機之間的數據通信。系統通過多線程及對消息緩沖區資源的訪問控制、延時等待控制等措施,保證了上下位機之間通信的可靠傳遞。實際應用中要根據具體的消息格式來組織通信過程中數據的分析處理。
參考文獻
[1] 吳金鋒,劉偉平,黃紅斌.Java串口通信數據采控系統的設計與實現[J].微計算機信息,2010(10).
[2] 唐未香.Java程序與ZigBee串口通訊的實現[J].福建電腦,2010(5).