Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.23;
Скачать: CL | DM;

Вниз

Чтение и запись в COM-порт в Win XP/NT   Найти похожие ветки 

 
nec   (2004-04-08 03:00) [0]

Помогите пожалуйста!!!
Я пишу прогу, которая должна посылать команды и считывать данные с прграммируемого контроллера через COM-порт. Под мастдай 98 прога работает, а NT/XP не дает читать и писать в порт. Реально ли реализовать чтение/запись под ХР/NT/2000  чисто средствами Делфа без подключения левых драйверов (прямого доступа)??? Если можно то как? Помогите чем сможете.
Заранее спасибо!!!


 
GanibalLector ©   (2004-04-08 03:04) [1]

У меня все работает.
Сразу возникает вопрос, как написано???Если через асемблерные вставки,то и не будет.А если на чистом WinApi , то
покажи как инициализируешь порт(обычно там траблы)!
Да и вообще,PortMon-рулит!!!Запускай и смотри.


 
tesseract ©   (2004-04-08 13:36) [2]

Рекомендуется к прочтению книга "Последовательные интерфейсы ПК. Практика программирования". О ней можно в "Книгах" прочитать.
только цена её пониже - на Совке 199 р.


 
nec   (2004-04-09 01:52) [3]

Gорт инициализирую стандартом, через CreateFile(...


 
nec   (2004-04-09 01:59) [4]

Sorry за глупую опечатку:-)
Если быть точнее:
CreateFile("COM1",GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);


 
jack128 ©   (2004-04-09 11:13) [5]

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;


 
GanibalLector ©   (2004-04-10 00:49) [6]

>>>Nec
убери FILE_FLAG_OVERLAPPED и поставь FILE_ATTRIBUTE_NORMAL.


 
jack128 ©   (2004-04-10 12:01) [7]

И если последуешь совету Лектора, то почитай про настройку таймаутов. Обычно это больная тема


 
nec   (2004-04-10 16:55) [8]

Jack182"у

Пожалуйста объясни, что есть TAsyncCommPortDriver.... Делфа на него ругается.


 
Jack128 ©   (2004-04-10 17:06) [9]

У-у-у как все запущено.. ;-)
TAsyncCommPortDriver - это мой компонентик для работы ком портами, основан на TCommPortDriver©Marco Cocco  (советую скачать, вроде тут в кладовке валялся, на torry.net - точно есть)

Этот код я просто выдрал для примера...

P.S. Учи Object pascal - без него в Delphi никак


 
Atrebuncev   (2004-04-10 18:23) [10]

Есть специальные компоненты для работы с COM-портами. Один из лучших - Comdrw32 (их сайт http://www.mdlive.com/d3k/delphi4). там уже все написано и таймауты в том числе. А с АСМ конечно не надо дергаться. Это уже язык только  микроконтроллеров, да и то пока у них память маленькая.


 
GanibalLector ©   (2004-04-11 02:17) [11]

А че Вы так 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);
...


 
Jack128 ©   (2004-04-11 11:59) [12]


> А че Вы так WinApi не взлюбили???
А кто не взлюбил? ;-)


 
GanibalLector ©   (2004-04-11 13:11) [13]

>А кто не взлюбил? ;-)

Та даже ты!!!Используешь TAsyncCommPortDriver,а зачем???


 
Jack128 ©   (2004-04-11 13:31) [14]


> Та даже ты!!!Используешь TAsyncCommPortDriver,а зачем???

Могу расказать.

Первая моя программа - как работа с устройством через ком порт. Тогда я ни о каких апи, естественно не знал.. Скачал компонент TCommPortDriver и использовал его..Со временем я узнал, что оказывается существует такая вещь как апи, и можно использовать их для работы с портом, но меня это не впечетлило ибо нафиг? Я привык работать с этим компонентом, он меня всем устаивал..Некоторое время назад мне потребовался компонент для работы с портом открытым с флагом FILE_FLAG_OVERLAPPED. Интерфейс работы с портом, который предоставлял TCommPortDriver меня вполне устраивал, и я переписал иерархию так: TCustomCommPortDriver - в котором весь общий код (установка параметров порта (скорость, контроль четности и ежи с ними)) от него наследуются TSyncCommPortDriver и TAsyncCommPortDriver, в которых перекрываются базовые методы чтения/записи и коннект к порту..

По поводу не любви к апи: не всяк кто пользуется компонентами - не знает апи, если бы я не знал апи (в части работы с портами), то я бы никогда не смог написать свой компонентик.. Тут дело в другом - тебе скорее всего по нраву процедурное программирование, а мне ООП ;-)


 
GanibalLector ©   (2004-04-11 16:58) [15]

>Jack128
Да,возможно это дело вкуса.

Я и сам начинал работать с портом через компоненты серии TurboPower(под названием AsyncProf...).Но позже возникли некоторые сложности при реализации проекта.В часности,необходимо было ответить устройству в течении 2-5мсек. и все попытки сводились на НЕТ(с этим ПОГАНЫМ компонентом).Вот тогда я и начал юзать WimApi,естественно возникали сотни вопросов\ошибок,но со временем все уляглось и ЩА все ОК.
З.Ы. И еще,я как-то посмотрел работу этого компонента через PortMon.Я был просто в ужасе!!!С тех пор категорически НЕТ.


 
Jack128 ©   (2004-04-11 17:32) [16]


> [15] GanibalLector ©   (11.04.04 16:58)
Хе, я использую только компоненты с исходниками, в случае чего всегда можно напильником обработать ;-)



Страницы: 1 вся ветка

Текущий архив: 2004.05.23;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.058 c
14-1083837700
syte_ser78
2004-05-06 14:01
2004.05.23
Исходник текстового окна со скротол


1-1083999590
Федя Мегатронов
2004-05-08 10:59
2004.05.23
Как вклинить прогрессбар в программу ?


1-1084029702
DDA
2004-05-08 19:21
2004.05.23
PByteArray


14-1083161865
FlankerX
2004-04-28 18:17
2004.05.23
NET Framework


1-1084267650
Andrey79
2004-05-11 13:27
2004.05.23
Шрифт для Code Editor