Добрый день всем. При работе с ком-портом наступил на грабли и нормального решения пока не нашёл. Проблема собственно в том, что если я на ком-порт отправляю запрос с верным завершающим символом, тогда всё ок, но если с "неверным" завершающим символом - ответ не получаю что естественно и все последующие команды висят. Но если порт закрою и наново открою, указав необходимый символ конца строки - запросы всё равно висят и не обрабатываются.
ЗЫ: советы мол не отправляй "левые" символы - не вариант, ибо если какое-то "тело" отправит команду на порт с неверным символом в конце, то моя программа перестаёт работать до ребута устройства, а хочется что бы программе даже кривые руки Юзверя не мешали.
ЗЫЫ: то что порт даже после "кривых" запросах может начать адекватно работать - это факт, ибо другое ПО успешно отправляет/получает данные на порт.
Код инициализации:
Код:
CommHandle := CreateFile(PChar('\\.\'+Port),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);
PurgeComm(CommHandle,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
SetCommMask(CommHandle,EV_RXFLAG);
GetCommState(CommHandle,DCB);
DCB.BaudRate:=CBR_115200;
DCB.Parity:=NOPARITY;
DCB.EofChar:=#0;
DCB.ErrorChar:=#0;
DCB.ByteSize:=8;
DCB.StopBits:=OneStopBit;
DCB.EvtChar:=EvtChar;//задание символа для флага
DCB.XonChar:=#$11;
DCB.XoffChar:=#$13;
DCB.XonLim:=8192;
DCB.XoffLim:=51200;
SetCommState(CommHandle,DCB);
lpCommTimeouts.ReadIntervalTimeout:=-1;
lpCommTimeouts.ReadTotalTimeoutMultiplier:=-1;
lpCommTimeouts.ReadTotalTimeoutConstant:=500;
lpCommTimeouts.WriteTotalTimeoutMultiplier:=1;
lpCommTimeouts.WriteTotalTimeoutConstant:=50;
SetCommTimeouts(CommHandle,lpCommTimeouts);
SetupComm(CommHandle,4096,4096);
CommThread := CreateThread(nil,0,@ReadComm,nil,0,ThreadID);
Параметры порта именно такие, т.к. получил их при помощи снифера порта и стороннего ПО по работе с портом.
запись в порт:
Код:
WriteFile(CommHandle,Transmit,Kol,Kol,@Ovr);
PurgeComm(CommHandle,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
z:=0;
repeat
Sleep(1);
Inc(z);
until (msg_ans<>'') or (z>500);
z - защита от зависания, может есть другие методы, но мне ничего другого не пришло в голову да и этот метод безотказно работает, хотя есть риски запуска моего ПО на древнем железе где 500мс будет маловато...
Считывание
Код:
while true do
begin
TransMask:=0;
WaitCommEvent(CommHandle,TransMask,@Ovr); //ждем
if (TransMask and EV_RXFLAG)=EV_RXFLAG then //проверяем нужное событие
begin
ClearCommError(CommHandle,Errs,@Stat);//сбрасываем флаг
Kols := Stat.cbInQue;
ReadFile(CommHandle,Resive,Kols,Kols,@Ovr);//читаем
msg_ans:=Resive;
ansver:=1;
end;//mask
end;//while