Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> COM-порт в COM(OLE) сервере (DLL) 
:(
    Опции темы
Satana
Дата 18.12.2003, 14:18 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Здравствуйте господа!

Я работаю с COM-портом в COM(OLE) сервере (DLL).
Если рассматривать задачу по частям(отдельно друг от друга), то всё работает идеально.
Т.е. используя модуль для работы с СОМ-портом (текст представлю ниже) в простом приложении, работает всё отлично.
Аналогично и при создании DLL, но используя компонент ComDrv32, всё кроме корректной работы CОМ порта работает.

Если работать с unit ComPort, то покрайней мере отсылка происходит вполне корректно(что не может, не радовать). А вот, считывание данных в переменную, организовать не получается.
Помогите разобраться.


Привожу тексты - примеры:
  Вверх
Satana
Дата 18.12.2003, 14:19 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Код
unit ComPort;
////////////////////////////////////////////////////////////////////////////////
//  Class:       TComPort                                                     //
//  Description: Asynchronous (overlapped) COM port                           //
//  Version:     1.0                                                          //
//  Date:        10-Jun-2003                                                  //
//  Author:      Igor Pavlov, [email protected]                               //
//  Copyright:   (c) 2003, Igor Pavlov                                        //
////////////////////////////////////////////////////////////////////////////////
interface
uses     Messages, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ComCtrls, ExtCtrls,
 SysUtils, Windows, Variants, Classes;
type
 EComPortError = class(Exception);
 TBaudRate = (br110 = CBR_110,
              br300 = CBR_300,
              br600 = CBR_600,
              br1200 = CBR_1200,
              br2400 = CBR_2400,
              br4800 = CBR_4800,
              br9600 = CBR_9600,
              br14400 = CBR_14400,
              br19200 = CBR_19200,
              br38400 = CBR_38400,
              br56000 = CBR_56000,
              br57600 = CBR_57600,
              br115200 = CBR_115200,
              br128000 = CBR_128000,
              br256000 = CBR_256000);
 TComPort = class;
 {Reading thread}
 TReadThread = class(TThread)
 private
   FBuf: array[0..$FF] of Byte;
   FComPort: TComPort;
   FOverRead: TOverlapped;
   FRead: DWORD;
   procedure DoRead;
 protected
   procedure Execute; override;
 public
   constructor Create(ComPort: TComPort);
   destructor Destroy; override;
 end;
 {Reading event}
 TReadEvent = procedure(Sender: TObject; ReadBytes: array of Byte) of object;
 {Com port class}
 TComPort = class
 private
   FOverWrite: TOverlapped;
   FPort: THandle;
   FPortName: String;
   FReadEvent: TReadEvent;
   FReadThread: TReadThread;
 public
   constructor Create(PortNumber: Cardinal; BaudRate: TBaudRate);
   destructor Destroy; override;
   procedure Write(WriteBytes: array of Byte);
 published
   property OnRead: TReadEvent read FReadEvent write FReadEvent;
   property PortName: String read FPortName;
 end;
implementation
constructor TReadThread.Create(ComPort: TComPort);
begin
 FComPort := ComPort;
 ZeroMemory(@FOverRead, SizeOf(FOverRead));
 {Event}
 FOverRead.hEvent := CreateEvent(nil, True, False, nil);
 if FOverRead.hEvent = Null then
   raise EComPortError.Create('Error creating read event');
 inherited Create(False);
end;
destructor TReadThread.Destroy;
begin
 CloseHandle(FOverRead.hEvent);
 inherited Destroy;
end;
procedure TReadThread.Execute;
var ComStat: TComStat;
    dwMask, dwError: DWORD;
begin
 FreeOnTerminate := True;
 while not Terminated do
 begin
   if not WaitCommEvent(FComPort.FPort, dwMask, @FOverRead) then
   begin
     if GetLastError = ERROR_IO_PENDING then
       WaitForSingleObject(FOverRead.hEvent, INFINITE)
     else
       raise EComPortError.Create('Error waiting port ' + FComPort.PortName + ' event');
   end;
   if not ClearCommError(FComPort.FPort, dwError, @ComStat) then
     raise EComPortError.Create('Error clearing port ' + FComPort.PortName);
   FRead := ComStat.cbInQue;
   if FRead > 0 then
   begin
     if not ReadFile(FComPort.FPort, FBuf, FRead, FRead, @FOverRead) then
       raise EComPortError.Create('Error reading port ' + FComPort.PortName);
    Synchronize(DoRead);
   end;
 end; {while}
end;
procedure TReadThread.DoRead;
var
 arrBytes: array of Byte;
 i: Integer;
begin
 if Assigned(FComPort.FReadEvent) then
 begin
   SetLength(arrBytes, FRead);
   for i := Low(FBuf) to FRead - 1 do
     arrBytes[i] := FBuf[i];
   FComPort.FReadEvent(Self, arrBytes);
   arrBytes := nil;
 end;  
end;
constructor TComPort.Create(PortNumber: Cardinal; BaudRate: TBaudRate);
var
 Dcb: TDcb;
begin
 inherited Create;
 ZeroMemory(@FOverWrite, SizeOf(FOverWrite));
 FPortName := 'COM' + IntToStr(PortNumber);
 {Open port}
 FPort := CreateFile(PChar(PortName),
   GENERIC_READ or GENERIC_WRITE, 0, nil,
   OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
 if FPort = INVALID_HANDLE_VALUE then
   raise EComPortError.Create('Error opening port ' + PortName);
 try
   {Set port state}
   if not GetCommState(FPort, Dcb) then
     raise EComPortError.Create('Error setting port ' + PortName + ' state');
   Dcb.BaudRate := DWORD(BaudRate);
   Dcb.Parity := NOPARITY;
   Dcb.ByteSize := 8;
   Dcb.StopBits := ONESTOPBIT;
   if not SetCommState(FPort, Dcb) then
     raise EComPortError.Create('Error setting port ' + PortName + ' state');
   {Purge port}
   if not PurgeComm(FPort, PURGE_TXCLEAR or PURGE_RXCLEAR) then
     raise EComPortError.Create('Error purging port ' + PortName);
   {Set mask}
   if not SetCommMask(FPort, EV_RXCHAR) then
     raise EComPortError.Create('Error setting port ' + PortName + ' mask');
   FOverWrite.hEvent := CreateEvent(nil, True, False, nil);
   if FOverWrite.hEvent = Null then
     raise EComPortError.Create('Error creating write event');
   {Reading thread}
   FReadThread := TReadThread.Create(Self);
 except
   CloseHandle(FOverWrite.hEvent);
   CloseHandle(FPort);
   raise;
 end;
end;
destructor TComPort.Destroy;
begin
 if Assigned(FReadThread) then
   FReadThread.Terminate;
 CloseHandle(FOverWrite.hEvent);
 CloseHandle(FPort);
 inherited Destroy;
end;
procedure TComPort.Write(WriteBytes: array of Byte);
var  dwWrite: DWORD;
begin
 if  (not WriteFile(FPort, WriteBytes, SizeOf(WriteBytes), dwWrite, @FOverWrite))
 and (GetLastError <> ERROR_IO_PENDING) then
   raise EComPortError.Create('Error writing port ' + PortName);
end;
end.


  Вверх
Satana
Дата 18.12.2003, 14:21 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











DLL из себя представляет нечто такое, организованное визардом:
Код

 IFPt = interface(IDispatch)
   ['{52FC7576-1ECA-4BFA-BF4C-AB478E6A7E99}']
   function  PortInit(Com: Shortint): OleVariant; safecall;
   function  SendLine(Line: OleVariant): OleVariant; safecall;

Надеюсь понятно.

пример рабочей программы!
Код

type
 TfrmMain = class(TForm)
...
  procedure OnRead(Sender: TObject; ReadBytes: array of Byte);
 private
...
procedure TfrmMain.btnOpenClick(Sender: TObject);
begin
 Port := TComPort.Create(udnPort.Position, br9600);
 Port.OnRead := OnRead;
end;
procedure t.OnRead(Sender: TObject; ReadBytes: array of Byte);
var  i: Integer;
begin
 for i := Low(ReadBytes) to High(ReadBytes) do
 begin
   if i > Low(ReadBytes) then
     frmMain.memRead1.Text := frmMain.memRead1.Text + '.';
   frmMain.memRead1.Text := frmMain.memRead1.Text + IntToHex(ReadBytes[i], 2);
 end;
 frmMain.memRead1.Lines.Add('');
end;
procedure TfrmMain.Button2Click(Sender: TObject);
var  strWrite: string;
     arrBytes: array of Byte;
     i:integer;
begin
strWrite :='Привет';
SetLength(arrBytes, Length(strWrite));
 for i := Low(arrBytes) to High(arrBytes) do
   arrBytes[i] := Ord(strWrite[i + 1]);
Port.Write(arrBytes);
arrBytes := nil;
end;


  Вверх
Satana
Дата 20.12.2003, 13:52 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











?
  Вверх
Unregistered
Дата 22.12.2003, 04:20 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











У тебя 98-я? В ней я сталкивался с проблемой настройки таймаутов, а именно: те настройки таймаутов что устанавливаются при открытии порта не всегда корректно работают (как не глупо это звучит). Кстати, в В2К такой проблемы не возникает.
Попробуй в TComPort.Create добавить следующее:

var CommTime:TCommTimeOuts;
...........
CommTime.ReadIntervalTimeout:=MAXDWORD;//4294967295
CommTime.ReadTotalTimeoutMultiplier:=0;
CommTime.ReadTotalTimeoutConstant:=0;
CommTime.WriteTotalTimeoutMultiplier:=0;
CommTime.WriteTotalTimeoutConstant:=0;
SetCommTimeouts(hCom,CommTime);

может поможет. Удачи.
  Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0440 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.