我正在将加速度计数据从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发送的数据包的第一个字节。
我已经使用高达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活动,以便其自由地尽快接收下一个吗?然后在主要活动中,我将重建数据包吗?还是对主要活动来说太费力了?
预先感谢您的帮助。