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

Вниз

Comm Port под Vista AMDx64   Найти похожие ветки 

 
Delion   (2009-03-22 14:47) [0]

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

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

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

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

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

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


 
clickmaker ©   (2009-03-23 14:20) [1]

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

какие?


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


> какие


- иногда ошибки открытия порта, хотя порт явно не занят.
- Ошибка передачи параметра.
- Ошибки чтения данных ввиде ни какой реакции на устройство подсоединённое к 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 написанная не мной (исходняка тоже нет), после её запуска и завершения все ошибки перечисленные выше пропадают, и работет как ни в чём не бывало.

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


 
tesseract ©   (2009-03-24 11:11) [3]

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


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


> 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 - кстати тоже может вернуть ошибки, как свою ошибку, так и ошибку работы порта (например ошибку фрейма). Это все тоже требует анализа.


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

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


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 режим


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


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

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

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


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


> 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 портами.


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


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));


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

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

А если я вставлю код на запись перед 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");


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


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


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


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


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

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

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

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

DCB.Flags    := (Bin:00000000000000000001000000000001)



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

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

Наверх




Память: 0.51 MB
Время: 0.058 c
15-1271414136
ocean
2010-04-16 14:35
2010.08.27
Блокировать сайты в ISA


9-1185021098
AlexanderMS
2007-07-21 16:31
2010.08.27
Повторный вывод уже построенной сцены в OpenGL.


15-1265372241
Alien1769
2010-02-05 15:17
2010.08.27
Задачка на логику


3-1243244910
Ольга
2009-05-25 13:48
2010.08.27
Текст в окне Messages Query Analyzer


15-1267705960
Kolan
2010-03-04 15:32
2010.08.27
Где взять справку по TMaskEdit?