Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Com Port


Автор: YuriyFrolov 27.3.2006, 14:27
У меня такой вопрос: мне нужно считывать и отправлять данные по com порту. Механизм простой программа должна общаться с прибором который на каждое её сообщение отвечает своим сообщением. Сам прибор произвольно сообщения не отсылает. Но отвечать он может и не сразу. При отладке программа работает правильно. Но когда её запустить то появляется следующая ошибка:
Код

if (!ReadFile(hComm, buf, sizeof(buf), &dwRead, &ov1))
{
  ...
}
else
{
  ...//программа перескакивает сюда хотя на самом деле она ничего не прочитала - ?!
}


Куски кода:
Код

void CServo_Change::SendCommand_01(byte k, byte l)
{
    DWORD dwWrite;
    BYTE buf[10];
    int sum = 0;
    for (int i = 1; i <= 7; i++)
    {
        sum = sum + buf[i];    
    }
    OVERLAPPED ov1 = {0};
    WriteFile(hComm, buf, sizeof(buf), &dwWrite, &ov1);
    ReadAnswerData(0, 1, k, l, 12);
}

void CServo_Change::ReadAnswerData(byte k, byte l, byte m, byte n, byte dlina_kadra)
{
    BYTE ErrorCode;
    int i1, i2, i3, i4;
    BYTE buf[6  + 16];
    BYTE buf1[6 +  4];
    BYTE buf2[6 +  8];
    BYTE buf3[6 + 12];
    BYTE buf4[6 + 16];
    DWORD dwRead, dwRes;
    OVERLAPPED ov1 = {0};
    ov1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!ReadFile(hComm, buf, sizeof(buf), &dwRead, &ov1))
    {
        if (GetLastError() != ERROR_IO_PENDING)
        {
            // обработка ошибки чтения
            AfxMessageBox("обработка ошибки чтения");
        }
        else
        {
            // Ожидание завершения операции
            AfxMessageBox("Ожидание завершения операции");
            dwRes = WaitForSingleObject(ov1.hEvent, 500);
            switch(dwRes) 
            {
            case WAIT_OBJECT_0:
                // чтение завершено
                GetOverlappedResult(hComm, &ov1, &dwRead, FALSE);
                // Обработка прочитанных данных
                ErrorCode = buf[2];
                
                break;
            case WAIT_TIMEOUT:
                // Тайм-аут завершен
                // Данные могли быть прочитаны не полностью
                
                break;
            }
            ResetEvent(ov1.hEvent);
        }
    }
    else
    {
        // Чтение выполнено немедленно
        // Обработка прочитанных данных
        ResetEvent(ov1.hEvent);
    }
}

В чём тут проблема?

Автор: DeadSoul 27.3.2006, 21:27
YuriyFrolov, SetCommTimeout делал?

Автор: Nuzur 28.3.2006, 10:00
а не проще ли так?
и так точно работает, порверялось и не раз.

Код


    DWORD EvtMask;

//если надо то чистим

    PurgeComm(/*ваш порт*/MyGreatComPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
    if (WaitCommEvent(/*ваш порт*/MyGreatComPortHandle, &EvtMask, NULL)) 
    {
//ждем символ
        if (EvtMask & EV_RXCHAR) //EV_RXCHAR
//проверяем на корректность, ну там флаги и все такое
//если нуна переходим снова на ожидание
//лучше всего ет забадяжить в потоке и не париться



И никаких гвоздей.
Включаете таймер на тайм аут и по срабатыванию таймера если не получили данных или данны не корректны остонавливаете поток и отсылаете прибору либо сообщение о повторной пересылке данных, либо о том что они уже как-то и не нужны.
Удачи.

ЗЫ Знакомая фамилия, вы откуда?

Автор: takedo 28.3.2006, 10:11
YuriyFrolov, А как вы определяете что данные не получены? Если по размеру входного буфера, то это знатный косячок, при котором изменение размера буфера никак не синхронизировано Windows с событием о приходе символа в порт! Я эту тему поднимал, но понимания не нашел. Однако, замечу, что такая проблема возникает, когда данные считываются кусками, то есть, когда в буфер пришло, например 5 байт из 505, мы тут же начинаем считывать пять байт и т.д. Если дожидаться конца кадра, смотреть размер входного буфера(очереди) с считывать это количество байт за один раз, проблема вроде бы отсутствует. Мое мнение - на большей скорости работы порта, например ГИГАБИТ(понятно, что этого пока нет), и этот вариант не прокатит. Есть трипути решения 1) описанный предложением выше, 2) писать свою очередь и ждать своего события, 3) переходить на синхронную передачу, тут и SetCommTimeout в тему будет.

Автор: YuriyFrolov 28.3.2006, 10:23
А я из Киева smile . Попробую сделать отдельный поток - тогда можно спокойно использовать синхронную связь.

Автор: Nuzur 28.3.2006, 10:55
Цитата

А как вы определяете что данные не получены? Если по размеру входного буфера, то это знатный косячок....


Зачем по размеру буфера? А CEvent вам зачем?
Получили байты 1-е знач появилась надежда что весь кадр(поток или как там ИСче назвать?) прийдет правельный... соответственно отложили "убитие" таймера на Н-е количество времени.... тоесть увеличели таймаут операции.....
Ну ето уже все зависит от ОУ.

А Организация ваша как дразниться, напишите в личку.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)