Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2004.05.23;
Скачать: [xml.tar.bz2];

Вниз

Чтение и запись в 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.036 c
7-1082149888
Сащок
2004-04-17 01:11
2004.05.23
Регистрация файлов


4-1081318448
DennisLNC
2004-04-07 10:14
2004.05.23
Mutex


14-1083666223
StudentOn
2004-05-04 14:23
2004.05.23
Apache со стороны Delphi


3-1083093062
Realist
2004-04-27 23:11
2004.05.23
<<< Общение между двумя БД в реальном времени >>>


3-1082970542
Ant
2004-04-26 13:09
2004.05.23
Графики Ганнта





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский