FireBoy » Пт дек 19, 2008 8:35 am
Предыстория:
Есть компьютер, который работает с оборудованием, подключенному к COM-порту. Есть программа, написанная на Delphi. Все работает нормально.
Далее была дана задача переместить на сервер терминалов (Win2003). При подключении к нему, ставлю галочку «Подключать последовательные порты». Подключился. Запускаю стандартную программу, которая поставлялась с оборудованием. Все работает. Запускаю свою программу – не работает.
А теперь вопрос:
При запуске программы есть функция открыть порт, все нормально. Далее при приеме данных ничего не выдает, будто не видит данные. Даже если данных нет, все равно что-то с порта берет (проверял локально).
Может при открытии порта нужно указывать дополнительные опции? Или при сервере с ОС Win2003, нужно как-то по-другому считывать данные с порта? Или может еще что-нибудь. Подскажите, пожалуйста.
Процедура открытия порта:
Код: Выделить всё
function OpenComm(Num : integer; var Com_Var : TComVar) : boolean;
var
ThreadId : DWord;
TimeOuts : TCommTimeouts;
begin
Result := False;
with Com_Var do begin
//получаем хэндл
cId := CreateFile(PChar('\\.\COM' + IntToStr(Num)),
GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if cId = INVALID_HANDLE_VALUE then Exit;
//устанавливаем маску эвентов
if not (SetCommMask(cId,EV_RXCHAR or EV_DSR or EV_CTS) and
//устанавливаем длину буферов ввода-вывода драйвера
SetupComm(cId,512,512) and
//очищаем все и вся
PurgeComm(cId,PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR) and
//записываем DCB
SetCommState(cId,DCB))
then begin
CloseHandle(cId);
Exit;
end;
//настраиваем таймауты на немедленный возврат из Read(Write)File
TimeOuts.ReadIntervalTimeout := 50;
TimeOuts.ReadTotalTimeoutMultiplier := 1;
TimeOuts.ReadTotalTimeoutConstant := 300;
TimeOuts.WriteTotalTimeoutMultiplier := 1;
TimeOuts.WriteTotalTimeoutConstant := 300;
//записываем таймауты
SetCommTimeouts(cId,TimeOuts);
//опускаем флаг завершения дочернего потока
Terminated := False;
//стартуем дочерний поток, функция потока - WorkComm
CommThread := CreateThread(nil,0,@WorkComm,@Com_Var,0,ThreadID);
if CommThread = 0 then begin
CloseHandle(cId);
Exit;
end;
//устанавливаем приоритет дочернего потока
SetThreadPriority(CommThread,8);
Result := True;
end;
end;
[/size]
Процедура работы с портом:
Код: Выделить всё
function WorkComm(var Parms : TComVar) : longint; stdcall;
var
Kols, Mask,Trans,Errs : DWord;
Ovr : TOverlapped;
Buff : array [0..255] of byte;
Reciv : pointer;
begin
Result := 0;
//инициализируем TOverlapped структуру
FillChar(Ovr,SizeOf(TOverlapped),0);
Ovr.hEvent := CreateEvent(nil,TRUE,FALSE,#0);
//стартуем бесконечный цикл
while not Parms.Terminated do with Parms do begin
if Terminated then break;
Mask := 0;
//запрашиваем (ожидаем) маску эвентов
if not WaitCommEvent(cId,Mask,@Ovr) then begin
//обрабатываем "отложенную" операцию ввода-вывода
//не задумывался о ее смысле, просто откуда то содрал
if GetLastError() = ERROR_IO_PENDING
then GetOverlappedResult(cId,Ovr,Trans,True);
end;
//очищаем ошибки с получением статуса порта, обязательно!!!
ClearCommError(cId,Errs,@Stat);
if Terminated then break;
if Mask = 0 then continue;
if (Mask and EV_RXCHAR) = EV_RXCHAR then begin
//если принят хотя бы один байт
if Stat.cbInQue < 512
then Kols := Stat.cbInQue
else Kols := 512;
if Terminated then break;
//пытаемся читать принятые байты
ReadFile(cId,Buff,Kols,Kols,@Ovr);
if Terminated then break;
//////////////////////// в данном месте Kols = 0.
if Kols > 0 then begin
//если хоть один байт считан - переносим в буфер накопления
GetMem(Reciv,kols);
Move(Buff,Reciv^,kols);
//шлем сообщение основному потоку
PostMessage(fmMain.Handle,cmRxByte,integer(Reciv),kols);
end;
end;
end;
CloseHandle(Ovr.hEvent);
end;
[/size]
[b]Предыстория:[/b]
Есть компьютер, который работает с оборудованием, подключенному к COM-порту. Есть программа, написанная на Delphi. Все работает нормально.
Далее была дана задача переместить на сервер терминалов (Win2003). При подключении к нему, ставлю галочку «Подключать последовательные порты». Подключился. Запускаю стандартную программу, которая поставлялась с оборудованием. Все работает. Запускаю свою программу – не работает.
[b]А теперь вопрос:[/b]
При запуске программы есть функция открыть порт, все нормально. Далее при приеме данных ничего не выдает, будто не видит данные. Даже если данных нет, все равно что-то с порта берет (проверял локально).
Может при открытии порта нужно указывать дополнительные опции? Или при сервере с ОС Win2003, нужно как-то по-другому считывать данные с порта? Или может еще что-нибудь. Подскажите, пожалуйста.
[b]Процедура открытия порта:[/b]
[size=150][code]function OpenComm(Num : integer; var Com_Var : TComVar) : boolean;
var
ThreadId : DWord;
TimeOuts : TCommTimeouts;
begin
Result := False;
with Com_Var do begin
//получаем хэндл
cId := CreateFile(PChar('\\.\COM' + IntToStr(Num)),
GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if cId = INVALID_HANDLE_VALUE then Exit;
//устанавливаем маску эвентов
if not (SetCommMask(cId,EV_RXCHAR or EV_DSR or EV_CTS) and
//устанавливаем длину буферов ввода-вывода драйвера
SetupComm(cId,512,512) and
//очищаем все и вся
PurgeComm(cId,PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR) and
//записываем DCB
SetCommState(cId,DCB))
then begin
CloseHandle(cId);
Exit;
end;
//настраиваем таймауты на немедленный возврат из Read(Write)File
TimeOuts.ReadIntervalTimeout := 50;
TimeOuts.ReadTotalTimeoutMultiplier := 1;
TimeOuts.ReadTotalTimeoutConstant := 300;
TimeOuts.WriteTotalTimeoutMultiplier := 1;
TimeOuts.WriteTotalTimeoutConstant := 300;
//записываем таймауты
SetCommTimeouts(cId,TimeOuts);
//опускаем флаг завершения дочернего потока
Terminated := False;
//стартуем дочерний поток, функция потока - WorkComm
CommThread := CreateThread(nil,0,@WorkComm,@Com_Var,0,ThreadID);
if CommThread = 0 then begin
CloseHandle(cId);
Exit;
end;
//устанавливаем приоритет дочернего потока
SetThreadPriority(CommThread,8);
Result := True;
end;
end;
[/code][/size]
[b]Процедура работы с портом:[/b]
[size=150][code]function WorkComm(var Parms : TComVar) : longint; stdcall;
var
Kols, Mask,Trans,Errs : DWord;
Ovr : TOverlapped;
Buff : array [0..255] of byte;
Reciv : pointer;
begin
Result := 0;
//инициализируем TOverlapped структуру
FillChar(Ovr,SizeOf(TOverlapped),0);
Ovr.hEvent := CreateEvent(nil,TRUE,FALSE,#0);
//стартуем бесконечный цикл
while not Parms.Terminated do with Parms do begin
if Terminated then break;
Mask := 0;
//запрашиваем (ожидаем) маску эвентов
if not WaitCommEvent(cId,Mask,@Ovr) then begin
//обрабатываем "отложенную" операцию ввода-вывода
//не задумывался о ее смысле, просто откуда то содрал
if GetLastError() = ERROR_IO_PENDING
then GetOverlappedResult(cId,Ovr,Trans,True);
end;
//очищаем ошибки с получением статуса порта, обязательно!!!
ClearCommError(cId,Errs,@Stat);
if Terminated then break;
if Mask = 0 then continue;
if (Mask and EV_RXCHAR) = EV_RXCHAR then begin
//если принят хотя бы один байт
if Stat.cbInQue < 512
then Kols := Stat.cbInQue
else Kols := 512;
if Terminated then break;
//пытаемся читать принятые байты
ReadFile(cId,Buff,Kols,Kols,@Ovr);
if Terminated then break;
//////////////////////// в данном месте Kols = 0.
if Kols > 0 then begin
//если хоть один байт считан - переносим в буфер накопления
GetMem(Reciv,kols);
Move(Buff,Reciv^,kols);
//шлем сообщение основному потоку
PostMessage(fmMain.Handle,cmRxByte,integer(Reciv),kols);
end;
end;
end;
CloseHandle(Ovr.hEvent);
end;
[/code]
[/size]