通过蓝牙从STM32向Android发送数据时未收到完整的数据包

时间:2019-01-23 18:13:43

标签: android c bluetooth stm32 spi

我正在将加速度计数据从STM32微控制器发送到HC-06蓝牙模块,并且我已经开发了一个Android应用程序来接收数据。

在STM32上,我制作了一个3字节的数据包(uartBuffer),其结构如下:[0]计数器,[1] xdata,[2] ydata。 然后,我通过UART将这些数据发送到HC-06模块。     HAL_UART_Transmit(&uartHand, uartBuffer, 3, 10); // {uartHandle, data, dataSize, timeout}

在Android上,与设备等连接时没有问题。但是,当我收到数据包时,它并没有一起到达。它确实总是会最终到达(也以正确的顺序),但是我可能会得到一个只有第一个字节的数据包,然后是最后两个字节的数据包,有时还会有其他组合,如下面的logcat图片所示。始终递增1的值(即20、21、22等)是STM32发送的数据包的第一个字节。

Android logcat

我已经使用高达100Hz的不同采样率和更大的数据包(最多5个字节)对它进行了测试。我从不丢失任何字节,但是在更高的采样率和数据大小下,数据包的排列被进一步划分。 / p>

这里是ConnectedThread类,该类在run方法中读取数据。

`
private class ConnectedThread extends Thread {

    private final BluetoothSocket mmBTSocket;
    private final InputStream mInStream;
    private final OutputStream mOutStream;

    public ConnectedThread(BluetoothSocket mSocket) {
        Log.d(TAG, "ConnectedThread: Starting");

        mmBTSocket = mSocket;
        InputStream mTempIn = null;
        OutputStream mTempOut = null;

        try {
            mTempIn = mmBTSocket.getInputStream();
            mTempOut = mmBTSocket.getOutputStream();
        } catch (IOException e) {
            Log.e(TAG, "Failed to get I/O Stream", e);
        }
        mInStream = mTempIn;
        mOutStream = mTempOut;
    }


    public void run(){
        byte[] mBuffer = new byte[3]
        int mBytes = 0; // bytes returned from read
        String mIncomingMessage = new String();
        mIncomingStringBuilder = new StringBuilder();

        while (true) {
            try {
                mIncomingStringBuilder.setLength(0);
                mBytes = mInStream.read(mBuffer, 0, 3);
                for (int i=0; i<mBytes; i++) {
                    mIncomingMessage = String.valueOf(mBuffer[i]);
                    mIncomingStringBuilder.append(mIncomingMessage + ",");
                }
                Log.d(TAG, "run: ConnectedThread - InputStream: " + mIncomingStringBuilder);
                Intent incomingMessageIntent = new Intent("incomingMessage");
                incomingMessageIntent.putExtra("theMessage", mIncomingStringBuilder.toString());
                LocalBroadcastManager.getInstance(mContext).sendBroadcast(incomingMessageIntent);
            } catch (IOException e) {
                Log.e(TAG, "error reading from inputStream, e);
                break;
            }
        }
}
`

所以我的问题是:

1)为什么我没有收到与从STM32发送来的相同结构的完整数据包?这里的评论者提到here

  

蓝牙连接基于流,而不是基于分组。无法保证或尝试保留打包。因此,任何数量的写入都可以导致任何数量的读取,只是保证字节流是正确的。如果需要检测数据包,则需要提供自己的数据包结构来包装数据。

这是真的吗?蓝牙真的不能保留完整的数据包结构吗?有人可以验证吗?

2)如果是这样,那么构造一个易于让Android检测到起点和终点的软件包的最佳方法是什么?我假设我需要一个同步/开始字节。如何确保加速度计数据中不会出现此同步字节?我应该使用2个连续的同步字节吗?数据包末尾的校验和是否足以检测数据包是否有错误?

3)最后,一种好的做法是仅在Android上使用connectedThread来接收字节,转换为字符串并发送给main活动,以便其自由地尽快接收下一个吗?然后在主要活动中,我将重建数据包吗?还是对主要活动来说太费力了?

预先感谢您的帮助。

0 个答案:

没有答案