在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

java串口通信編程實例

PoisonApple ? 來源:網(wǎng)絡(luò)整理 ? 2018-02-01 10:15 ? 次閱讀

串口通信原理

1.串口通信指串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時用另一根線接收數(shù)據(jù)。

2.串口是計算機上一種非常通用的設(shè)備通信協(xié)議(不要與通用串行總線Universal SerialBus或者USB混淆)

3.地,串口用于ASCII碼字符的傳輸。通信使用3根線完成:(1)地線,(2)發(fā)送,(3)接收。由于串口通信是異步的,端口能夠在一根線上發(fā)送數(shù)據(jù)同時在另一根線上接收數(shù)據(jù)。其他線用于握手,但是不是必須的。串口通信最重要的參數(shù)是比特率、數(shù)據(jù)位、停止位和奇偶校驗。對于兩個進(jìn)行通信的端口,這些參數(shù)必須匹配

4.-232(ANSI/EIA-232標(biāo)準(zhǔn))是IBM-PC及其兼容機上的串行連接標(biāo)準(zhǔn)、RS-422(EIA RS-422-AStandard)是Apple的Macintosh計算機的串口連接標(biāo)準(zhǔn)。RS-485(EIA-485標(biāo)準(zhǔn))是RS-422的改進(jìn)。

說到開源,恐怕很少有人不挑大指稱贊。學(xué)生通過開源代碼學(xué)到了知識,程序員通過開源類庫獲得了別人的成功經(jīng)驗及能夠按時完成手頭的工程,商家通過開源軟件賺到了錢……,總之是皆大歡喜。然而開源軟件或類庫的首要缺點就是大多缺乏詳細(xì)的說明文檔和使用的例子,或者就是軟件代碼隨便你用,就是文檔,例子和后期服務(wù)收錢。這也難怪,畢竟就像某個著名NBA球員說的那樣:“我還要養(yǎng)家,所以千萬美元以下的合同別找我談,否則我寧可待業(yè)”。是啊,支持開源的人也要養(yǎng)家,收點錢也不過分。要想既不花錢又學(xué)到知識就只能借助網(wǎng)絡(luò)和了,我只是想拋磚引玉,為開源事業(yè)做出點微薄共獻(xiàn),能為你的工程解決哪怕一個小問題,也就足夠了。

雖然我的這個系列介紹的東西不是什么Web框架,也不是什么開源服務(wù)器,但是我相信,作為一個程序員,什么樣的問題都會遇到。有時候越是簡單的問題反而越棘手;越是小的地方就越是找不到稱手的家伙。只要你不是整天只與“架構(gòu)”、“構(gòu)件”、“框架”打交道的話,相信我所說的東西你一定會用到。

1 串口通信簡介

1.1 常見的Java串口包

1.2 串口包的安裝(Windows下)

2 串口API概覽

2.1 javax.comm.CommPort

2.2 javax.comm.CommPortIdentifier

2.3 javax.comm.SerialPort

2.4 串口API實例

2.4.1 列舉出本機所有可用串口

2.4.2 串口參數(shù)的配置

2.4.3 串口的讀寫

3 串口通信的通用模式及其問題

3.1 事件監(jiān)聽模型

3.2 串口讀數(shù)據(jù)的線程模型

3.3 第三種方法

4 結(jié)束語

1 串口通信簡介

嵌入式系統(tǒng)傳感器網(wǎng)絡(luò)的很多應(yīng)用和測試都需要通過PC機與嵌入式設(shè)備或傳感器節(jié)點進(jìn)行通信。其中,最常用的接口就是RS-232串口和并口(鑒于USB接口的復(fù)雜性以及不需要很大的數(shù)據(jù)傳輸量,USB接口用在這里還是顯得過于奢侈,況且目前除了SUN有一個支持USB的包之外,我還沒有看到其他直接支持USB的Java類庫)。SUN的CommAPI分別提供了對常用的RS232串行端口和IEEE1284并行端口通訊的支持。RS-232-C(又稱EIA RS-232-C,以下簡稱RS232)是在1970年由美國電子工業(yè)協(xié)會(EIA)聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定的用于串行通訊的標(biāo)準(zhǔn)。RS232是一個全雙工的通訊協(xié)議,它可以同時進(jìn)行數(shù)據(jù)接收和發(fā)送的工作。

