[英]Reading from Linux serial port using C++ provides messy data
所以我有基於Raspberry Pi(Modberry)的嵌入式設備和通過一個USB集線器連接的4個傳感器。 這些傳感器始終通過串口發送數據,我必須閱讀和分析。 數據按塊分割:每個7個字節,它們之間有空格。 前4個字節是時間,3個字節是由傳感器測量的值。 正常值應該是大約0 + - 5.波特率是921600.當我只讀取一個傳感器,例如“/ dev / ttyUSB0”時,一切都很好但是當我開始增加可讀傳感器的數量時,事情就完全錯了。 代表時間的4個字節總是以正確的方式傳遞,並且永遠不會錯,但最后3個字節帶有奇怪的值99%的時間並開始發送垃圾郵件,如下所示:
[2019-04-22 17:48:02.264] Device: /dev/ttyUSB3, Time: 12226408, Value: 1690
[2019-04-22 17:48:02.265] Device: /dev/ttyUSB2, Time: 12217312, Value: 1690
[2019-04-22 17:48:02.265] Device: /dev/ttyUSB2, Time: 12217316, Value: 1690
有趣的是,它在重新啟動應用程序后不會100%發生,但大約80%。
我也在Python和Java中創建了一個沒有這個問題的應用程序。 它們都在同一台設備上運行。 我試圖在單獨的線程中讀取每個傳感器,但它也沒有幫助。
我簡化了我的代碼並刪除了這個塊中的所有錯誤檢查。
void openSerial()
{
const int fileDescriptor = ::open(mParams.path.c_str(), O_RDONLY | O_NOCTTY);
termios SerialPortSettings;
SerialPortSettings.c_cflag &= ~PARENB;
SerialPortSettings.c_cflag &= ~CSTOPB;
SerialPortSettings.c_cflag &= ~CSIZE;
SerialPortSettings.c_cflag |= CS8;
SerialPortSettings.c_cflag &= ~CRTSCTS;
SerialPortSettings.c_cflag |= CREAD | CLOCAL;
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
SerialPortSettings.c_oflag &= ~OPOST;
SerialPortSettings.c_cc[VMIN] = 10;
SerialPortSettings.c_cc[VTIME] = 0;
cfsetispeed(&SerialPortSettings, 921600);
tcsetattr(fileDescriptor, TCSANOW, &SerialPortSettings);
tcflush(fileDescriptor, TCIOFLUSH);
}
static const int BUFFER_SIZE = 256;
void readSerial()
{
char buffer[BUFFER_SIZE + 1] = { 0 };
int count = 0;
count = read(mfd, buffer, BUFFER_SIZE);
std::vector<char> rawBuffer;
for (int i = 0; i < count; i++) {
rawBuffer.push_back(buffer[i]);
}
parse(rawBuffer);
}
void parse(std::vector<char> rawBuffer)
{
auto currentSpace = std::find(rawBuffer.begin(), rawBuffer.end(), ' ');
auto nextSpace = std::find(currentSpace + 1, rawBuffer.end(), ' ');
size_t counter = 0;
while (currentSpace != rawBuffer.end()) {
const int dist = std::distance(currentSpace, nextSpace);
if (dist == 8) {
XD1000Data data;
data.time = parseTime(&(*(currentSpace + TIME_SHIFT)));
data.value = parseValue(&(*(currentSpace + VALUE_SHIFT)));
} else {
printf("packet size error, dist %d, rawBuffer.size %d, counter %d", dist, rawBuffer.size(), counter);
}
counter++;
currentSpace = nextSpace;
nextSpace = std::find(currentSpace + 1, rawBuffer.end(), ' ');
}
rawBuffer.clear();
}
long parseTime(char *buffer)
{
long dest[4];
long time;
parseBuffer<long, 4>(buffer, dest);
time = dest[3] + (dest[2] << 6) + (dest[1] << 12) + (dest[0] << 18);
return time;
}
int parseValue(char *buffer)
{
int dest[3];
int value;
parseBuffer<int, 3>(buffer, dest);
value = dest[2] + (dest[1] << 6) + (dest[0] << 12);
return (short)((value & 0x1000) ? (value | 0xf000) : (value & 0x0fff));
}
template <typename T, size_t size> void parseBuffer(char *buffer, T *dest)
{
for (size_t i = 0; i < size; i++) {
if (isupper(buffer[i]))
dest[i] = buffer[i] - 'A';
else if (islower(buffer[i]))
dest[i] = buffer[i] - 'a' + 26;
else if (isdigit(buffer[i]))
dest[i] = buffer[i] - '0' + 52;
else if (buffer[i] == '+')
dest[i] = 62;
else if (buffer[i] == '/')
dest[i] = 63;
else // error
;
}
}
我100%確定傳感器沒有發送這個1690數據,在任何其他帶有任何傳感器甚至Minicom的應用程序中都沒有觀察到這種行為。 這就是它應該如何工作,並且它做了一些罕見的時間:
Device:/dev/ttyUSB3 14006188 -5
Device:/dev/ttyUSB3 14006192 -6
Device:/dev/ttyUSB3 14006196 -5
Device:/dev/ttyUSB3 14006200 -6
Device:/dev/ttyUSB3 14006204 -5
Device:/dev/ttyUSB3 14006208 -6
Device:/dev/ttyUSB3 14006212 -5
Device:/dev/ttyUSB0 14006152 -1
Device:/dev/ttyUSB0 14006156 -2
Device:/dev/ttyUSB0 14006160 -1
Device:/dev/ttyUSB0 14006164 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.