читать из последовательного порта C ++ - PullRequest
1 голос
/ 08 ноября 2011

У меня есть следующий код C ++, и когда я запускаю программу, иногда она работает, а иногда нет!

Я думаю, что проблема возникает, когда я пытаюсь открыть последовательный порт, когда остаются данные для чтения.

Иногда после запуска этой программы Windows XP неожиданно перезагружается! Это не синий экран, он просто перезагружается.

Я использую Visual Studio 2010 для его компиляции.

main()
{
    while(0) { // BIG FAT WARNING: MIGHT SUDDEN REBOOT YOUR MACHINE IF ENABLED
        read_from_serial(_data);
    }
}

bool read_from_serial(octed_string &_data)
{
    HANDLE hSerial;
    hSerial = CreateFile(TEXT("COM2"),
                         GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if (hSerial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            cout << "1:";
            return false;
        //serialportdoesnotexist.Informuser.
        }
        cout << "2:";
        return false;

        //someothererroroccurred.Informuser.
    }

    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);

    if(!GetCommState(hSerial,&dcbSerialParams))
    {
        cout<<"3:";
        return false;
        //errorgettingstate
    }

    dcbSerialParams.BaudRate=CBR_9600;
    dcbSerialParams.ByteSize=7;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=EVENPARITY;

    if (!SetCommState(hSerial,&dcbSerialParams))
    {
        cout<<"4:";
        return false;
        //errorsettingserialportstate
    }

    COMMTIMEOUTS timeouts={0};
    timeouts.ReadIntervalTimeout=50;
    timeouts.ReadTotalTimeoutConstant=10;
    timeouts.ReadTotalTimeoutMultiplier=10;
    timeouts.WriteTotalTimeoutConstant=50;
    timeouts.WriteTotalTimeoutMultiplier=10;

    if (!SetCommTimeouts(hSerial,&timeouts))
    {
        cout<<"5:";
        return false;
        //erroroccureed.Informuser
    }

    const int n=1;

    DWORD dwBytesRead=0;

    char_t tmp_receive[255]={0};

    char_t buff[255];

    int len=255;

    if (!ReadFile(hSerial,tmp_receive,len,&dwBytesRead,NULL))
    {
        cout<<"6:";
        CloseHandle(hSerial);
        return false;
    }

    CloseHandle(hSerial);

    tmp_receive[dwBytesRead+1]=END_OF_STRING;
    string tmp_buff_str=tmp_receive;
    _data.append(tmp_buff_str);
    return true;
}

1 Ответ

1 голос
/ 09 ноября 2011

Причина

У меня есть подозрение, что в этой строке происходит сбой вашей программы

tmp_receive[dwBytesRead+1]=END_OF_STRING;

Вы определили массив tmp_receive с элементами 255, что делает возможные индексы *От 1008 * до 254.Затем вы инициализировали len до 255.Если при вызове ReadFile(...) доступно 255 байтов для чтения, то dwBytesRead будет равен 255, и строка, о которой я упоминал выше, будет выглядеть следующим образом и будет означать, что вы пытаетесь записать в памятьвне рамок массива tmp_receive.

tmp_receive[256] = END_OF_STRING;

Что касается перезагрузки, я точно не знаю, но, возможно, ваша программа вызывает сбой системы при попытке записи в недопустимую памятьи у вас Windows XP настроена на перезагрузку вместо отображения BSOD .


Решения

Чтобы предотвратить сбой вашей программы, я вижу, что у вас есть 2 варианта.Я не могу сказать, какой из них лучше, поскольку я не знаю, какой формат данных вы ожидаете получить, поэтому вам придется проанализировать результаты каждого варианта и принять решение самостоятельно.

Опция # 1

Используйте число элементов 257 при определении массива tmp_receive.

Опция # 2

Отнимите 2 от len при совершении вызова на ReadFile(...)

if (!ReadFile(hSerial,tmp_receive,len-2,&dwBytesRead,NULL))

Дополнительная информация

  • Естьобратитесь к документации MSDN по ReadFile(...) для получения дополнительной информации о поведении ReadFile(...) Windows API.

  • Если вы хотите узнать больше о том, как строки хранятся в памяти, я бы посоветовал взглянуть на статью Символьные последовательности на www.cplusplus.com .

...