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

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

Асинхронная работа с Com портом. [D7, WinXP]


Страницы:   1 2

Kolan ©   (2006-01-27 20:31:00) 

Здравствуйте,
 Помогите понять эту тему.

Сделал тестовый проект по этой статье:
http://articles.org.ru/cfaq/index.php?qid=1185

Сделали мне заглушку в Com порт. Те что послал то и принял.
Она 100% работает, проверил на своих проектах...

Чтение выполняется в отдельном потоке. Вот его код полнистью:


unit KAsyncComPortThread;

interface

uses
 Windows, Classes, KAsyncComPortRoutines, Variants;

type
 TReadThread = class(TThread)
 private
   { Private declarations }
   FBuffer: array[0..$FF] of Byte;
   FPortHandle: THandle;
   FOverRead: TOverlapped;
   FReadCount: DWORD;
   FReadEvent: TReadEvent;
   procedure DoRead;
 protected
   procedure Execute; override;
 public
   constructor Create(PortHandle: THandle; ReadEvent: TReadEvent);
   destructor Destroy; override;  
 end;

implementation

{ Important: Methods and properties of objects in visual components can only be
 used in a method called using Synchronize, for example,

     Synchronize(UpdateCaption);

 and UpdateCaption could look like,

   procedure TReadThread.UpdateCaption;
   begin
     Form1.Caption := 'Updated in a thread';
   end; }

{ TReadThread }

constructor TReadThread.Create(PortHandle: THandle; ReadEvent: TReadEvent);
var
 {//}Err: Boolean;
begin
 FReadEvent := nil;
 FPortHandle := PortHandle;
 FReadEvent := ReadEvent;
 ZeroMemory(@FOverRead, SizeOf(@FOverRead));
 FOverRead.hEvent := CreateEvent(nil, True, False, nil);
 if FOverRead.hEvent = Null then
   {//}Err := True;
 inherited Create(False);
end;

destructor TReadThread.Destroy;
begin
 CloseHandle(FOverRead.hEvent);
 inherited;
end;

procedure TReadThread.DoRead;
var
 Answer: TByteArray;
 I: Integer;
begin
 if Assigned(FReadEvent) then
 begin
   SetLength(Answer, FReadCount);
   for I := Low(Answer) to High(Answer) do
     Answer[I] := FBuffer[I];
     FReadEvent(Self, Answer);
     SetLength(Answer, 0);
 end;
end;

procedure TReadThread.Execute;
var
 ComStat: TComStat;
 dwMask, dwError: DWORD;
 {//}Err: Boolean;
 I: LongBool;
begin
 { Place thread code here }
 FreeOnTerminate := True;
 while not Terminated do
 begin
   //I := WaitCommEvent(FPortHandle, dwMask, @FOverRead);
   if not WaitCommEvent(FPortHandle, dwMask, @FOverRead) then
   begin
     if GetLastError = ERROR_IO_PENDING then
       WaitForSingleObject(FOverRead.hEvent, INFINITE)
     else
       {//}Err := True;
   end;
   if not Terminated then
     if not ClearCommError(FPortHandle, dwError, @ComStat) then
       {//}Err := True;

    FReadCount := ComStat.cbInQue;
   if FreadCount > 0 then
   begin
     if not ReadFile(FPortHandle, FBuffer, FReadCount, FReadCount, @FOverRead) then
       {//}Err := True;

     Synchronize(DoRead);
   end;
 end;

end;

end.


Вроде я разобрался в том как это все должно работать.

Проблема заключается в том, что какое бы кол-во байт я не пошлю приходит всегда 4(а должно быть как-бы эхо).
Причем 2 последних всегда одинаковые.

Ума не приложу с чем это может быть связано...

Проверил действительно в этой строке:
FReadCount := ComStat.cbInQue;
cbInQue = 4


tesseract   (2006-01-28 11:25:00) [21]

Kolan не парься. К этому классу я шёл года 3.
В конечном итоге и поддержка масок и ThreadSafe и дружбу с классом для Tcp/IP соединений  реализовать таки удалось :-)

Вышли конечно. А в Win98 непойдет?

Пойдёт но только через  winapi. И номер порта не может быть больше 9.


Kolan   (2006-01-28 11:11:00) [22]

Вышли конечно. А в Win98 непойдет?

А что насчет моего проекта...

PS
 Когдаже осушествится моя мечта и я напишу класс для работы с портом, котроый будет все правильно читать, не подвисать при чтении, самое главное работать с таймаутом, вообшем такой чтобы я забыл о этой проблемме..... уже год парюсь все неразберусь.


tesseract   (2006-01-28 10:58:00) [23]

Сказал бы сразу что надо. Выслать мой класс для прямого общения с драйвером порта (Win2k+) ?


Kolan   (2006-01-28 00:17:00) [24]

Чуть чуть не понял.
1. Что такое Size, а точнее где его взять. Желательно чтобы приемник незнал сколько надо читать. Сколько пришло- столько пришло...

2. Блин что делает эта ClearCommErrorникак непойму?

3. Дело в том что скорее всего мне придется кождую секунду принимать массив в 512 остчетов(что-то вроде графика). Каждый остчет- 2 числа, каждое число наверно по 4 байта..... Вообшем довольно много...


tesseract   (2006-01-27 23:54:00) [25]

А так?

for count:=1 to 5 do
begin
  ClearCommError(hCom, ErrCode, @hCurState);
  if hCurState.cbInQue>=Size then
   begin
   result:=true;
   exit;
   end;
   sleep(50);
end;


Kolan   (2006-01-27 23:46:00) [26]

 
  Sleep(100);
if not ClearCommError(FPortHandle, dwError, @ComStat) then
      {//}Err := True;

  FReadCount := ComStat.cbInQue;
  if FreadCount > 0 then


Так? - Непомогло


tesseract   (2006-01-27 23:38:00) [27]

Не парься. Всё ок. Правда с RS-484 я работал только с конвертерами. Для особо одарённых случаев приходилось отключать  WaitCommMask и работать именно таким способом.


Kolan   (2006-01-27 23:24:00) [28]

Шас попробую с задержкой. Ненравится мне этот вариант тк у меня будет RS-485.
Не уверен что получится

Если вас незатруднит обясните мне глубокий смысл ф-ции ClearCommError.

Из справки я понял что: Функция извлекает инф. о ошибках связи и сообщ текущее состояние устр-ва связи (это Com порт как я понял). Функция вызывается при возникновении ошибки, и отчишает флаг ошибки устр-ва ч тобы включить дополнительные операции ввода/вывода.

Вот это я не очень понял...


tesseract   (2006-01-27 23:08:00) [29]


>Просто засыпть? - это решение мне ненравится...

Зря. Если используешь поток - нормально, на загрузке проца не скажется.
ClearCommError можно вызывать десяток раз, через некоторые промежутки времени Ж-)


Kolan   (2006-01-27 23:05:00) [30]

Непойму как это сделать?
Просто засыпть? - это решение мне ненравится...


tesseract   (2006-01-27 22:27:00) [31]

Винда использует буфер.
подожди побольше - придёт побольше байтов.


Страницы:   1 2

Наверх

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