欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android讀取串口數(shù)據(jù)的操作指南

 更新時(shí)間:2024年05月24日 08:47:49   作者:Crazy_MT  
在Android系統(tǒng)上讀取串口數(shù)據(jù)是一個(gè)常見的需求,特別是當(dāng)我們需要與硬件設(shè)備進(jìn)行通信時(shí),本文給大家介紹了Android讀取串口數(shù)據(jù)的操作指南,文中有詳細(xì)的步驟和代碼示例,幫助你更好地理解和實(shí)現(xiàn)串口通信,需要的朋友可以參考下

在Android系統(tǒng)上讀取串口數(shù)據(jù)是一個(gè)常見的需求,特別是當(dāng)我們需要與硬件設(shè)備進(jìn)行通信時(shí)。通過(guò)開源項(xiàng)目 Crazy-MT/SerialAssistant,我們可以快速了解如何在Android上實(shí)現(xiàn)這一功能。以下是詳細(xì)的步驟和代碼示例,幫助你更好地理解和實(shí)現(xiàn)串口通信。

一、確定串口號(hào)和波特率

1. 查找設(shè)備文件

在Linux系統(tǒng)中(Android基于Linux),串口設(shè)備通常表示為 /dev/ttySx 或 /dev/ttyUSBx,其中 x 是數(shù)字。例如,/dev/ttyS0 代表第一個(gè)串口,/dev/ttyUSB0 代表第一個(gè)USB串口適配器。

2. 通過(guò)文件系統(tǒng)查看可用串口

你可以在Android設(shè)備的終端中使用 ls /dev/tty* 命令來(lái)查看可用的串口設(shè)備文件。使用ADB(Android Debug Bridge)來(lái)連接和訪問(wèn)設(shè)備終端:

adb shell
ls /dev/tty*

二、確定波特率

波特率是串口通信的速率,單位是波特(baud)。常見的波特率有 9600、19200、38400、57600、115200 等。波特率的選擇通常由串口設(shè)備的規(guī)格或協(xié)議決定。你需要查閱設(shè)備手冊(cè)或與設(shè)備供應(yīng)商確認(rèn)。

三、讀取串口數(shù)據(jù)

在選擇正確的串口號(hào)和波特率后,可以通過(guò)輸入流讀取串口數(shù)據(jù)。以下是一個(gè)讀取線程的示例代碼:

private class ReadThread extends Thread {
    @Override
    public void run() {
        super.run();
        while(!isInterrupted()) {
            try
            {
                if (mInputStream == null) return;
                int size = mInputStream.read(tempBuff);
                if (size > 0){
                    onDataReceived(Arrays.copyOfRange(tempBuff, 0, size));
                }
                try
                {
                    Thread.sleep(10);//延時(shí)10ms
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            } catch (Throwable e)
            {
                e.printStackTrace();
                return;
            }
        }
    }
}

四、數(shù)據(jù)包處理

以某品牌的電子秤為例,其數(shù)據(jù)協(xié)議如下:

取重

1、主動(dòng)/被動(dòng)模式的數(shù)據(jù)格式相同。
2、上位機(jī)指令(HEX): 1b 01 02
3、數(shù)據(jù)格式:(總共 24 字節(jié))

01 02  000.000kg 000.000kg sta  X   03 04
數(shù)據(jù)頭  凈重       皮重      狀態(tài) 校驗(yàn) 數(shù)據(jù)尾

SHead1        SOH(01H)   1 字節(jié),標(biāo)題開始
SHead2        STX(02H)   1 字節(jié),正文開始
Weight 1      XXX.XXX    7 字節(jié),凈重。
Weight Units  U1U0       2 字節(jié),重量單位。如“kg”
Weight2       XXX.XXX    7 字節(jié),皮重。
Weight Units  U1U0       2 字節(jié),重量單位。如“kg”
Status        STA        1 字節(jié),狀態(tài)
Check Sum     BCC        1 字節(jié),使用 BCC 算法,除 SOH STX ETX EOT 及本字節(jié)外所有字符的 BCC 校驗(yàn)。
Tail1         ETX(03H)   1 字節(jié),標(biāo)題結(jié)束
Tail2         EOT(04H)   1 字節(jié),傳輸結(jié)束

重量格式(凈重/皮重),例如:
123.456kg
23.456kg
12.3456kg
0.012kg
-12.345kg
-1.234kg
-0.0001kg
(前面無(wú)數(shù)據(jù)則用空格填充。如果小數(shù)點(diǎn)后面有四位,則為精確到 0.1g)

狀態(tài):
bit7:1 重量溢出;0 重量正常
bit6:1 開機(jī)后未歸零(開機(jī)時(shí)秤盤上有重物);0 開機(jī)后已歸零
bit5:1 當(dāng)前在去皮模式;0 當(dāng)前不是    去皮模式
bit4:1 當(dāng)前重量為 0;0 當(dāng)前重量不為 0 
bit3:1 重量穩(wěn)定;0 重量不穩(wěn)定 
bit2~bit0  0

在串口通信中,處理數(shù)據(jù)包并確保數(shù)據(jù)的完整性是一項(xiàng)重要的任務(wù)。在這篇博客中,我們將探討如何使用 Java 通過(guò)串口讀取數(shù)據(jù),并確保每條讀到的數(shù)據(jù)都是完整的。我們將介紹如何設(shè)計(jì)一個(gè)系統(tǒng)來(lái)處理數(shù)據(jù)包,包括數(shù)據(jù)包解析和驗(yàn)證的邏輯。

五、數(shù)據(jù)包解析類

定義一個(gè)抽象數(shù)據(jù)包類 Packet:

public abstract class Packet {
    protected byte[] data;

