Искажение данных при чтении с COM порта
От: Alexei_z_  
Дата: 11.11.04 17:14
Оценка:
Всем доброго времени суток,
Возникла следующая проблема:
Есть класс, в нем такие функции для работы с COM портом:
int SerialPort::ReadData(unsigned char *buffer, const int buffer_size) // reads from port into buffer amount of bytes specified //by buffer_size 
{
    if(idCom == 0) return -1; //port is not opened
    unsigned long nbread;
    Sleep(100); // wait to meet COM port requirements
    if(!ReadFile(idCom, buffer, COMMAND_LENGTH, &nbread, NULL)) return -2; //if were errors during reading
    if(nbread != COMMAND_LENGTH) return -3; //if wrong amount of bytes was read
    return 0;
}

int SerialPort::WriteData(unsigned char *buffer, const int buffer_size) // writes into port from buffer amount of bytes specified by buffer_size 
{
    if(idCom == 0) return -1; //port not opened
    unsigned long nbread;
    Sleep(100); // wait to meet COM port requirements
    PurgeComm(idCom,PURGE_TXCLEAR); // clear output buffer
    // serial pooling
    if(!WriteFile(idCom, buffer, buffer_size, &nbread, NULL)) return -1; 

    PurgeComm(idCom,PURGE_RXCLEAR); // clear input buffer
    return 0;
}


Отсылаются данные по 4 байта через COM порт на другой компютер

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

Все это запускаю в цикле (на двух компах, соединенных через COM-порт — на одном — write\read, на другом -наоборот)
Цикл примерно такой :

    for (int k=0;k<50; k++)
    {

        line[0]= 0xF0; 
        line[1]= 0x23; 
        line[2]= 0x52; 
        line[3]= 0x35; 
        
        memcpy(line_to_compare, line, COMMAND_LENGTH);
        p_SerialPort->WriteData(line,COMMAND_LENGTH); //reset
        read_result = p_SerialPort->ReadData(line,COMMAND_LENGTH);
    }
    
    return 0;
}