1.1 常見的Java串口包

目前,常見的Java串口包有SUN在1998年發(fā)布的串口通信API:comm2.0.jar(Windows下)、comm3.0.jar(Linux/Solaris);IBM的串口通信API以及一個開源的實現(xiàn)。鑒于在Windows下SUN的API比較常用以及IBM的實現(xiàn)和SUN的在API層面都是一樣的,那個開源的實現(xiàn)又不像兩家大廠的產(chǎn)品那樣讓人放心,這里就只介紹SUN的串口通信API在Windows平臺下的使用。

1.2 串口包的安裝(Windows下)

到SUN的網(wǎng)站下載javacomm20-win32.zip,包含的東西如下所示:

java串口通信編程實例

按照其使用說明(Readme.html)的說法,要想使用串口包進(jìn)行串口通信,除了設(shè)置好環(huán)境變量之外,還要將win32com.dll復(fù)制到《JDK》/bin目錄下;將comm.jar復(fù)制到《JDK》/lib;把javax.comm.properties也同樣拷貝到《JDK》/lib目錄下。然而在真正運行使用串口包的時候,僅作這些是不夠的。因為通常當(dāng)運行“java MyApp”的時候,是由JRE下的虛擬機啟動MyApp的。而我們只復(fù)制上述文件到JDK相應(yīng)目錄下,所以應(yīng)用程序?qū)崾菊也坏酱凇=鉀Q這個問題的方法很簡單,我們只須將上面提到的文件放到JRE相應(yīng)的目錄下就可以了。

值得注意的是,在網(wǎng)絡(luò)應(yīng)用程序中使用串口API的時候,還會遇到其他更復(fù)雜問題。有興趣的話,你可以查看CSDN社區(qū)中“關(guān)于網(wǎng)頁上Applet用javacomm20讀取客戶端串口的問題”的帖子。

2 串口API概覽

2.1 javax.comm.CommPort

這是用于描述一個被底層系統(tǒng)支持的端口的抽象類。它包含一些高層的IO控制方法,這些方法對于所有不同的通訊端口來說是通用的。SerialPort 和ParallelPort都是它的子類,前者用于控制串行端口而后者用于控這并口,二者對于各自底層的物理端口都有不同的控制方法。這里我們只關(guān)心SerialPort。

2.2 javax.comm.CommPortIdentifier

這個類主要用于對串口進(jìn)行管理和設(shè)置,是對串口進(jìn)行訪問控制的核心類。主要包括以下方法

l 確定是否有可用的通信端口

l 為IO操作打開通信端口

l 決定端口的所有權(quán)

l 處理端口所有權(quán)的爭用

l 管理端口所有權(quán)變化引發(fā)的事件(Event)

2.3 javax.comm.SerialPort

這個類用于描述一個RS-232串行通信端口的底層接口,它定義了串口通信所需的最小功能集。通過它,用戶可以直接對串口進(jìn)行讀、寫及設(shè)置工作。

2.4 串口API實例

大段的文字怎么也不如一個小例子來的清晰,下面我們就一起看一下串口包自帶的例子---SerialDemo中的一小段代碼來加深對串口API核心類的使用方法的認(rèn)識。

2.4.1 列舉出本機所有可用串口

void listPortChoices() {

CommPortIdentifier portId;

Enumeration en = CommPortIdentifier.getPortIdentifiers();

// iterate through the ports.

while (en.hasMoreElements()) {

portId = (CommPortIdentifier) en.nextElement();

if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {

System.out.println(portId.getName());

}

}

portChoice.select(parameters.getPortName());

}

以上代碼可以列舉出當(dāng)前系統(tǒng)所有可用的串口名稱,我的機器上輸出的結(jié)果是COM1和COM3。

