[文章信息]?
?
作者:?ptboy?
時間:?2003-03-17?
出處:?天極論壇?
責(zé)任編輯:? ?
?
[文章導(dǎo)讀]?
?
本文介紹了一個簡單的通過串口實現(xiàn)全雙工通訊的Java類庫,該類庫大大的簡化了對串口進行操作的過程?
?一個嵌入式系統(tǒng)通常需要通過串口與其主控系統(tǒng)進行全雙工通訊,譬如一個流水線控制系統(tǒng)需要不斷的接受從主控系統(tǒng)發(fā)送來的查詢和控制信息,并將執(zhí)行結(jié)果或查詢結(jié)果發(fā)送回主控系統(tǒng)。本文介紹了一個簡單的通過串口實現(xiàn)全雙工通訊的Java類庫,該類庫大大的簡化了對串口進行操作的過程。
本類庫主要包括:SerialBean.java?(與其他應(yīng)用程序的接口),?SerialBuffer.java(用來保存從串口所接收數(shù)據(jù)的緩沖區(qū)),?ReadSerial.java?(從串口讀取數(shù)據(jù)的程序)。另外本類庫還提供了一個例程SerialExample.java?作為示范。在下面的內(nèi)容中將逐一對這幾個部分進行詳細介紹。
1.?SerialBean
SerialBean是本類庫與其他應(yīng)用程序的接口。該類庫中定義了SerialBean的構(gòu)造方法以及初始化串口,從串口讀取數(shù)據(jù),往串口寫入數(shù)據(jù)以及關(guān)閉串口的函數(shù)。具體介紹如下:
public?SerialBean(int?PortID)?
本函數(shù)構(gòu)造一個指向特定串口的SerialBean,該串口由參數(shù)PortID所指定。PortID?=?1?表示COM1,PortID?=?2?表示COM2,由此類推。
public?int?Initialize()?
本函數(shù)初始化所指定的串口并返回初始化結(jié)果。如果初始化成功返回1,否則返回-1。初始化的結(jié)果是該串口被SerialBean獨占性使用,其參數(shù)被設(shè)置為9600,?N,?8,?1。如果串口被成功初始化,則打開一個進程讀取從串口傳入的數(shù)據(jù)并將其保存在緩沖區(qū)中。
public?String?ReadPort(int?Length)?
本函數(shù)從串口(緩沖區(qū))中讀取指定長度的一個字符串。參數(shù)Length指定所返回字符串的長度。
public?void?WritePort(String?Msg)?
本函數(shù)向串口發(fā)送一個字符串。參數(shù)Msg是需要發(fā)送的字符串。
public?void?ClosePort()?
本函數(shù)停止串口檢測進程并關(guān)閉串口。
SerialBean的源代碼如下:
package?serial;
import?java.io.*;
import?java.util.*;
import?javax.comm.*;
/**
*
*?This?bean?provides?some?basic?functions?to?implement?full?dulplex
*?information?exchange?through?the?srial?port.
*
*/
public?class?SerialBean
{
static?String?PortName;
CommPortIdentifier?portId;
SerialPort?serialPort;
static?OutputStream?out;
static?InputStream?in;
SerialBuffer?SB;
ReadSerial?RT;
/**
*
*?Constructor
*
*?@param?PortID?the?ID?of?the?serial?to?be?used.?1?for?COM1,
*?2?for?COM2,?etc.
*
*/
public?SerialBean(int?PortID)
{
PortName?=?"COM"?+?PortID;
}
/**
*
*?This?function?initialize?the?serial?port?for?communication.?It?starts?a
*?thread?which?consistently?monitors?the?serial?port.?Any?signal?captured
*?from?the?serial?port?is?stored?into?a?buffer?area.
*
*/
public?int?Initialize()
{
int?InitSuccess?=?1;
int?InitFail?=?-1;
try
{
portId?=?CommPortIdentifier.getPortIdentifier(PortName);
try
{
serialPort?=?(SerialPort)
portId.open("Serial_Communication",?2000);
}?catch?(PortInUseException?e)
{
return?InitFail;
}
//Use?InputStream?in?to?read?from?the?serial?port,?and?OutputStream
//out?to?write?to?the?serial?port.
try
{
in?=?serialPort.getInputStream();
out?=?serialPort.getOutputStream();
}?catch?(IOException?e)
{
return?InitFail;
}
//Initialize?the?communication?parameters?to?9600,?8,?1,?none.
try
{
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
}?catch?(UnsupportedCommOperationException?e)
{
return?InitFail;
}
}?catch?(NoSuchPortException?e)
{
return?InitFail;
}
//?when?successfully?open?the?serial?port,?create?a?new?serial?buffer,
//?then?create?a?thread?that?consistently?accepts?incoming?signals?from
//?the?serial?port.?Incoming?signals?are?stored?in?the?serial?buffer.
SB?=?new?SerialBuffer();
RT?=?new?ReadSerial(SB,?in);
RT.start();
//?return?success?information
return?InitSuccess;
}
/**
*
*?This?function?returns?a?string?with?a?certain?length?from?the?incoming
*?messages.
*
*?@param?Length?The?length?of?the?string?to?be?returned.
*
*/
public?String?ReadPort(int?Length)
{
String?Msg;
Msg?=?SB.GetMsg(Length);
return?Msg;
}
/**
*
*?This?function?sends?a?message?through?the?serial?port.
*
*?@param?Msg?The?string?to?be?sent.
*
*/
public?void?WritePort(String?Msg)
{
int?c;
try
{
for?(int?i?=?0;?i?<?Msg.length();?i++)
out.write(Msg.charAt(i));
}?catch?(IOException?e)?{}
}
/**
*
*?This?function?closes?the?serial?port?in?use.
*
*/
public?void?ClosePort()
{
RT.stop();
serialPort.close();
}
}
?
2.?SerialBuffer
SerialBuffer是本類庫中所定義的串口緩沖區(qū),它定義了往該緩沖區(qū)中寫入數(shù)據(jù)和從該緩沖區(qū)中讀取數(shù)據(jù)所需要的函數(shù)。
public?synchronized?String?GetMsg(int?Length)?
本函數(shù)從串口(緩沖區(qū))中讀取指定長度的一個字符串。參數(shù)Length指定所返回字符串的長度。
public?synchronized?void?PutChar(int?c)?
本函數(shù)望串口緩沖區(qū)中寫入一個字符,參數(shù)c?是需要寫入的字符。
在往緩沖區(qū)寫入數(shù)據(jù)或者是從緩沖區(qū)讀取數(shù)據(jù)的時候,必須保證數(shù)據(jù)的同步,因此GetMsg和PutChar函數(shù)均被聲明為synchronized并在具體實現(xiàn)中采措施實現(xiàn)的數(shù)據(jù)的同步。
SerialBuffer的源代碼如下:
package?serial;
/**
*
*?This?class?implements?the?buffer?area?to?store?incoming?data?from?the?serial
*?port.
*
*/
public?class?SerialBuffer
{
private?String?Content?=?"";
private?String?CurrentMsg,?TempContent;
private?boolean?available?=?false;
private?int?LengthNeeded?=?1;
/**
*
*?This?function?returns?a?string?with?a?certain?length?from?the?incoming
*?messages.
*
*?@param?Length?The?length?of?the?string?to?be?returned.
*
*/
public?synchronized?String?GetMsg(int?Length)
{
LengthNeeded?=?Length;
notifyAll();
if?(LengthNeeded?>?Content.length())
{
available?=?false;
while?(available?==?false)
{
try
{
wait();
}?catch?(InterruptedException?e)?{?}
}
}
CurrentMsg?=?Content.substring(0,?LengthNeeded);
TempContent?=?Content.substring(LengthNeeded);
Content?=?TempContent;
LengthNeeded?=?1;
notifyAll();
return?CurrentMsg;
}
/**
*
*?This?function?stores?a?character?captured?from?the?serial?port?to?the
*?buffer?area.
*
*?@param?t?The?char?value?of?the?character?to?be?stored.
*
*/
public?synchronized?void?PutChar(int?c)
{
Character?d?=?new?Character((char)?c);
Content?=?Content.concat(d.toString());
if?(LengthNeeded?<?Content.length())
{
available?=?true;
}
notifyAll();
}
}
?
3.?ReadSerial
ReadSerial是一個進程,它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
public?ReadSerial(SerialBuffer?SB,?InputStream?Port)?
本函數(shù)構(gòu)造一個ReadSerial進程,參數(shù)SB指定存放傳入數(shù)據(jù)的緩沖區(qū),參數(shù)Port指定從串口所接收的數(shù)據(jù)流。
public?void?run()?
ReadSerial進程的主函數(shù),它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
ReadSerial的源代碼如下:
package?serial;
import?java.io.*;
/**
*
*?This?class?reads?message?from?the?specific?serial?port?and?save
*?the?message?to?the?serial?buffer.
*
*/
public?class?ReadSerial?extends?Thread
{
private?SerialBuffer?ComBuffer;
private?InputStream?ComPort;
/**
*
*?Constructor
*
*?@param?SB?The?buffer?to?save?the?incoming?messages.
*?@param?Port?The?InputStream?from?the?specific?serial?port.
*
*/
public?ReadSerial(SerialBuffer?SB,?InputStream?Port)
{
ComBuffer?=?SB;
ComPort?=?Port;
}
public?void?run()
{
int?c;
try
{
while?(true)
{
c?=?ComPort.read();
ComBuffer.PutChar(c);
}
}?catch?(IOException?e)?{}
}
}?
4.?SerialExample
SerialExample是本類庫所提供的一個例程。它所實現(xiàn)的功能是打開串口COM1,對其進行初始化,從串口讀取信息對其進行處理后將處理結(jié)果發(fā)送到串口。
import?serial.*;
import?java.io.*;
/**
*
*?This?is?an?example?of?how?to?use?the?SerialBean.?It?opens?COM1?and?reads
*?six?messages?with?different?length?form?the?serial?port.
*
*/
class?SerialExample
{
public?static?void?main(String[]?args)
{
//TO?DO:?Add?your?JAVA?codes?here
SerialBean?SB?=?new?SerialBean(1);
String?Msg;
SB.Initialize();
for?(int?i?=?5;?i?<=?10;?i++)
{
Msg?=?SB.ReadPort(i);
SB.WritePort("Reply:?"?+?Msg);
}
SB.ClosePort();
}
}
?
5.?編譯與調(diào)試
本類庫中使用了Java?Communication?API?(javax.comm)。這是一個Java擴展類庫,并不包括在標準的Java?SDK當中。如果你尚未安裝這個擴展類庫的話,你應(yīng)該從Sun公司的Java站點下載這個類庫并將其安裝在你的系統(tǒng)上。在所下載的包里面包括一個安裝說明,如果你沒有正確安裝這個類庫及其運行環(huán)境的話,運行這個程序的時候你會找不到串口。
正確安裝Java?Communication?API并將上述程序編譯通過以后,你可以按如下方法測試這個程序。如果你只有一臺機器,你可以利用一條RS-232電纜將COM1和COM2連接起來,在COM1上運行SerialExample,在COM2上運行Windows提供的超級終端程序。如果你有兩臺機器的話,你可以利用一條RS-232電纜將兩臺機器的COM1(或者是COM2)連接起來,在一端運行例程,另外一端運行Windows提供的超級終端程序。如果有必要的
話,可以對SerialExample中所聲明的串口進行相應(yīng)改動。
本程序在Windows?2000?+?Java?SDK?1.3環(huán)境下編譯通過并成功運行。
posted on 2007-02-01 15:24
OMG 閱讀(638)
評論(1) 編輯 收藏 所屬分類:
JavaX