我正在尝试从硬件设备读取串行响应。我读的字符串很长,我只需要它的一部分。要获取我想要的部分字符串,我使用std::string.substr(x,y);
。但是我遇到的问题有时会出现异常错误,因为我正在读取的缓冲区没有y字符。这是我现在用来读取值的代码:
while(1)
{
char szBuff[50+1] = {0};
char wzBuff[14] = {"AT+CSQ\r"};
DWORD dZBytesRead = 0;
DWORD dwBytesRead = 0;
if(!WriteFile(hSerial, wzBuff, 7, &dZBytesRead, NULL))
std::cout << "Write error";
if(!ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL))
std::cout << "Read Error";
std:: cout << szBuff;
std::string test = std::string(szBuff).substr(8,10);
std::cout << test;
Sleep(500);
我发出命令“AT + CSQ”。这将返回:
N,N
行
它返回两个整数值,用逗号分隔后跟一个新行,然后是“OK”。
我的问题是,如何在抓取子字符串之前确保从串口读取所有值?根据我的理解,收到的最后一个字符应该是一个新行。
答案 0 :(得分:1)
ReadFile
函数的界面似乎为您提供了读取的字节数。如果你知道预期的长度,你应该循环尝试从文件读取(可能是端口描述符),直到读取预期的字节数。
如果响应的长度未知,则可能必须读取并检查读取缓冲区是否已读取分隔符令牌(在这种情况下,您的协议似乎表明可以使用新行)确定EOM - 消息的结尾)
如果您可以使用其他库,我会考虑使用boost::asio
和read_until
功能(或您正在使用的任何库中的等效功能)。虽然管理这个的代码不是火箭科学,但在大多数情况下重新发明轮子是没有意义的。
答案 1 :(得分:0)
您应该使用ReadFile
将每个周期的特定字节数读入缓冲区。应填写此缓冲区,直到ReadFile
读取0
字节,您已达到\n
或\r\n
个字符,或填充缓冲区为最大值。
完成此操作后,就不需要substr
您的字符串,您可以遍历字符缓冲区。
例如,
while (awaitResponse) {
ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL);
if (dwBytesRead != 0) {
// move memory from szBuff to your class member (e.g. mySerialBuff)
} else {
// nothing to read
if (buffCounter > 0) {
// process buffer
}
else {
// zero out all buffers
}
}
}
答案 2 :(得分:0)
正如你在最后一行中所说,你知道响应的终结符是一个新的行字符。您需要从序列中读取,直到在输入中的某处接收到新行。从前一个新行到当前新行收到的所有内容都是响应,当前新行之后的所有内容都是下一个响应的一部分。这是通过循环读取,处理发现的每个响应来实现的:
char* myBigBuff;
int indexToBuff = 0;
int startNewLine = 0;
while (ReadFile(hSerial, myBigBuff + indexToBuff, 100, &dwBytesRead, NULL))
{
if (strchr(myBigBuff, '\n') != NULL)
{
handleResponse(myBigBuff + startNewLine, indexToBuff + dwBytesRead);
startNewLine = indexToBuff + dwBytesRead;
}
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
这是基本的想法。你应该通过你选择的任何方式处理左边的字符(循环缓冲区,简单复制到临时数组等)。
答案 3 :(得分:0)
老问题,但我将@Eli Iser代码修改为:
while (ReadFile(hSerial, myBigBuff + indexToBuff, 1, &dwBytesRead, NULL)) {
if (strchr(myBigBuff, '-') != NULL || dwBytesRead < 1)
break;
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
if (indexToBuff != 0) {
//Do whatever with the code, it received successfully.
}