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

C++ C++;-确保完整的串行响应,c++,c,windows,serial-port,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

我正在尝试从硬件设备读取串行响应。我读的字符串很长,我只需要它的一部分。为了得到我想要的字符串部分,我使用
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);
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您的
ReadFile
函数的接口似乎为您提供了读取的字节数。如果您知道预期的长度,您应该循环尝试读取文件(可能是端口描述符),直到读取预期的字节数

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


如果您可以使用其他库,我会考虑使用<代码> Boo::ASIO 和<代码> Read直到功能(或者在您使用的任何库中等效)。虽然管理这一点的代码不是火箭科学,但在大多数情况下,重新发明轮子是没有意义的。

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

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


如果您可以使用其他库,我会考虑使用<代码> Boo::ASIO 和<代码> Read直到功能(或者在您使用的任何库中等效)。虽然管理这一点的代码不是火箭科学,但在大多数情况下,重新发明轮子是没有意义的。

您应该使用
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
        }
    }
}

您应该使用
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
        }
    }
}

正如您在最后一行中所说,您知道响应的终止符是一个新行字符。您需要从序列中读取,直到在输入中的某个位置收到新行为止。您从上一新行到当前新行收到的所有内容都是响应,在当前新行之后的所有内容都是响应的一部分下一个响应。这是通过在循环中读取,在发现每个响应时处理它来实现的:

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

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

正如您在最后一行中所说,您知道响应的终止符是一个新行字符。您需要从序列中读取,直到在输入中的某个位置收到新行。从上一新行到当前新行收到的所有内容都是响应,在当前新行之后的所有内容都是响应的一部分下一个响应。这是通过在循环中读取来实现的,在发现每个响应时对其进行处理:

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

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

旧问题,但我将@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.
        }
while(ReadFile(hSerial,myBigBuff+indexToBuff,1,&dwBytesRead,NULL)){
if(strchr(myBigBuff,“-”)!=NULL | | dwBytesRead<1)
打破
//在缓冲区中向前移动。这应该循环进行
indexToBuff+=dwBytesRead;
}
如果(indexToBuff!=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.
        }
while(ReadFile(hSerial,myBigBuff+indexToBuff,1,&dwBytesRead,NULL)){
if(strchr(myBigBuff,“-”)!=NULL | | dwBytesRead<1)
打破
//在缓冲区中向前移动。这应该循环进行
indexToBuff+=dwBytesRead;
}
如果(indexToBuff!=0){
//不管对代码做什么,它都会成功接收。
}

Define“all values”(定义“all values”)。您为什么希望接收到一定数量的数据?数据源到底是什么?是否有任何关于通信协议的文档需要阅读?(我强烈怀疑有)编辑。我基本上在等待一行新的内容。定义“all values”(定义“all values(所有值))。为什么您希望收到一定数量的数据?数据源到底是什么?您是否应该阅读有关通信协议的任何文档?(我强烈怀疑有。)已编辑。我基本上在等待新行。好的,当这个调用成功运行时,它返回23个字节。这意味着我的sz中的元素22