![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чтение и запись в COM-порт в Win XP/NT [D7]
nec © (2004-04-08 03:00:00)Помогите пожалуйста!!!
Я пишу прогу, которая должна посылать команды и считывать данные с прграммируемого контроллера через COM-порт. Под мастдай 98 прога работает, а NT/XP не дает читать и писать в порт. Реально ли реализовать чтение/запись под ХР/NT/2000 чисто средствами Делфа без подключения левых драйверов (прямого доступа)??? Если можно то как? Помогите чем сможете.
Заранее спасибо!!!
Jack128 (2004-04-11 17:32:00) [1]
> [15] GanibalLector © (11.04.04 16:58)
Хе, я использую только компоненты с исходниками, в случае чего всегда можно напильником обработать ;-)
GanibalLector (2004-04-11 16:58:00) [2]>Jack128
Да,возможно это дело вкуса.
Я и сам начинал работать с портом через компоненты серии TurboPower(под названием AsyncProf...).Но позже возникли некоторые сложности при реализации проекта.В часности,необходимо было ответить устройству в течении 2-5мсек. и все попытки сводились на НЕТ(с этим ПОГАНЫМ компонентом).Вот тогда я и начал юзать WimApi,естественно возникали сотни вопросов\ошибок,но со временем все уляглось и ЩА все ОК.
З.Ы. И еще,я как-то посмотрел работу этого компонента через PortMon.Я был просто в ужасе!!!С тех пор категорически НЕТ.
Jack128 (2004-04-11 13:31:00) [3]
> Та даже ты!!!Используешь TAsyncCommPortDriver,а зачем???
Могу расказать.
Первая моя программа - как работа с устройством через ком порт. Тогда я ни о каких апи, естественно не знал.. Скачал компонент TCommPortDriver и использовал его..Со временем я узнал, что оказывается существует такая вещь как апи, и можно использовать их для работы с портом, но меня это не впечетлило ибо нафиг? Я привык работать с этим компонентом, он меня всем устаивал..Некоторое время назад мне потребовался компонент для работы с портом открытым с флагом FILE_FLAG_OVERLAPPED. Интерфейс работы с портом, который предоставлял TCommPortDriver меня вполне устраивал, и я переписал иерархию так: TCustomCommPortDriver - в котором весь общий код (установка параметров порта (скорость, контроль четности и ежи с ними)) от него наследуются TSyncCommPortDriver и TAsyncCommPortDriver, в которых перекрываются базовые методы чтения/записи и коннект к порту..
По поводу не любви к апи: не всяк кто пользуется компонентами - не знает апи, если бы я не знал апи (в части работы с портами), то я бы никогда не смог написать свой компонентик.. Тут дело в другом - тебе скорее всего по нраву процедурное программирование, а мне ООП ;-)
GanibalLector (2004-04-11 13:11:00) [4]>А кто не взлюбил? ;-)
Та даже ты!!!Используешь TAsyncCommPortDriver,а зачем???
Jack128 (2004-04-11 11:59:00) [5]
> А че Вы так WinApi не взлюбили???
А кто не взлюбил? ;-)
GanibalLector (2004-04-11 02:17:00) [6]А че Вы так WinApi не взлюбили???
Все просто.Вот ложу пример:
function LStr(const Source:Ansistring;Count:Integer):Ansistring;
begin
Result:=Copy(Source,1,Count);
end;
function OpenComm(Mode:AnsiString):THandle;
var
DCB : TDCB;
TOut: TCommTimeouts;
I:Integer;
Bfr:AnsiString;
begin
Bfr:=Mode;
UniqueString(Bfr);
I:=Pos(':',Bfr)-1;
if I<=0 then I:=4;
Result := CreateFile(PChar(LStr(Bfr,I)),GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
GetCommState( Result, DCB) ;
BuildCommDCB(PChar(Bfr),DCB);
DCB.EvtChar := #13;
SetCommState( Result, DCB) ;
//
TOut.ReadIntervalTimeout := MAXDWORD;
TOut.ReadTotalTimeoutMultiplier := 0;
TOut.ReadTotalTimeoutConstant := 0;
TOut.WriteTotalTimeoutMultiplier := 0;
TOut.WriteTotalTimeoutConstant := 0;
SetCommTimeOuts( Result, TOut);
SetCommMask(Result,EV_RLSD OR EV_RXFLAG);
PurgeComm(Result,PURGE_TXCLEAR); //clear transmit buffer
PurgeComm(Result,PURGE_RXCLEAR); //clear receive buffer
end;
function ReadComm(Handle:THandle; var Bfr:AnsiString):Integer;
var
I,J:DWord;
begin
Result:=0;
J:=Length(Bfr);
repeat
ReadFile(Handle, Bfr[Result+1], J-DWord(Result), I, nil);
Inc(Result,Integer(I));
if DWord(Result)=J then break;
until I=0;
end;
function WriteComm(Handle:THandle; const Bfr:AnsiString):Integer;
var
I,J:DWord;
begin
Result:=0;
J:=Length(Bfr);
repeat
WriteFile(Handle, Bfr[Result+1], J-DWord(Result), I, nil);
Inc(Result,Integer(I));
if DWord(Result)=J then break;
until I=0;
end;
function CloseComm(Handle:THandle):boolean;
begin
CloseHandle(Handle);
result:=true;
end;
function SetRxTime(Handle:THandle; const TimeC,TimeM:Integer):Boolean;
var
TOut:TCommTimeouts;
begin
if (TimeC=0) AND (TimeM=0) then
TOut.ReadIntervalTimeout := MAXDWORD
else TOut.ReadIntervalTimeout := 0;
TOut.ReadTotalTimeoutMultiplier := TimeM;
TOut.ReadTotalTimeoutConstant := TimeC;
TOut.WriteTotalTimeoutMultiplier := 0;
TOut.WriteTotalTimeoutConstant := 0;
Result:=SetCommTimeOuts(Handle, TOut);
end;
Вызывать так :
...
Handle:=OpenComm('COM'+co+':BAUD='+baud+' PARITY=N DATA=8 STOP=1');
if Handle=INVALID_HANDLE_VALUE then begin result:=false;exit;end;
setrxtime(handle,100,25);
...
Atrebuncev (2004-04-10 18:23:00) [7]Есть специальные компоненты для работы с COM-портами. Один из лучших - Comdrw32 (их сайт http://www.mdlive.com/d3k/delphi4). там уже все написано и таймауты в том числе. А с АСМ конечно не надо дергаться. Это уже язык только микроконтроллеров, да и то пока у них память маленькая.
Jack128 (2004-04-10 17:06:00) [8]У-у-у как все запущено.. ;-)
TAsyncCommPortDriver - это мой компонентик для работы ком портами, основан на TCommPortDriver©Marco Cocco (советую скачать, вроде тут в кладовке валялся, на torry.net - точно есть)
Этот код я просто выдрал для примера...
P.S. Учи Object pascal - без него в Delphi никак
nec (2004-04-10 16:55:00) [9]Jack182'у
Пожалуйста объясни, что есть TAsyncCommPortDriver.... Делфа на него ругается.
jack128 (2004-04-10 12:01:00) [10]И если последуешь совету Лектора, то почитай про настройку таймаутов. Обычно это больная тема
GanibalLector (2004-04-10 00:49:00) [11]>>>Nec
убери FILE_FLAG_OVERLAPPED и поставь FILE_ATTRIBUTE_NORMAL.
jack128 (2004-04-09 11:13:00) [12]type
TTransferFunc = function (Handle: THandle; DataPtr: Pointer;
MaxDataSize: DWORD; var lpNumberOfBytesTranser: DWORD;
lpOverlapped: POverlapped): BOOL; stdcall;
TTransferDirection = (tdRead, tdWrite);
const
TransferFuncs: array[TTransferDirection] of Pointer = (@ReadFile, @WriteFile);
function TAsyncCommPortDriver.TransferData(Direction: TTransferDirection;
DataPtr: pchar; DataSize, Timeout: DWORD): DWORD;
var
nTransfer: DWORD;
ov: TOverlapped;
bTransferCompleted: boolean;
begin
// Do nothing if port has not been opened
Result := 0;
if not Connected then
exit;
bTransferCompleted := True;
// Pause polling
PausePolling;
try
if not Assigned(FEvent) then
FEvent := TEvent.Create(nil, False, False, '');
ZeroMemory(@ov, SizeOf(ov));
ov.hEvent := FEvent.Handle;
bTransferCompleted :=
TTransferFunc(TransferFuncs[Direction])(FHandle, DataPtr, DataSize, nTransfer, @ov);
if not bTransferCompleted and (GetLastError <> ERROR_IO_PENDING) then
begin
// Передача данных закончена, а то что с ошибкой, ну дык, что поделаешь..
bTransferCompleted := True;
Exit;
end;
Result := nTransfer;
while True do
begin
FEvent.WaitFor(Timeout);
bTransferCompleted := GetOverlappedResult(FHandle, ov, nTransfer, False);
// Если нечего не прочитали/записали с прошлого раза, то на выход...
if nTransfer = Result then Exit;
Result := nTransfer;
if bTransferCompleted then Exit;
end;
finally
if not bTransferCompleted then Cancel;
// Continue polling
ContinuePolling;
end;
end;
function TAsyncCommPortDriver.ReadDataEx(DataPtr: pchar; MaxDataSize,
Timeout: DWORD): DWORD;
begin
Result := TransferData(tdRead, DataPtr, MaxDataSize, Timeout);
end;
function TAsyncCommPortDriver.SendDataEx(DataPtr: pchar; DataSize,
Timeout: DWORD): DWORD;
begin
Result := TransferData(tdWrite, DataPtr, DataSize, Timeout);
end;
nec (2004-04-09 01:59:00) [13]Sorry за глупую опечатку:-)
Если быть точнее:
CreateFile('COM1',GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
nec (2004-04-09 01:52:00) [14]Gорт инициализирую стандартом, через CreateFile(...
tesseract (2004-04-08 13:36:00) [15]Рекомендуется к прочтению книга "Последовательные интерфейсы ПК. Практика программирования". О ней можно в "Книгах" прочитать.
только цена её пониже - на Совке 199 р.
GanibalLector (2004-04-08 03:04:00) [16]У меня все работает.
Сразу возникает вопрос, как написано???Если через асемблерные вставки,то и не будет.А если на чистом WinApi , то
покажи как инициализируешь порт(обычно там траблы)!
Да и вообще,PortMon-рулит!!!Запускай и смотри.