开发者

C++ - ensuring full serial response

I am trying to read a serial response from a hardware device. The string I read is long and I only need a portion of it. To get to portion of the string I want I use std::string.substr(x,y); . The problem I run into however is sometimes I get an exception error because the buffer I am reading from doesn't have y characters. Here is the code I use now to read values:

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, &dwBytesRea开发者_StackOverflow中文版d, NULL))
    std::cout << "Read Error";



std:: cout << szBuff;
std::string test = std::string(szBuff).substr(8,10);
std::cout << test;
Sleep(500);

I am issuing the command "AT+CSQ". This returns:

N, N

OK

It returns two integer values seperated by a comma followed by a new line, followed by "OK".

My question is, how can I make sure I read all values from the serial port before grabbing a substring? From what I understand, the last character received should be a new line.


The interface of your ReadFile function seems to provide you with the number of bytes read. If you know the length that is expected, you should loop trying reading from the file (probably port descriptor) until the expected number of bytes is read.

If the length of the response is not known, you might have to read and check in the read buffer whether the separator token has been read or not (in this case your protocol seems to indicate that a new-line can be used to determine EOM --end of message)

If you can use other libraries, I would consider using boost::asio and the read_until functionality (or the equivalent in whatever libraries you are using). While the code to manage this is not rocket science, in most cases there is no point in reinventing the wheel.


As you said yourself in the last line, you know that the terminator for the response is a new line character. You need to read from the serial until you receive a new line somewhere in the input. Everything you received from the previous new line to the current new line is the response, with everything after the current new line is part of the next response. This is achieved by reading in a loop, handling each response as it is discovered:

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

This is the basic idea. You should handle the left overs characters via any way you choose (cyclic buffer, simple copy to a temp array, etc.)


You should use ReadFile to read a certain amount of bytes per cycle into your buffer. This buffer should be filled until ReadFile reads 0 bytes, you have reached your \n or \r\n characters, or filled your buffer to the max.

Once you have done this, there would be no need to substr your string and you can iterate through your character buffer.

For example,

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


Old question, but I modified @Eli Iser code to:

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.
        }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