2.4.2 串口參數(shù)的配置

串口一般有如下參數(shù)可以在該串口打開以前配置進(jìn)行配置:

java串口通信編程實例

包括波特率,輸入/輸出流控制,數(shù)據(jù)位數(shù),停止位和齊偶校驗。

SerialPort sPort;

try {

sPort.setSerialPortParams(BaudRate,Databits,Stopbits,Parity);

//設(shè)置輸入/輸出控制流

sPort.setFlowControlMode(FlowControlIn | FlowControlOut);

} catch (UnsupportedCommOperationException e) {}

2.4.3 串口的讀寫

對串口讀寫之前需要先打開一個串口:

CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(PortName);

try {

SerialPort sPort = (SerialPort) portId.open(“串口所有者名稱”, 超時等待時間);

} catch (PortInUseException e) {//如果端口被占用就拋出這個異常

throw new SerialConnectionException(e.getMessage());

}

//用于對串口寫數(shù)據(jù)

OutputStream os = new BufferedOutputStream(sPort.getOutputStream());

os.write(int data);

//用于從串口讀數(shù)據(jù)

InputStream is = new BufferedInputStream(sPort.getInputStream());

int receivedData = is.read();

讀出來的是int型,你可以把它轉(zhuǎn)換成需要的其他類型。

這里要注意的是,由于Java語言沒有無符號類型,即所有的類型都是帶符號的,在由byte到int的時候應(yīng)該尤其注意。因為如果byte的最高位是1,則轉(zhuǎn)成int類型時將用1來占位。這樣,原本是10000000的byte類型的數(shù)變成int型就成了1111111110000000,這是很嚴(yán)重的問題,應(yīng)該注意避免。

3 串口通信的通用模式及其問題

終于嘮叨完我最討厭的基礎(chǔ)知識了,下面開始我們本次的重點--串口應(yīng)用的研究。由于向串口寫數(shù)據(jù)很簡單,所以這里我們只關(guān)注于從串口讀數(shù)據(jù)的情況。通常,串口通信應(yīng)用程序有兩種模式,一種是實現(xiàn)SerialPortEventListener接口,監(jiān)聽各種串口事件并作相應(yīng)處理;另一種就是建立一個獨立的接收線程專門負(fù)責(zé)數(shù)據(jù)的接收。由于這兩種方法在某些情況下存在很嚴(yán)重的問題(至于什么問題這里先賣個關(guān)子J),所以我的實現(xiàn)是采用第三種方法來解決這個問題。

3.1 事件監(jiān)聽模型

現(xiàn)在我們來看看事件監(jiān)聽模型是如何運作的

l 首先需要在你的端口控制類(例如SManager)加上“implements SerialPortEventListener”

l 在初始化時加入如下代碼:

try {

SerialPort sPort.addEventListener(SManager);

} catch (TooManyListenersException e) {

sPort.close();

throw new SerialConnectionException(“too many listeners added”);

}

sPort.notifyOnDataAvailable(true);

l 覆寫public void serialEvent(SerialPortEvent e)方法,在其中對如下事件進(jìn)行判斷:

BI -通訊中斷。

CD -載波檢測

CTS -清除發(fā)送。

DATA_AVAILABLE -有數(shù)據(jù)到達(dá)。

DSR -數(shù)據(jù)設(shè)備準(zhǔn)備好。

FE -幀錯誤。

OE -溢位錯誤。

OUTPUT_BUFFER_EMPTY -輸出緩沖區(qū)已清空。

PE -奇偶校驗錯。

RI -振鈴指示。

一般最常用的就是DATA_AVAILABLE--串口有數(shù)據(jù)到達(dá)事件。也就是說當(dāng)串口有數(shù)據(jù)到達(dá)時,你可以在serialEvent中接收并處理所收到的數(shù)據(jù)。然而在我的實踐中,遇到了一個十分嚴(yán)重的問題。

