SetCommMask( CommHandle_01,EV_TXEMPTY);
DCBCommport_01.Parity=MARKPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
TransMask=0;
WriteFile(CommHandle_01,Transmit_01,1,&KolByte,&Ovr_w_01);
Sleep(1);
WaitCommEvent( CommHandle_01,&TransMask,&Ovr_w_01);
if ((TransMask & EV_TXEMPTY)==EV_TXEMPTY )
{
DCBCommport_01.Parity=SPACEPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
// WriteFile(CommHandle_01,&(Transmit_01[1]),kol_pered-1,&KolByte,&Ovr_w_01);
}
проблема с COM портом
проблем не было на медленных машинах. на быстрых возникла проблема.
делаю так
Код:
пока не добавляется задержка (закоментированный Sleep) осциллографом вижу , что бит четности не переустанавливается. т.е SPACEPARITY забивает предыдущий MARKPARITY.
программно все работает.
пробовал другие проверки
WaitForSingleObject,GetOverlappedResult - что байт ушел
GetCommState что перезапись произошла. программно все работает , на осциллографе пока нет задержки бита четности нет.
помогите разобраться с вопросом.
А когда ты используешь задержку - все ок, первый отправился, из буфера ушел, поменялись настройки, второй ушел - и т.д.
При использовании стандартного драйвера COM-порта в Линуксе у меня было несколько вариантов решения проблемы. Дело в том, что такое поведение порта можно несколько изменить, например:
1. при изменении настроек все текущие байты в буфере удалить, а потом применять новые настройки (навряд ли этот вариант тебе подойдет :) )
2. при изменении настроек сначала дождаться, пока все содержимое буфера уйдет, а потом применять новые настройки - скорее всего этот вариант тебя устроит.
У меня это настраивалось программно настройками порта. В чем и как программируешь ты, я не знаю, поэтому читай доку к своим средствам программироания.
ЗЫ. При использовании второго варианта есть одно но - если настройки меняются часто, то возможна большая (относительно) задержка между байтами, которая связана с временем ожидания опустошения буфера каждый раз при изменении настроек - меня, например, это никак не устраивало, пришлось писать свой драйвер.
Цитата: Iceman
2. при изменении настроек сначала дождаться, пока все содержимое буфера уйдет, а потом применять новые настройки - скорее всего этот вариант тебя устроит.
не просто устроит, а так и делается. но , к сожалению, ни к чему хорошему эта проверка не приводит.
EV_TXEMPTY проверяется был ли передан последний символ из буфера и программно буфер чист.
ClearCommError проверял число символов в передающем буфере. было =0
GetOverlappedResult проверял количество переданных и =1.
и только после этого менялся бит четности.
http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1126 . Там, среди всего прочего, написано, что проверять только по EV_TXEMPTY пустоту буфера нельзя, так как это событие показывает, что в буфер можно дописать байты, а не то, что он пуст.
И вот еще кое-что с того же сайта - http://www.delphikingdom.com/asp/answer.asp?IDAnswer=41030, возможно, станет полезным...
Вот нашел одну любобытную статейку -
И вот еще кое-что с того же сайта - http://www.delphikingdom.com/asp/answer.asp?IDAnswer=41030, возможно, станет полезным...
Код:
GetCommState(CommHandle_01,&DCBCommport_01);
DCBCommport_01.Parity=MARKPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
if (!WriteFile(CommHandle_01,Transmit_01,1,&KolByte,&Ovr_w_01))
if (GetLastError() != ERROR_IO_PENDING ) { Memo1->Lines->Add("ошибка записи");}
else
{
dwait=WaitForSingleObject(Ovr_w_01.hEvent,1);
switch (dwait)
{ case WAIT_OBJECT_0 :
{
if (!GetOverlappedResult(CommHandle_01,&Ovr_w_01,&Kols_01,false))
{
if (GetLastError() != ERROR_IO_INCOMPLETE ) Memo1->Lines->Add("незавершение записи");
}
else{
if (Kols_01==1){
//Sleep(1);
DCBCommport_01.Parity=SPACEPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
}
}
break;
}
case WAIT_TIMEOUT :{
break;
}
case WAIT_FAILED : {
// break;
}
} //switch
} //else
ResetEvent(Ovr_w_01.hEvent);
DCBCommport_01.Parity=MARKPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
if (!WriteFile(CommHandle_01,Transmit_01,1,&KolByte,&Ovr_w_01))
if (GetLastError() != ERROR_IO_PENDING ) { Memo1->Lines->Add("ошибка записи");}
else
{
dwait=WaitForSingleObject(Ovr_w_01.hEvent,1);
switch (dwait)
{ case WAIT_OBJECT_0 :
{
if (!GetOverlappedResult(CommHandle_01,&Ovr_w_01,&Kols_01,false))
{
if (GetLastError() != ERROR_IO_INCOMPLETE ) Memo1->Lines->Add("незавершение записи");
}
else{
if (Kols_01==1){
//Sleep(1);
DCBCommport_01.Parity=SPACEPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);
}
}
break;
}
case WAIT_TIMEOUT :{
break;
}
case WAIT_FAILED : {
// break;
}
} //switch
} //else
ResetEvent(Ovr_w_01.hEvent);
так вот там , где стоит sleep это место окончания операции записи. а на самом деле это не так. без задержки не работает.
по ходу исследования с различными портами возник еще один вопрос : про переобозначении порта для СОМ1..СОМ9 все переобозначается и работает. а вот при СОМ10 и более
порт не открывается по ERROR_FILE_NOT_FOUND
CommHandle_01 = CreateFile("COM12",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED ,NULL);
if (CommHandle_01 == INVALID_HANDLE_VALUE )
{
LastError=GetLastError();
if (LastError==ERROR_FILE_NOT_FOUND) {}
}
как с этим пробороться?