Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Comm Port под Vista AMDx64


Delion ©   (2009-03-22 14:47:00) 

Здравствуйте товарищи программисты

Есть проблемка, ни как решить не могу.

Вобщем у меня Vista 64 битная, дык под ней программы которые пишу на Delphi 10 для обработки RS-232 не хотят работать, либо не считывают данные, либо вовсе выдают ошибки.

Брал исходняки и с этого сайта и сдругих, шо только не пробовал.

Может кто занимался бодобным делом, знает какие-нибудь стать по этому поводу или примеры программ.

Заранее благодарю за любую помощь.


Delion   (2009-03-26 13:04:00) [1]

Спасибо вам всем за помощь.

Нашёл в чём заключалась ошибка.

у меня девайс работает при:

DCB.Flags    := (Bin:00000000000000000001000000000001)


Delion   (2009-03-26 09:54:00) [2]


> ошибок никаких нет


Я имею ввиду нет ошибки на запись, а lpErrorsвсё равно выдают 16 ошибку


Delion   (2009-03-26 09:52:00) [3]


if WaitCommEvent (ComH,lpEvtMask,@Overlapped) then
     if Terminated then Break;

     if not ClearCommError(ComH,lpErrors,@lpStat) then raise Exception.Create('Error clearing port');
     if lpErrors<>0 then raise Exception.Create(IntToStr(lpErrors));


В lpErrors16 ошибка о чём это может говорить?

Причём это происходит на первом же цикле.

А если я вставлю код на запись перед WaitCommEvent:


SetLength(Buf, 10);
if (not WriteFile(ComH, Buf[0], Length(Buf),  lpErrors, @Overlapped)) and
  (GetLastError <> ERROR_IO_PENDING) then  raise Exception.Create('Error writing port');


то всё нормально и ошибок никаких нет.


Вариант   (2009-03-25 12:18:00) [4]


> Delion   (25.03.09 10:15) [5]


> if not GetOverlappedResult(ComH,Overlapped,lpErrors,false)
> then raise Exception.Create('Error GetOverlappedResult');
>
>      if lpErrors<>0 then raise Exception.Create(IntToStr(lpErrors));
>  //ERROR_TOO_MANY_OPEN_FILES = 4;
>
> Во время выполнения стопится на строке где подписанно: ERROR_TOO_MANY_OPEN_FILES
> и код ошибки 4.


К чему в данном месте делать проверку if lpErrors<>0?


> И ещё хочу уточнить если WaitCommEvent выполнилась правильно
> она что должна вернуть True или False.



> походу я ваще не въезжаю как и в каком порядке надо обрабатывать
> команды. Скока не смотрел примеры там вроде так примерно
> описанно.


А вопрос и непрост, особенно когда в первый раз начинаешь разбираться.
Главное найти документацию, примеры, описание

Советую поискать  книги по программированию Com портов.
Одного из авторов помню -  Агуров Павел. Пощите гуглом. Или в магазинах.
По поводу синхронного и OVERLAPPED режимов - у него же вроде написано.

Кроме того вариант - overlapped I/O в MSDN.

По вызову функций, параметрам и возвращаемым результатам  - MSDN или help Win SDK  в дельфи очень помогают.

Так же советую сопоставлять с описанием функций в pas файлах. В данном случае посмотрите как описана функция в Windows.pas - тоже даст ответы на  ваши вопросы (что и как возвращает например).

Сайт www.delphikingdom.com -там были статьи по работе с COM портами.


Alex1234   (2009-03-25 10:22:00) [5]

Очень похоже вот на этот исходник

http://articles.org.ru/docum/comport.php


Delion   (2009-03-25 10:15:00) [6]

Вобщем я немного переписал код потока вот он:


procedure TCommTh.Execute;
var
 lpEvtMask: DWORD;
 lpErrors: DWORD;
 lpStat: TComStat;
 Overlapped:TOverlapped;
begin
 SetName;
 { Place thread code here }
