我正在通过UART接收来自Arduino的数据。我按照文档进行了操作,大多数情况下我都能获得预期的数据。有时读操作不会完成,会获取几个零,然后使用其余数据开始新的读操作。这可以在示例输出中看到,所有数据都在那里,但被分成了两个读取。我每秒只发送一次数据,所以应该有足够的时间。
我的代码:
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
@Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
private void readUartBuffer(UartDevice uart) throws IOException {
// Maximum amount of data to read at one time
final int maxCount = 20;
byte[] buffer = new byte[maxCount];
uart.read(buffer, maxCount);
Log.i(TAG, Arrays.toString(buffer));
}
@Override
public void onUartDeviceError(UartDevice uart, int error) {
Log.w(TAG, uart + ": Error event " + error);
}
};
输出示例:
[50, 48, 54, 46, 52, 53, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 57, 51, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 48, 52, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 55, 46, 51, 52, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 53, 48, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 55, 46, 51, 54, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 57, 51, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 0, 0, 0, 0]
[51, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[50, 48, 55, 46, 51, 56, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 0, 0, 0, 0]
[51, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[50, 48, 54, 46, 52, 57, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
我非常确定问题出在R Pi上,因为我从Arduino循环到我的PC时没有任何问题。我还发现,除非我将maxCount设置为我发送的确切字节数,否则这个问题会更加普遍。因此,数据以随机包的形式出现,但顺序正确。我是在浪费时间吗?我应该只使用I2C吗?
发布于 2018-07-08 19:26:47
“我应该直接使用I2C吗?”-不。R Pi没有问题,因为“所有的数据都在那里”。它们(可以)被分成2个(或更多)读,因为onUartDeviceDataAvailable()
可以在所有数据可用(但只有部分数据可用)之前触发,所以您应该循环读取它们,直到接收到所有数据为止。并且,从您的代码中可以看出:maxCount - Maximum amount of data to read at one time
的大小并不适用于所有数据,它是最大的。一次性读取的大小。你的代码可以是这样的(NB!这只是一个例子,而不是完整的解决方案):
private void readUartBuffer(UartDevice uart) throws IOException {
// Buffer for all data
final int maxSizeOfAllData = 30;
byte[] completaDataBuffer = new byte[maxSizeOfAllData];
// Buffer for one uart.read() call
final int maxCount = 20;
byte[] buffer = new byte[maxCount];
int bytesReadOnce; // number of actually available data
int totalBytesRead = 0;
// read all available data
while ((bytesReadOnce = uart.read(buffer, maxCount))) > 0) {
// add new data to "all data" buffer
for (int i = 0; i < bytesReadOnce; i++) {
completaDataBuffer[totalBytesRead + i] = buffer[i]
if (totalBytesRead + i == maxSizeOfAllData - 1) {
// process complete buffer here
...
totalBytesRead = 0;
break;
}
}
totalBytesRead += bytesReadOnce;
}
}
另外,看看来自Android Things user-space drivers的NmeaGpsModule.java和来自Android Things samples的LoopbackActivity.java。
发布于 2018-07-09 23:19:36
我最后添加了一个结束字符(0x36)并使用了一个dataCompleteFlag:
private void readUartBuffer(UartDevice uart) throws IOException {
// Maximum amount of data to read at one time
final int maxCount = 32;
byte[] buffer = new byte[maxCount];
boolean dataCompleteFlag = false;
uart.read(buffer, maxCount);
Log.i(TAG, Arrays.toString(buffer));
if (!dataCompleteFlag) {
for (int i = 0; i < maxCount; i++) {
if (buffer[i] == 36) {
dataCompleteFlag = true;
dataCount = 0;
}
else if(dataCount > maxCount) {
dataCount = 0;
}
else if(buffer[i] != 0) {
finalDataBuffer[dataCount] = buffer[i];
dataCount++;
}
}
}
if (dataCompleteFlag) {
//process data
}
}
@Override
public void onUartDeviceError(UartDevice uart, int error) {
Log.w(TAG, uart + ": Error event " + error);
}
};
https://stackoverflow.com/questions/51229615
复制相似问题