当前位置: 代码网 > it编程>App开发>Android > Android读取串口数据的操作指南

Android读取串口数据的操作指南

2024年06月10日 Android 我要评论
在android系统上读取串口数据是一个常见的需求,特别是当我们需要与硬件设备进行通信时。通过开源项目 crazy-mt/serialassistant,我们可以快速了解如何在android上实现这一

在android系统上读取串口数据是一个常见的需求,特别是当我们需要与硬件设备进行通信时。通过开源项目 crazy-mt/serialassistant,我们可以快速了解如何在android上实现这一功能。以下是详细的步骤和代码示例,帮助你更好地理解和实现串口通信。

一、确定串口号和波特率

1. 查找设备文件

在linux系统中(android基于linux),串口设备通常表示为 /dev/ttysx 或 /dev/ttyusbx,其中 x 是数字。例如,/dev/ttys0 代表第一个串口,/dev/ttyusb0 代表第一个usb串口适配器。

2. 通过文件系统查看可用串口

你可以在android设备的终端中使用 ls /dev/tty* 命令来查看可用的串口设备文件。使用adb(android debug bridge)来连接和访问设备终端:

adb shell
ls /dev/tty*

二、确定波特率

波特率是串口通信的速率,单位是波特(baud)。常见的波特率有 9600、19200、38400、57600、115200 等。波特率的选择通常由串口设备的规格或协议决定。你需要查阅设备手册或与设备供应商确认。

三、读取串口数据

在选择正确的串口号和波特率后,可以通过输入流读取串口数据。以下是一个读取线程的示例代码:

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);//延时10ms
                } catch (interruptedexception e)
                {
                    e.printstacktrace();
                }
            } catch (throwable e)
            {
                e.printstacktrace();
                return;
            }
        }
    }
}

四、数据包处理

以某品牌的电子秤为例,其数据协议如下:

取重

1、主动/被动模式的数据格式相同。
2、上位机指令(hex): 1b 01 02
3、数据格式:(总共 24 字节)

01 02  000.000kg 000.000kg sta  x   03 04
数据头  净重       皮重      状态 校验 数据尾

shead1        soh(01h)   1 字节,标题开始
shead2        stx(02h)   1 字节,正文开始
weight 1      xxx.xxx    7 字节,净重。
weight units  u1u0       2 字节,重量单位。如“kg”
weight2       xxx.xxx    7 字节,皮重。
weight units  u1u0       2 字节,重量单位。如“kg”
status        sta        1 字节,状态
check sum     bcc        1 字节,使用 bcc 算法,除 soh stx etx eot 及本字节外所有字符的 bcc 校验。
tail1         etx(03h)   1 字节,标题结束
tail2         eot(04h)   1 字节,传输结束

重量格式(净重/皮重),例如:
123.456kg
23.456kg
12.3456kg
0.012kg
-12.345kg
-1.234kg
-0.0001kg
(前面无数据则用空格填充。如果小数点后面有四位,则为精确到 0.1g)

状态:
bit7:1 重量溢出;0 重量正常
bit6:1 开机后未归零(开机时秤盘上有重物);0 开机后已归零
bit5:1 当前在去皮模式;0 当前不是    去皮模式
bit4:1 当前重量为 0;0 当前重量不为 0 
bit3:1 重量稳定;0 重量不稳定 
bit2~bit0  0

在串口通信中,处理数据包并确保数据的完整性是一项重要的任务。在这篇博客中,我们将探讨如何使用 java 通过串口读取数据,并确保每条读到的数据都是完整的。我们将介绍如何设计一个系统来处理数据包,包括数据包解析和验证的逻辑。

五、数据包解析类

定义一个抽象数据包类 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();
}

实现具体的数据解析类 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();
    }
}

六、数据包解析接口和实现类

定义数据包解析接口 packetparser:

public interface packetparser {
    int getdatalength();
    boolean isvalid(byte[] data);
    boolean checkchecksum(byte[] data);
    packet parse(byte[] data);
}

具体数据包解析类

defaultpacketparser 实现了具体的数据包解析和验证逻辑:

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);
    }
}

七、数据包输入流类

packetinputstream 类使用 packetparser 来处理数据包的解析和验证,并累积无效数据:

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 {
        // 将上次剩余的无效数据写入缓冲区
        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 表示无效数据包
        }

        if (!parser.checkchecksum(buffer)) {
            bytearraybuffer.write(buffer, 0, bufferpos);
            bufferpos = 0;
            return null; // 返回 null 表示校验失败
        }

        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 来读取和处理数据包:

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()));
    }
}

总结

通过抽象数据包解析逻辑,我们可以更好地处理串口数据包的完整性问题。我们定义了数据包类 packet 和 defaultpacket,并使用 packetparser 接口来实现数据包的解析和验证。packetinputstream 类负责处理数据包的读取和无效数据的累积,而 readthread 负责读取和处理有效数据包。这种设计使代码更加模块化、易于维护和扩展,可以很容易地适应不同格式的数据包。

以上就是android读取串口数据的操作指南的详细内容,更多关于android读取串口数据的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com