FreeOnTerminate:=True;
FillChar(Overlapped,SizeOf(TOverlapped),0);
Overlapped.hEvent:=CreateEvent(nil, True, False, #0);
if Overlapped.hEvent=0 then raise Exception.Create('Error Create Event');

while not Terminated  do
 begin
   lpEvtMask:=0;
   lpErrors:=0;
   if (not WaitCommEvent (ComH,lpEvtMask,@Overlapped))and(GetLastError=ERROR_IO_PENDING) then
     if WaitForSingleObject(Overlapped.hEvent, INFINITE)=WAIT_OBJECT_0 then
       if not GetOverlappedResult(ComH,Overlapped,lpErrors,false) then raise Exception.Create('Error GetOverlappedResult');
     if lpErrors<>0 then raise Exception.Create(IntToStr(lpErrors)); //ERROR_TOO_MANY_OPEN_FILES = 4;
     if Terminated then Break;

     if not ClearCommError(ComH,lpErrors,@lpStat) then raise Exception.Create('Error clearing port');
     if lpErrors<>0 then raise Exception.Create(IntToStr(lpErrors));
     if (lpEvtMask and (EV_RXCHAR or EV_TXEMPTY))=(EV_RXCHAR or EV_TXEMPTY) then
       begin
       //********************************
       SetLength(Buf, lpStat.cbInQue);
       //********************************
       if not ReadFile(ComH,Buf[0],lpStat.cbInQue,lpStat.cbInQue,@Overlapped) then raise Exception.Create('Error reading port');
       if GetLastError<>0 then raise Exception.Create('Error:'+IntToStr(GetLastError));
       if Length(Buf)>0 then PostMessage(ComPortfrm.Handle,WM_USER,Buf[2],lpStat.cbInQue);
       end;
  if not PurgeComm(ComH,PURGE_RXABORT or PURGE_RXCLEAR or PURGE_TXABORT or PURGE_TXCLEAR) then raise Exception.Create('Error purging port');
  end;
 
end;


Во время выполнения стопится на строке где подписанно: ERROR_TOO_MANY_OPEN_FILESи код ошибки 4.


> Порт открываете с флагом FILE_FLAG_OVERLAPPED, а WaitCommEvent
> и ReadFile используется как при  синхронной работе с портом
> (@Overlapped в коде я вижу, но логика работы так прописывается
> при синхронной работе).


А нет примерчика как правильно работать в асинхронном режиме?
походу я ваще не въезжаю как и в каком порядке надо обрабатывать команды. Скока не смотрел примеры там вроде так примерно описанно.

И ещё хочу уточнить если WaitCommEvent выполнилась правильно она что должна вернуть Trueили False.


> Или не используйте OVERLAPPED режим


пробовал, без этого режима прога ваще виснет на закрытии порта, а обработка в игноре.


Вариант   (2009-03-25 06:36:00) [7]


> Delion   (24.03.09 10:42) [2]


Порт открываете с флагом FILE_FLAG_OVERLAPPED, а WaitCommEvent и ReadFile используется как при  синхронной работе с портом (@Overlapped в коде я вижу, но логика работы так прописывается при синхронной работе).  

Как уже писали  выше  - используйте GetOverlappedResult и/или WaitForXXX функции. Или не используйте OVERLAPPED режим. У вас сейчас логика работы написана именно без него.

Далее, допустим вы исправили ошибки указанные выше, но  вы указываете маски ожидания событий EV_RXCHAR or EV_TXEMPTY, а у вас в коде нет анализа причин возникновения событий порта. Что произошло, какое событие - получен байт, конец записи.....?
Далее -  функция WaitCommEvent возвращает результат. Нужен его анализ.

Кроме анализа на успех или неуспех,обычно нужен и анализ причины возникновения ошибки. У вас нигде нет вызова GetLastError. Так как ReadFile например может вернуть false в разных вариантах, а не только при ERROR_IO_PENDING...  Так же интересно знать, почему программа не смогла открыть порт. Да и в других случаях анализ кодов ошибок часто позволяет найти ошибки в своем коде.

ClearCommError - кстати тоже может вернуть ошибки, как свою ошибку, так и ошибку работы порта (например ошибку фрейма). Это все тоже требует анализа.


tesseract   (2009-03-24 11:11:00) [8]

Возможно порт не закрываешь правильно. Или события у тебя зависают. Так же try...except и крит секции не используешь. GetOverlappedREsult вообще не вижу в твоей программе.


Delion   (2009-03-24 10:42:00) [9]


> какие


- иногда ошибки открытия порта, хотя порт явно не занят.
- Ошибка передачи параметра.
- Ошибки чтения данных ввиде ни какой реакции на устройство подсоединённое к Com порту, или при инициализации Com порта выдаст один случайно прочитанный байт и заглохнет.

Вот как происходит инициализация:

ComH:=CreateFile(PAnsiChar('Com3'), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

if ComH=INVALID_HANDLE_VALUE then begin MessageBox(Handle,'Error','Error',MB_OK);  exit; end;
//*****
SetupComm(ComH,256,256);
SetCommMask(ComH, EV_RXCHAR or EV_TXEMPTY);

if not GetCommState(ComH, Dcb) then MessageBox(Handle,'Error setting port state','Error',MB_OK);
Dcb.BaudRate := StrToInt(BaudRate.Text);
Dcb.ByteSize := StrToInt(ByteSize.Text);
Dcb.Parity   := Parity.ItemIndex;
Dcb.StopBits := StopBits.ItemIndex;
if not SetCommState(ComH, Dcb) then MessageBox(Handle,'Error setting port state','Error',MB_OK);
if not PurgeComm(ComH,PURGE_RXABORT or PURGE_RXCLEAR or PURGE_TXABORT or PURGE_TXCLEAR) then MessageBox(Handle,'Error purging port','Error',MB_OK);

//---------- Создание потока для обработки данных ---------------

CommThread:=TCommTh.Create(False);

//---------- Собственно сам поток для обработки -----------------

procedure TCommTh.Execute;
var
 lpEvtMask: DWORD;
 lpErrors: DWORD;
 lpStat: TComStat;
 Overlapped:TOverlapped;
begin
 SetName;
 { Place thread code here }
FreeOnTerminate:=True;
FillChar(Overlapped,SizeOf(TOverlapped),0);
Overlapped.hEvent:=CreateEvent(nil, True, False, nil);
while not Terminated  do
 begin

   WaitCommEvent(ComH,lpEvtMask,@Overlapped);
   if Terminated then Break;
   ClearCommError(ComH,lpErrors,@lpStat);
   //********************************
   SetLength(Buf, lpStat.cbInQue);
   //********************************
   if not ReadFile(ComH,Buf[0],lpStat.cbInQue,lpStat.cbInQue,@Overlapped) then SendMessage(ComPortfrm.Handle,WM_USER,ERROR_IO_PENDING,GetLastError);
   if lpStat.cbInQue>0 then PostMessage(ComPortfrm.Handle,WM_USER,Buf[2],lpStat.cbInQue);  //В данном случае важен только 3 байт
  end;
 
end;



Но, есть программа для чтения данных с com написанная не мной (исходняка тоже нет), после её запуска и завершения все ошибки перечисленные выше пропадают, и работет как ни в чём не бывало.

Я как только не пробовал инициализировать, какие есть идеи?????????


clickmaker   (2009-03-23 14:20:00) [10]

> либо вовсе выдают ошибки.

какие?


Наверх

Титульная страница Поиск, карта сайта Написать письмо