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

Вниз

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 вся ветка

Форум: "WinAPI";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.055 c
15-1265202233
БарЛог
2010-02-03 16:03
2010.08.27
Нарисовать график


2-1271147554
Сергей
2010-04-13 12:32
2010.08.27
Ошибка сокета.


2-1267885769
Mer01
2010-03-06 17:29
2010.08.27
Как задать массив Record при инициализации?


15-1269453084
SergD
2010-03-24 20:51
2010.08.27
Экземпляр класса


15-1270053342
AntonioBanderas
2010-03-31 20:35
2010.08.27
MSDOS программка перестала запускаться





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский