C ++ - 确保完整的串行响应

时间:2011-10-10 11:59:39

标签: c++ c windows serial-port

我正在尝试从硬件设备读取串行响应。我读的字符串很长,我只需要它的一部分。要获取我想要的部分字符串,我使用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”。

我的问题是,如何在抓取子字符串之前确保从串口读取所有值?根据我的理解,收到的最后一个字符应该是一个新行。

4 个答案:

答案 0 :(得分:1)

ReadFile函数的界面似乎为您提供了读取的字节数。如果你知道预期的长度,你应该循环尝试从文件读取(可能是端口描述符),直到读取预期的字节数。

如果响应的长度未知,则可能必须读取并检查读取缓冲区是否已读取分隔符令牌(在这种情况下,您的协议似乎表明可以使用新行)确定EOM - 消息的结尾)

如果您可以使用其他库,我会考虑使用boost::asioread_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.
        }