android平板(应用层)串口通信如何防止丢包数据

473 阅读2分钟

引言

MCU与应用之间的通信非常的快一般200ms左右就会交互一次,同时数据在传输过程中也很容易受到干扰“1”变成“0”或者“0”变成“1”,而且在读取数据流时候刚好是一包数据的中间或者结尾。总之能拿到一包正确的数据确实要考虑到很多的问题。

数据安全

上篇文章我会以“0xAA”举例就是因为“10101010”是它的二进制这个数比较有规律,受到干扰变成这样的二进制概率比较小,如果加上“01010101“就更好了,这样安全的多。但是数据还是不能以”AA 55“为一包数据的唯一校验方式,必须以CRC来校验因为出现”AA 55“开头的无效数据还是有可能的。CRC的校验方式有很多种,大家和电控同事确定一种就好。

数据读取

//示例代码
final BlockingQueue<Byte> CACHE_QUEUE = new ArrayBlockingQueue<>(256);
while (!isInterrupted()) {
    try {
        byte[] buffer = new byte[8];
        if (mInputStream == null){
            return;
        }
    
        int size = mInputStream.read(buffer);
        if (size <= 0) {
            continue;
        }
        for (int i = 0; i < size; i++) {
            //往里添加数据
            CACHE_QUEUE.offer(buffer[i]);
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

ArrayBlockingQueue 阻塞队列很好的解决了多线程中数据的安全传输问题,同时保障了“先进先出” 这里里面主要是用到了“先进先出” 就像流水一下先取的数据先用来组合。

防止数据丢包

  • 堵塞读取数据 CACHE_QUEUE.take()
while (true) {
    try {
        handle(CACHE_QUEUE.take());
    } catch (InterruptedException e) {
        e.printStackTrace();
        continue;
    }
}
  • 读取每个字节从中取出一包有效数据

/**
* buffer 缓存读取一包数据
*/
 byte[] buffer = null;
 


/**
 * 处理每一个字节
 *
 * @param b
 */
@RequiresApi(api = Build.VERSION_CODES.O)
private void handle(byte b) {
    if(index==0||index==1){
        head(b);
    } else if (index < length - 1) {
        middle(b);
    } else if (index == length - 1) {
        last(b);
    } else {
        reset();
    }
}

private void head(byte b) {
    if (数据头) {
        this.reset();
        first = b;
        index++;
    }  else {
        this.reset();
    }
}

/**
*数据中
*/
private void middle(byte b) {
    buffer[index] = b;
    index++;
}

/**
* 数据尾
*/

private void last(byte b) {
    buffer[index] = b;
    this.print(buffer);

    // 校验CRC
    if (FrameUtils.isAPacketData(buffer, buffer.length)) {
        // 处理业务逻辑
        // todo
       
        System.out.println("一包数据");
        reset();
    } else {
        //从头后数据再添加处理
        byte[] tempBuffer = Arrays.copyOf(buffer, buffer.length);
        reset();
        for (int i = 2; i < tempBuffer.length; i++) {
            this.handle(tempBuffer[i]);
        }
    }
}



/**
*重置
*/
private void reset() {
    first = 0x00;
    index = 0;
    length = 0;
    buffer = null;
 
}