Функция открытия порта:
int SerialPort::OpenPort(unsigned port)// Opens COM port with number "port"
    {

        char pcPort [5];
        sprintf(pcPort,"%s%i","COM",port);
        idCom = CreateFile(pcPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if(idCom == INVALID_HANDLE_VALUE) return -1; // if cannot open COM port
        if(!SetupComm(idCom, 4096, 4096)) return -3; // if cannot set port parameters 
        if(!GetCommState(idCom, &dcb)) return -3;  // loading "dcb" by default values 
    
        dcb.ByteSize = 8;
        dcb.BaudRate = 115200;
//        dcb.BaudRate = 1200;

        dcb.Parity = NOPARITY;
        dcb.StopBits = ONESTOPBIT;
        dcb.fDtrControl = DTR_CONTROL_DISABLE;
        if(!SetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

        if(!GetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

        if(!PurgeComm(idCom,PURGE_RXCLEAR)) return -3; // clear input   buffer
        if(!PurgeComm(idCom,PURGE_TXCLEAR)) return -3; // clear output  buffer

        return 0;
}

При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?
Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально






12.11.04 05:06: Перенесено модератором из 'C/C++' — Павел Кузнецов
Re: Искажение данных при чтении с COM порта
От: sva1509  
Дата: 11.11.04 17:46
Оценка:
Здравствуйте, Alexei_z_, Вы писали:

A__>Функция открытия порта:

A__>
A__>int SerialPort::OpenPort(unsigned port)// Opens COM port with number "port"
A__>    {

A__>        char pcPort [5];
A__>        sprintf(pcPort,"%s%i","COM",port);
A__>        idCom = CreateFile(pcPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
A__>        if(idCom == INVALID_HANDLE_VALUE) return -1; // if cannot open COM port
A__>        if(!SetupComm(idCom, 4096, 4096)) return -3; // if cannot set port parameters 
A__>        if(!GetCommState(idCom, &dcb)) return -3;  // loading "dcb" by default values 
    
A__>        dcb.ByteSize = 8;
A__>        dcb.BaudRate = 115200;
A__>//        dcb.BaudRate = 1200;

A__>        dcb.Parity = NOPARITY;
A__>        dcb.StopBits = ONESTOPBIT;
A__>        dcb.fDtrControl = DTR_CONTROL_DISABLE;
A__>        if(!SetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

A__>        if(!GetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

A__>        if(!PurgeComm(idCom,PURGE_RXCLEAR)) return -3; // clear input   buffer
A__>        if(!PurgeComm(idCom,PURGE_TXCLEAR)) return -3; // clear output  buffer

A__>        return 0;
A__>}
A__>

A__>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?
A__>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

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

ЗЫ: похоже что функция чтения возвращается раньше чем получен весь пакет.

С уважением Валерий.
Re[2]: Искажение данных при чтении с COM порта
От: ArtSh Россия  
Дата: 11.11.04 17:54
Оценка:
Здравствуйте, sva1509, Вы писали:

S>Определи для порта таймауты.

S>SetCommTimeouts
S>Событиями ты не пользуешся, а драйвер должен знать по истечению какого времени
S>передачу или прием можно считать закончеными.

S>ЗЫ: похоже что функция чтения возвращается раньше чем получен весь пакет.


S>С уважением Валерий.


Скорее всего таймауты выставлены по умолчанию, а по умолчанию они очень большие,(на мой взгляд самые оптимальные написаны в примере к MSDN).
А ошибки возникают из — за высокой скорости передачи данных(у меня например были ошибки на такой скорости каждые 40000 байт и даже чаще). Пусть обмен происходит на 48000 бод.
Re[2]: Искажение данных при чтении с COM порта
От: Alexei_z_  
Дата: 11.11.04 17:55
Оценка:
Здравствуйте, sva1509, Вы писали:

S>Здравствуйте, Alexei_z_, Вы писали:


A__>>Функция открытия порта:

A__>>
A__>>int SerialPort::OpenPort(unsigned port)// Opens COM port with number "port"
A__>>    {

A__>>        char pcPort [5];
A__>>        sprintf(pcPort,"%s%i","COM",port);
A__>>        idCom = CreateFile(pcPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
A__>>        if(idCom == INVALID_HANDLE_VALUE) return -1; // if cannot open COM port
A__>>        if(!SetupComm(idCom, 4096, 4096)) return -3; // if cannot set port parameters 
A__>>        if(!GetCommState(idCom, &dcb)) return -3;  // loading "dcb" by default values 
    
A__>>        dcb.ByteSize = 8;
A__>>        dcb.BaudRate = 115200;
A__>>//        dcb.BaudRate = 1200;

A__>>        dcb.Parity = NOPARITY;
A__>>        dcb.StopBits = ONESTOPBIT;
A__>>        dcb.fDtrControl = DTR_CONTROL_DISABLE;
A__>>        if(!SetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

A__>>        if(!GetCommState(idCom, &dcb)) return -3; // if cannot set port parameters 

A__>>        if(!PurgeComm(idCom,PURGE_RXCLEAR)) return -3; // clear input   buffer
A__>>        if(!PurgeComm(idCom,PURGE_TXCLEAR)) return -3; // clear output  buffer

A__>>        return 0;
A__>>}
A__>>

A__>>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?
A__>>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

S>Определи для порта таймауты.

S>SetCommTimeouts
S>Событиями ты не пользуешся, а драйвер должен знать по истечению какого времени
S>передачу или прием можно считать закончеными.

S>ЗЫ: похоже что функция чтения возвращается раньше чем получен весь пакет.


S>С уважением Валерий.


Я устанавливаю параметры на чтение:
int SerialPort::SetReadTimeOut(unsigned long wait_time)//sets maximal time of waiting response from the board
{

    if(!GetCommTimeouts(idCom, &timeouts)) return -3;  // loading "timeouts" by default values 

    timeouts.ReadTotalTimeoutConstant = wait_time;
    timeouts.ReadIntervalTimeout = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;

    if(!SetCommTimeouts(idCom, &timeouts))return -3; //setting new timeout value
    

    return 0;
}

Потом
p_SerialPort->SetReadTimeOut(5000)

На запись — должны же быть какие-то по умолчанию?
По поводу событий — я использую синхронные версии функций (overlapped 0) — они должны возвращать управление после того как закончат запис в буффер?
Потом, у меня есть предопределенное число байтов, которые нужно считать
Если количество считанных и ожидаемых несовпадает — возвращается ошибка
Такое бывает, но очень редко
Re[3]: Искажение данных при чтении с COM порта
От: Alexei_z_  
Дата: 11.11.04 17:57
Оценка:
Здравствуйте, ArtSh, Вы писали:

AS>Здравствуйте, sva1509, Вы писали:


S>>Определи для порта таймауты.

S>>SetCommTimeouts
S>>Событиями ты не пользуешся, а драйвер должен знать по истечению какого времени
S>>передачу или прием можно считать закончеными.

S>>ЗЫ: похоже что функция чтения возвращается раньше чем получен весь пакет.


S>>С уважением Валерий.


AS>Скорее всего таймауты выставлены по умолчанию, а по умолчанию они очень большие,(на мой взгляд самые оптимальные написаны в примере к MSDN).

AS>А ошибки возникают из — за высокой скорости передачи данных(у меня например были ошибки на такой скорости каждые 40000 байт и даже чаще). Пусть обмен происходит на 48000 бод.


Мы менянли скорость на 1200 — не помогло, при этой скорсти почему-то первые байты всегда были искажены
Re: Искажение данных при чтении с COM порта
От: maq Россия http://www.maqdev.com
Дата: 11.11.04 19:21
Оценка:
A__>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?
A__>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

Видимо потому что вы использует кабель в котором всего три провода — чтение,запись,общий и не используется
протокол синхронизации XON/XOFF.
На высоких скоростях надо использовать полный кабель с разведенными CTS/DSR/RTS/DTR etc и включить
аппаратную синхронизацию DTR_CONTROL_HANDSHAKE и RTS_CONTROL_HANDSHAKE.

Кстати это все равно не дает гарантии 100% достоверности передаваемых данных — так как
проверка ошибок выполняется с помощью бита четности. Если необходимо обеспечить
100% гарантию — надо реализовывать свой протокол.
<RSDN@Home ME> FooBar2k: silent
Re[2]: Искажение данных при чтении с COM порта
От: Protey Россия  
Дата: 12.11.04 06:30
Оценка:
Здравствуйте, maq, Вы писали:

A__>>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?

A__>>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

maq>Видимо потому что вы использует кабель в котором всего три провода — чтение,запись,общий и не используется

maq>протокол синхронизации XON/XOFF.
maq>На высоких скоростях надо использовать полный кабель с разведенными CTS/DSR/RTS/DTR etc и включить
maq>аппаратную синхронизацию DTR_CONTROL_HANDSHAKE и RTS_CONTROL_HANDSHAKE.

maq>Кстати это все равно не дает гарантии 100% достоверности передаваемых данных — так как

maq>проверка ошибок выполняется с помощью бита четности. Если необходимо обеспечить
maq>100% гарантию —

Согласен, всё правда

maq>надо реализовывать свой протокол.


А что HDLC/PPP уже отменили? ИМХО единственный реальный способ собрать на СОМ линии помехоустойчивый поток.
Re[3]: Искажение данных при чтении с COM порта
От: Alexei_z_  
Дата: 12.11.04 09:44
Оценка:
Здравствуйте, Protey, Вы писали:

P>Здравствуйте, maq, Вы писали:


A__>>>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?

A__>>>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

maq>>Видимо потому что вы использует кабель в котором всего три провода — чтение,запись,общий и не используется

maq>>протокол синхронизации XON/XOFF.
maq>>На высоких скоростях надо использовать полный кабель с разведенными CTS/DSR/RTS/DTR etc и включить
maq>>аппаратную синхронизацию DTR_CONTROL_HANDSHAKE и RTS_CONTROL_HANDSHAKE.

maq>>Кстати это все равно не дает гарантии 100% достоверности передаваемых данных — так как

maq>>проверка ошибок выполняется с помощью бита четности. Если необходимо обеспечить
maq>>100% гарантию —

P>Согласен, всё правда


maq>>надо реализовывать свой протокол.


P>А что HDLC/PPP уже отменили? ИМХО единственный реальный способ собрать на СОМ линии помехоустойчивый поток.


А можно подробнее про последнее? HDLC/PPP и XON/XOFF?
А то все мои знания на эту тему уместятся в два предложения
Или где почитать?
Re[3]: Искажение данных при чтении с COM порта
От: maq Россия http://www.maqdev.com
Дата: 12.11.04 12:50
Оценка:
P>А что HDLC/PPP уже отменили? ИМХО единственный реальный способ собрать на СОМ линии помехоустойчивый поток.

В общем конечно да, но это если обе стороны ее поддерживают.
А вот если одной из сторон является некое примитивное устройство, зачастую
самодельное — придется писать какой нибудь протокол самому.
<RSDN@Home ME> FooBar2k: silent
Re: Искажение данных при чтении с COM порта
От: RvRom  
Дата: 14.11.04 22:34
Оценка:
Здравствуйте, Alexei_z_, Вы писали:

A__>Всем доброго времени суток,

A__>Возникла следующая проблема:
A__>Есть класс, в нем такие функции для работы с COM портом:

случаем buffer на реад и врайт — не один и тот же?
попробуй в кретические секции запихнуть реад и врайт... слип бы я вообще убрал...
Re[4]: Искажение данных при чтении с COM порта
От: Protey Россия  
Дата: 15.11.04 05:58
Оценка:
Трактатъ о асинхронных линиях связи.

Введение.

Асинхронные линии связи — такие линии связи, в которых потоки данных от устройстав и к устройству в общем случае не зависят друг от друга, либо зависят слабо. Т.е. устройство в любой момент времени может передать пакет байт, либо принять.

Проблемы.

Проблема только одна — нет линий связи с целостностью передаваемой информации = 100%. Отчего, при потере первого байта в пакете, например, случается искажение необходимой информации. Это не есть гут.

Решение.

Оччень простое, в начале пакета передаём некий байт — флаг, далее данные, потом чек-сумму пакета, закрывающий флаг.
Теперь при поере любого байта будет потерян только лишь один пакет, не повлияв на остальные.

Практически имеется много протоколов, наиболее часто используемый — PPP/HDLC.

Читать RFC 1661, 1662. Поле прочтения никто не заставляет писать ВЕСЬ РРР протокол, для прОстых устройств достаточно иплементировать HDLC.
Re: Искажение данных при чтении с COM порта
От: mr.X  
Дата: 26.09.06 12:16
Оценка:
Здравствуйте, Alexei_z_, Вы писали:

A__>При приеме данных переодически возникает искажение данных, иногда потеря. C чем это связано?

A__>Если соеденить контакты скрепкой, писать и читать одной программой — все работает идеально

длина кабеля тоже имеет значение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.