    public Packet(byte[] data) {
        this.data = data;
    }

    public byte[] getData() {
        return data;
    }

    public abstract String getNetWeight();
    public abstract String getTareWeight();
    public abstract byte getStatus();
}

實(shí)現(xiàn)具體的數(shù)據(jù)解析類 DefaultPacket:

public class DefaultPacket extends Packet {

    public DefaultPacket(byte[] data) {
        super(data);
    }

    @Override
    public String getNetWeight() {
        return new String(data, 2, 7);
    }

    @Override
    public String getTareWeight() {
        return new String(data, 11, 7);
    }

    @Override
    public byte getStatus() {
        return data[20];
    }

    public static String parseStatus(byte status) {
        StringBuilder sb = new StringBuilder();
        sb.append("Weight Overflow: ").append((status & 0x80) != 0).append("\n");
        sb.append("Not Zeroed on Power-up: ").append((status & 0x40) != 0).append("\n");
        sb.append("Tare Mode: ").append((status & 0x20) != 0).append("\n");
        sb.append("Weight is Zero: ").append((status & 0x10) != 0).append("\n");
        sb.append("Weight Stable: ").append((status & 0x08) != 0).append("\n");
        return sb.toString();
    }
}

六、數(shù)據(jù)包解析接口和實(shí)現(xiàn)類

定義數(shù)據(jù)包解析接口 PacketParser:

public interface PacketParser {
    int getDataLength();
    boolean isValid(byte[] data);
    boolean checkChecksum(byte[] data);
    Packet parse(byte[] data);
}

具體數(shù)據(jù)包解析類

DefaultPacketParser 實(shí)現(xiàn)了具體的數(shù)據(jù)包解析和驗(yàn)證邏輯:

public class DefaultPacketParser implements PacketParser {
    @Override
    public int getDataLength() {
        return 24;
    }

    @Override
    public boolean isValid(byte[] data) {
        return data[0] == 0x01 && data[1] == 0x02 && data[22] == 0x03 && data[23] == 0x04;
    }

    @Override
    public boolean checkChecksum(byte[] data) {
        byte checksum = 0;
        for (int i = 2; i < 21; i++) {
            checksum ^= data[i];
        }
        return checksum == data[21];
    }

    @Override
    public Packet parse(byte[] data) {
        return new DefaultPacket(data);
    }
}

七、數(shù)據(jù)包輸入流類

PacketInputStream 類使用 PacketParser 來(lái)處理數(shù)據(jù)包的解析和驗(yàn)證,并累積無(wú)效數(shù)據(jù):

import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class PacketInputStream extends FilterInputStream {
    private PacketParser parser;
    private byte[] buffer;
    private int bufferPos = 0;
    private ByteArrayOutputStream byteArrayBuffer = new ByteArrayOutputStream();

    public PacketInputStream(InputStream in, PacketParser parser) {
        super(in);
        this.parser = parser;
        this.buffer = new byte[parser.getDataLength()];
    }

    public Packet readPacket() throws IOException {
        // 將上次剩余的無(wú)效數(shù)據(jù)寫入緩沖區(qū)
        if (byteArrayBuffer.size() > 0) {
            byte[] invalidData = byteArrayBuffer.toByteArray();
            System.arraycopy(invalidData, 0, buffer, 0, invalidData.length);
            bufferPos = invalidData.length;
            byteArrayBuffer.reset();
        }

        while (bufferPos < parser.getDataLength()) {
            int read = in.read(buffer, bufferPos, parser.getDataLength() - bufferPos);
            if (read == -1) {
                return null; // EOF reached
            }
            bufferPos += read;
        }

        int start = findPacketStart(buffer);
        while (start == -1 && bufferPos >= 2) {
            System.arraycopy(buffer, 1, buffer, 0, bufferPos - 1);
            bufferPos--;
            int read = in.read(buffer, bufferPos, 1);
            if (read == -1) {
                return null; // EOF reached
            }
            bufferPos += read;
            start = findPacketStart(buffer);
        }

        if (start != 0) {
            byte[] remainingData = Arrays.copyOfRange(buffer, start, bufferPos);
            System.arraycopy(remainingData, 0, buffer, 0, remainingData.length);
            bufferPos = remainingData.length;
            return null;
        }

        if (!parser.isValid(buffer)) {
            byteArrayBuffer.write(buffer, 0, bufferPos);
            bufferPos = 0;
            return null; // 返回 null 表示無(wú)效數(shù)據(jù)包
        }

        if (!parser.checkChecksum(buffer)) {
            byteArrayBuffer.write(buffer, 0, bufferPos);
            bufferPos = 0;
            return null; // 返回 null 表示校驗(yàn)失敗
        }

        Packet packet = parser.parse(Arrays.copyOf(buffer, parser.getDataLength()));
        bufferPos = 0;
        return packet;
    }

    private int findPacketStart(byte[] data) {
        for (int i = 0; i < data.length - 1; i++) {
            if (data[i] == 0x01 && data[i + 1] == 0x02) {
                return i;
            }
        }
        return -1;
    }
}

八、讀取線程類

ReadThread 使用 PacketInputStream 和 PacketParser 來(lái)讀取和處理數(shù)據(jù)包:

import java.io.InputStream;

private class ReadThread extends Thread {
    private PacketInputStream packetInputStream;

