c++ -确保全串行响应

C++ - ensuring full serial response

本文关键字:响应 确保 c++      更新时间:2023-10-16

我正在尝试从硬件设备读取串行响应。我读取的字符串很长,我只需要它的一部分。为了得到我想要的字符串的一部分,我用std::string.substr(x,y);。然而,我遇到的问题是,有时我会得到一个异常错误,因为我正在读取的缓冲区没有y个字符。下面是我现在用来读取值的代码:

while(1)
{
char szBuff[50+1] = {0};
char wzBuff[14] = {"AT+CSQr"};
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"。

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

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

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

如果您可以使用其他库,我会考虑使用boost::asioread_until功能(或您正在使用的任何库中的等效功能)。虽然管理这个的代码不是火箭科学,但在大多数情况下,重新发明轮子是没有意义的。

正如您在上一行中所说的,您知道响应的结束符是一个新的行字符。您需要从串行读取,直到在输入的某个地方接收到新行。从上一个新行到当前新行收到的所有内容都是响应,当前新行之后的所有内容都是下一个响应的一部分。这是通过在循环中读取来实现的,在发现响应时处理每个响应:

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; 
}

这是基本思想。您应该通过您选择的任何方式处理剩余字符(循环缓冲区,简单复制到临时数组等)

您应该使用ReadFile每个周期将一定数量的字节读入缓冲区。这个缓冲区应该被填满,直到ReadFile读取0字节,达到nrn字符,或将缓冲区填满到最大值。

一旦你这样做了,就不需要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
        }
    }
}

老问题,但我修改了@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.
        }