Форум: "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.073 c