    public ReadThread(InputStream inputStream, PacketParser parser) {
        this.packetInputStream = new PacketInputStream(inputStream, parser);
    }

    @Override
    public void run() {
        super.run();
        while (!isInterrupted()) {
            try {
                Packet packet = packetInputStream.readPacket();
                if (packet != null) {
                    if (packet instanceof DefaultPacket) {
                        onDataReceived((DefaultPacket) packet);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
    }

    private void onDataReceived(DefaultPacket packet) {
        System.out.println("Net Weight: " + packet.getNetWeight());
        System.out.println("Tare Weight: " + packet.getTareWeight());
        System.out.println("Status: " + DefaultPacket.parseStatus(packet.getStatus()));
    }
}

總結(jié)

通過(guò)抽象數(shù)據(jù)包解析邏輯,我們可以更好地處理串口數(shù)據(jù)包的完整性問(wèn)題。我們定義了數(shù)據(jù)包類 Packet 和 DefaultPacket,并使用 PacketParser 接口來(lái)實(shí)現(xiàn)數(shù)據(jù)包的解析和驗(yàn)證。PacketInputStream 類負(fù)責(zé)處理數(shù)據(jù)包的讀取和無(wú)效數(shù)據(jù)的累積,而 ReadThread 負(fù)責(zé)讀取和處理有效數(shù)據(jù)包。這種設(shè)計(jì)使代碼更加模塊化、易于維護(hù)和擴(kuò)展,可以很容易地適應(yīng)不同格式的數(shù)據(jù)包。

以上就是Android讀取串口數(shù)據(jù)的操作指南的詳細(xì)內(nèi)容,更多關(guān)于Android讀取串口數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android通過(guò)HTTP協(xié)議實(shí)現(xiàn)上傳文件數(shù)據(jù)

    Android通過(guò)HTTP協(xié)議實(shí)現(xiàn)上傳文件數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Android通過(guò)HTTP協(xié)議實(shí)現(xiàn)上傳文件數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android實(shí)現(xiàn)彈出列表、單選、多選框

    Android實(shí)現(xiàn)彈出列表、單選、多選框

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)彈出列表、單選、多選框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • AndroidStudio4.0日志中文亂碼問(wèn)題

    AndroidStudio4.0日志中文亂碼問(wèn)題

    這篇文章主要介紹了AndroidStudio4.0日志中文亂碼問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Android編程開發(fā)之RadioGroup用法實(shí)例

    Android編程開發(fā)之RadioGroup用法實(shí)例

    這篇文章主要介紹了Android編程開發(fā)之RadioGroup用法,結(jié)合實(shí)例形式分析了Android中RadioGroup單選按鈕的具體使用技巧,需要的朋友可以參考下
    2015-12-12
  • Flutter實(shí)現(xiàn)頂部導(dǎo)航欄功能

    Flutter實(shí)現(xiàn)頂部導(dǎo)航欄功能

    這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)頂部導(dǎo)航欄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Android極光推送處理message遇到的坑解決

    Android極光推送處理message遇到的坑解決

    這篇文章主要為大家介紹了Android極光推送處理message遇到的坑解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Android開發(fā)之子線程操作UI的幾種方法

    Android開發(fā)之子線程操作UI的幾種方法

    這篇文章主要介紹了Android開發(fā)之子線程操作UI的幾種方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • Android 暫停和恢復(fù)Activity

    Android 暫停和恢復(fù)Activity

    在正常的應(yīng)用程序使用,前臺(tái)activity有時(shí)會(huì)被其他可視化組件遮擋,從而 造成activity的暫停。例如,當(dāng)一個(gè)半透明的activity打開時(shí)(如在一個(gè)風(fēng)格對(duì)話框),以前的activity就暫停了。只要 activity仍然是部分可見,但目前沒(méi)有獲得焦點(diǎn),它就依然處于暫停狀態(tài)
    2016-03-03
  • android之listview懸浮topBar效果

    android之listview懸浮topBar效果

    這篇文章主要為大家詳細(xì)介紹了android之listview懸浮topBar效果的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 基于Android開發(fā)支持表情的實(shí)現(xiàn)詳解

    基于Android開發(fā)支持表情的實(shí)現(xiàn)詳解

    本篇文章是對(duì)在Android開發(fā)中支持表情的實(shí)現(xiàn)代碼進(jìn)行了介紹。需要的朋友參考下
    2013-05-05

最新評(píng)論