首先描述一下我的實驗:我的應(yīng)用程序需要接收傳感器節(jié)點從串口發(fā)回的查詢數(shù)據(jù),并將結(jié)果以圖標(biāo)的形式顯示出來。串口設(shè)定的波特率是115200,川口每隔128毫秒返回一組數(shù)據(jù)(大約是30字節(jié)左右),周期(即持續(xù)時間)為31秒。實測的時候在一個周期內(nèi)應(yīng)該返回4900多個字節(jié),而用事件監(jiān)聽模型我最多只能收到不到1500字節(jié),不知道這些字節(jié)都跑哪里去了,也不清楚到底丟失的是那部分?jǐn)?shù)據(jù)。值得注意的是,這是我將serialEvent()中所有處理代碼都注掉,只剩下打印代碼所得的結(jié)果。數(shù)據(jù)丟失的如此嚴(yán)重是我所不能忍受的,于是我決定采用其他方法。

3.2 串口讀數(shù)據(jù)的線程模型

這個模型顧名思義,就是將接收數(shù)據(jù)的操作寫成一個線程的形式:

public void startReadingDataThread() {

Thread readDataProcess = new Thread(new Runnable() {

public void run() {

while (newData != -1) {

try {

newData = is.read();

System.out.println(newData);

//其他的處理過程

………。

} catch (IOException ex) {

System.err.println(ex);

return;

}

}

readDataProcess.start();

}

在我的應(yīng)用程序中,我將收到的數(shù)據(jù)打包放到一個緩存中,然后啟動另一個線程從緩存中獲取并處理數(shù)據(jù)。兩個線程以生產(chǎn)者—消費者模式協(xié)同工作,數(shù)據(jù)的流向如下圖所示:

java串口通信編程實例

這樣,我就圓滿解決了丟數(shù)據(jù)問題。然而,沒高興多久我就又發(fā)現(xiàn)了一個同樣嚴(yán)重的問題:雖然這回不再丟數(shù)據(jù)了,可是原本一個周期(31秒)之后,傳感器節(jié)電已經(jīng)停止傳送數(shù)據(jù)了,但我的串口線程依然在努力的執(zhí)行讀串口操作,在控制臺也可以看見收到的數(shù)據(jù)仍在不斷的打印。原來,由于傳感器節(jié)點發(fā)送的數(shù)據(jù)過快,而我的接收線程處理不過來,所以InputStream就先把已到達(dá)卻還沒處理的字節(jié)緩存起來,于是就導(dǎo)致了明明傳感器節(jié)點已經(jīng)不再發(fā)數(shù)據(jù)了,而控制臺卻還能看見數(shù)據(jù)不斷打印這一奇怪的現(xiàn)象。唯一值得慶幸的是最后收到數(shù)據(jù)確實是4900左右字節(jié),沒出現(xiàn)丟失現(xiàn)象。然而當(dāng)處理完最后一個數(shù)據(jù)的時候已經(jīng)快1分半鐘了,這個時間遠(yuǎn)遠(yuǎn)大于節(jié)點運行周期。這一延遲對于一個實時的顯示系統(tǒng)來說簡直是災(zāi)難!

后來我想,是不是由于兩個線程之間的同步和通信導(dǎo)致了數(shù)據(jù)接收緩慢呢?于是我在接收線程的代碼中去掉了所有處理代碼,僅保留打印收到數(shù)據(jù)的語句,結(jié)果依然如故。看來并不是線程間的通信阻礙了數(shù)據(jù)的接收速度,而是用線程模型導(dǎo)致了對于發(fā)送端數(shù)據(jù)發(fā)送速率過快的情況下的數(shù)據(jù)接收延遲。這里申明一點,就是對于數(shù)據(jù)發(fā)送速率不是如此快的情況下前面者兩種模型應(yīng)該還是好用的,只是特殊情況還是應(yīng)該特殊處理。

3.3 第三種方法

痛苦了許久(Boss天天催我L)之后,偶然的機會,我聽說TinyOS中(又是開源的)有一部分是和我的應(yīng)用程序類似的串口通信部分,于是我下載了它的1.x版的Java代碼部分,參考了它的處理方法。解決問題的方法說穿了其實很簡單,就是從根源入手。根源不就是接收線程導(dǎo)致的嗎,那好,我就干脆取消接收線程和作為中介的共享緩存,而直接在處理線程中調(diào)用串口讀數(shù)據(jù)的方法來解決問題(什么,為什么不把處理線程也一并取消?----都取消應(yīng)用程序界面不就鎖死了嗎?所以必須保留)于是程序變成了這樣:

public byte[] getPack(){

while (true) {

// PacketLength為數(shù)據(jù)包長度

byte[] msgPack = new byte[PacketLength];

for(int i = 0; i 《 PacketLength; i++){

if( (newData = is.read()) != -1){

msgPack[i] = (byte) newData;

System.out.println(msgPack[i]);

}

}

return msgPack;

}

}

在處理線程中調(diào)用這個方法返回所需要的數(shù)據(jù)序列并處理之,這樣不但沒有丟失數(shù)據(jù)的現(xiàn)象行出現(xiàn),也沒有數(shù)據(jù)接收延遲了。這里唯一需要注意的就是當(dāng)串口停止發(fā)送數(shù)據(jù)或沒有數(shù)據(jù)的時候is.read()一直都返回-1,如果一旦在開始接收數(shù)據(jù)的時候發(fā)現(xiàn)-1就不要理它,繼續(xù)接收,直到收到真正的數(shù)據(jù)為止。

4 結(jié)束語

本文介紹了串口通信的基本知識,以及常用的幾種模式。通過實踐,提出了一些問題,并在最后加以解決。值得注意的是對于第一種方法,我曾將傳感器發(fā)送的時間由128毫秒增加到512毫秒,仍然有很嚴(yán)重的數(shù)據(jù)丟失現(xiàn)象發(fā)生,所以如果你的應(yīng)用程序需要很精密的結(jié)果,傳輸數(shù)據(jù)的速率又很快的話,就最好不要用第一種方法。對于第二種方法,由于是線程導(dǎo)致的問題,所以對于不同的機器應(yīng)該會有不同的表現(xiàn),對于那些處理多線程比較好的機器來說,應(yīng)該會好一些。但是我的機器是Inter 奔四3.0雙核CPU+512DDR內(nèi)存,這樣都延遲這么厲害,還得多強的CPU才行啊?所以對于數(shù)據(jù)量比較大的傳輸來說,還是用第三種方法吧。不過這個世界問題是很多的,而且未知的問題比已知的問題多的多,說不定還有什么其他問題存在,歡迎你通過下面的聯(lián)系方式和我一起研究。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • usb
    usb
    +關(guān)注

    關(guān)注

    60

    文章

    7988

    瀏覽量

    266261
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2976

    瀏覽量

    105211
  • 串口通信
    +關(guān)注

    關(guān)注

    34

    文章

    1627

    瀏覽量

    55754
收藏 人收藏

    評論

    相關(guān)推薦

    JAVA編程實例:多種風(fēng)格的窗口

    JAVA編程實例:多種風(fēng)格的窗口 
    發(fā)表于 12-06 12:37

    JAVA編程實例:右鍵彈出菜單

    JAVA編程實例:右鍵彈出菜單
    發(fā)表于 12-06 12:37

    JAVA編程實例:森林狀的關(guān)系圖

    JAVA編程實例:森林狀的關(guān)系圖
    發(fā)表于 12-06 12:38

    LabVIEW串口通信實例:PC機與51單片機串口通信實例

    相關(guān)課程推薦:《8周LabVIEW視覺項目編程實戰(zhàn)特訓(xùn)營》LabVIEW串口通信實例:PC機與51單片機串口通信實例
    發(fā)表于 06-28 20:04

    pc機用java是怎樣進(jìn)行串口通信

    總是有些人在質(zhì)疑,說pc機用java無法直接進(jìn)行串口通信。這篇文章通過完成的實例代碼,完美的宣告了一些!!!!
    發(fā)表于 07-14 06:57

    java多線程編程實例 (源程序)

    java多線程編程實例 import java.awt.*;import javax.swing.*; public class CompMover extends Object
    發(fā)表于 10-22 11:48 ?0次下載

    java_串口通訊實例

    java_串口通訊實例說明
    發(fā)表于 11-09 17:48 ?75次下載

    VISUAL BASIC串口通信編程實例_部分2

    以VisualBasic6.0中文版為背景編寫,從初學(xué)者的角度,在介紹VB串口通信基本知識和MSComm串口通信控件的基礎(chǔ)上,主要列舉典型測控應(yīng)用
    發(fā)表于 03-31 16:12 ?7次下載

    VISUAL BASIC串口通信編程實例_部分1

    以VisualBasic6.0中文版為背景編寫,從初學(xué)者的角度,在介紹VB串口通信基本知識和MSComm串口通信控件的基礎(chǔ)上,主要列舉典型測控應(yīng)用
    發(fā)表于 03-31 16:13 ?20次下載

    VISUAL BASIC串口通信編程實例_部分3

    以VisualBasic6.0中文版為背景編寫,從初學(xué)者的角度,在介紹VB串口通信基本知識和MSComm串口通信控件的基礎(chǔ)上,主要列舉典型測控應(yīng)用
    發(fā)表于 03-31 16:17 ?4次下載

    串口通信實例教程

    串口通信實例教程,感興趣的可以看看。
    發(fā)表于 06-23 17:56 ?0次下載

    Java串口通信詳解

    這里有java串口通信的詳細(xì)資料,打開串口串口掃描,波特率端口設(shè)置。
    發(fā)表于 09-26 16:31 ?7次下載

    MFC串口通信編程介紹

    主要介紹了用 CreateFile()函數(shù)和 WriteFile()函數(shù)讀寫串口實例,以及設(shè)置串口屬性的實例。 在工業(yè)控制中,工控機(一般都基于 Windows 平臺)經(jīng)常需要與智能
    發(fā)表于 11-16 11:35 ?7次下載

    python串口編程實例

    本文主要介紹了幾種python串口編程實例。Python是純粹的自由軟件, 源代碼和解釋器CPython遵循 GPL(GNU General Public License)協(xié)議。Python具有豐富
    發(fā)表于 01-15 09:35 ?4.7w次閱讀

    Java實現(xiàn)與51單片機串口通信 Serie Library

    Java實現(xiàn)與51單片機串口通信 Serie Library項目結(jié)構(gòu)Program Struct測試代碼package com.lius.testS;import
    發(fā)表于 11-23 16:51 ?15次下載
    <b class='flag-5'>Java</b>實現(xiàn)與51單片機<b class='flag-5'>串口</b><b class='flag-5'>通信</b> Serie Library
    主站蜘蛛池模板: 国产色爽女小说免费看 | 欧美激情片网站 | 亚洲成a人片777777久久 | 亚洲乱强| 色多多免费视频观看区一区 | 中国成人在线视频 | 69精品在线 | 日韩xx00 | 成年美女黄网站色大免费视频 | 在线天堂中文有限公司 | 国产v69| 性欧美xxxx视频 | 国模精品视频一区二区三区 | 乱高h辣黄文np公交车 | 资源视频在线观看 | 欧美一区亚洲 | 亚洲欧美精品成人久久91 | 日本超黄视频 | 色免费在线观看 | 国产高清网站 | 2022第二三四天堂网 | 日日添天天做天天爱 | 久久艹免费视频 | 久久草精品 | 五月婷婷网站 | 女人扒开腿让男人桶到爽 | 欧美一卡二卡科技有限公司 | 欧美一级特黄aaa大片 | 久久久久久免费播放一级毛片 | 奇米影视一区 | 日本成人资源 | 秋霞特色大片18入口私人高清 | 美女扒开尿口给男人捅 | 欧美在线91 | 91视频看看 | 香蕉视频在线观看国产 | 午夜视频在线看 | 日本伊人网 | 精品精品国产理论在线观看 | 午夜片在线 | 性久久久久久久 |