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

Вниз

Программирование устройства через COM-port   Найти похожие ветки 

 
Rafa ©   (2008-08-05 17:14) [0]

Мне требуется написать программу для отправки команды в хексе на одно промышленное устройство (контроллер "Квант-1" если это кому-то важно). Устройство управляется через COM-port, использовать можно только ноуты, так как тем кто будет использовать программу требуется мобильность, там кроме USB нету ничего. Они используют для соединения с устройствами переходник USB-COM, на который есть свой драйвер.
Теперь вопросы:
1)Самое важное что мне надо знать, это чему передавать команду? COM порту, USB порту или драйверу переходника?
2)Я использовал WinAPI функцию для управления COM портом SetCommState в которую передавал Handle  
hndCOM:=CreateFile(PChar("COM1"),GENERIC_READ+GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
и структуру TDCB. Когда я протестировал програмку не произошло даже отправки чего-нибудь устройству, даже попытки отправить как я понял. Быть может я неправильно установил параметры порта в структуре? Если кто встречался с подобной проблемой, может это быть из-за неверных параметров в структуре?
3) Будь то передача в COM порт, USB или ещё что-нибудь, передайте пожалуйста хоть какой-нибудь пример используемых функций, или если вы знаете как можно решить без использования WinAPI дайте ссылку на компонент.
Заранее спасибо...


 
KilkennyCat ©   (2008-08-05 22:14) [1]


> 1)Самое важное что мне надо знать, это чему передавать команду?
>  COM порту, USB порту или драйверу переходника?


COM порту


> 2)...>  может это быть из-за неверных параметров в структуре?


Разумеется. В том числе из-за неправильного имени порта.

3)http://www.torry.net/pages.php?id=1223


 
KilkennyCat ©   (2008-08-05 22:19) [2]

не совсем угадал :) - эта точнее
http://www.torry.net/pages.php?id=198


 
tesseract ©   (2008-08-06 10:52) [3]


> Будь то передача в COM порт, USB или ещё что-нибудь, передайте
> пожалуйста хоть какой-нибудь пример используемых функций,
>  


hCom:=CreateFile(PChar(fPortName),GENERIC_READ OR GENERIC_WRITE,0,NIL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);
// Если неверен выходим
if (hCom=INVALID_HANDLE_VALUE) or (hcom=ERROR_ALREADY_EXISTS) then exit;
// Устанавливаем буфер
FillChar(ReadOl,SizeOF(ReadOL),0);
ReadOl.hevent:=CreateEvent(nil,true,true,nil);

 result:=false;
if not(SetupComm(hCom,512,512)) then exit;
// Чистим буфер
if not(PurgeComm(hCom,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR )) then exit;
GetCommTimeOuts(hCom,CommTimeOuts);
// Устанавливаем задержки/время ожидания
 CommTimeOuts.ReadIntervalTimeout:= 50;
 CommTimeOuts.ReadTotalTimeoutMultiplier := 40;
 CommTimeOuts.ReadTotalTimeoutConstant := 0;
 CommTimeOuts.WriteTotalTimeoutMultiplier := 10;
 CommTimeOuts.WriteTotalTimeoutConstant := 0;

 // Если не получилось выходим
if not(SetCommTimeouts(hCom,CommTimeOuts)) then exit;
 // Устанавливаем параметры порта через DCB

//Заполняем нужные параметры
 hdcb.BaudRate :=fBaudRate;  hdcb.ByteSize := fByteSize;
 hdcb.StopBits := fStopBits;  hdcb.Parity := fParity;
// Устанавливаем DpCB
if not(SetCommState(hCom,hdcb)) then exit;

succ:=ReadFile(hCom,result,1,fRead,@ReadOL);
      if not succ then
            begin
             if GetLastError=ERROR_IO_PENDING then
              if WaitForSingleObject(ReadOl.hEvent,waitint)=WAIT_OBJECT_0 then
               if GetOverlappedResult(hCom, ReadOL, fREad,true)  then
                Succ:=true;
              end; // if not succ
if not(GetCommState(hCom,hDCB)) then exit;


 
Variant   (2008-08-06 12:04) [4]


> tesseract ©   (06.08.08 10:52) [3]



> if (hCom=INVALID_HANDLE_VALUE) or (hcom=ERROR_ALREADY_EXISTS)
> then .......


ERROR_ALREADY_EXISTS - лишнее,не вернется в данном случае. Эта ошибка возвращается уже при вызове GetLastError. Но мне кажется, что и при вызове GetLastError она не вернется для COM порта.. , но... точно не скажу, просто не видел такой ошибки для COM порта


 
tesseract ©   (2008-08-06 12:23) [5]


>  просто не видел такой ошибки для COM порта


Описался :-) Порт всегда конечно существует. Там ERROR_ALREADY_OPEN вроде должно стоять, точно не помню сейчас.


 
brother ©   (2008-08-06 13:21) [6]

> чему передавать команду? COM порту, USB порту или драйверу
> переходника?

если после установки драйвера появился новый com порт, то ему иначе usb а дальше забота дравера)


 
Viktorious ©   (2008-08-07 00:08) [7]

Если есть переходник USB-COM, его драйвера обычно ставят виртуальный COM-порт, с которым программы работают как с самым обычным последовательным портом, а преобразование сигналов посл. порта в USB интерфейс и обратно - это уже забота драйвера и собственно переходника.

Я пользуюсь вот этим http://synapse.ararat.cz/files/synaser.zip (класс TBlockSerial) - простая обертка над Windows API, которая прячет внутри себя эти громоздкие вызовы. Недостаток - все вызовы блокирующие (при обрыве линии и плохом проектировании приложения может надолго завесить всю программу). Пример использования:


var Ser:TBlockSerial;
    Buffer:packed array[0..1024]of byte;
    BufSize:integer;
begin
 BufSize := 32;
 ser:=TBlockSerial.Create;
 try
  //Соединение с портом. Вы должны правильно указать номер порта
   ser.Connect("COM3");
 //Настройка порта. Вы должны знать параметры, с которыми работает Ваше
 //внешнее устройства - скорость передачи, битность, четность и т.д.
   ser.config(9600,8,"N",ONESTOPBIT,false,false);
 //Прочитать данные из порта. Лучше использовать RecvBufferEx -  можно задавать тайм-аут ожидания.
   ser.RecvBuffer(@Buffer,BufSize);
 //отправить данные в последовательный порт
   ser.SendBuffer(@Buffer,BufSize);
 finally
   ser.free;
 end;
end;


 
Уянга   (2008-12-01 07:58) [8]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, TeeProcs, TeEngine, Chart, Series;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   Chart1: TChart;
   Timer1: TTimer;
   Button2: TButton;
   Edit2: TEdit;
   Label1: TLabel;
   Label2: TLabel;
   Edit3: TEdit;
   Label3: TLabel;
   Edit4: TEdit;
   Label4: TLabel;
   Button3: TButton;
   Button4: TButton;
   Series2: TFastLineSeries;
   procedure Button1Click(Sender: TObject);
   procedure DrawGraphics();
   procedure Timer1Timer(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure Button4Click(Sender: TObject);

 private
   { Private declarations }
 public
   { Public declarations }
 end;
Type
 TProcedure = procedure;
var
 Form1: TForm1;
 Data, TData: integer;
 ComFile: THandle;
 t, dt, t0: real;
 a, b, c, d, e, f, g, h, m : integer;
 dataToSend: string;
 BytesWritten: DWORD;

function Out32(wAddr:word;bOut:byte):byte; stdcall; external "inpout32.dll";
function Inp32(wAddr:word):byte; stdcall; external "inpout32.dll";

implementation

{$R *.dfm}

function HexToBin():integer;
begin
 a:=data and $01;
 b:=data and $02;
 b:=b shr 1;
 b:=b*10;
 c:=data and $04;
 c:=c shr 2;
 c:=c*100;
 d:=data and $08;
 d:=d shr 3;
 d:=d*1000;
 e:=data and $010;
 e:=e shr 4;
 e:=e*10000;
 f:=data and $20;
 f:=f shr 5;
 f:=f*100000;
 g:=data and $40;
 g:=g shr 6;
 g:=g*1000000;
 h:=data and $80;
 h:=h shr 7;
 h:=h*10000000;
m:=h+g+f+e+d+c+b+a;
result:=m;
end;

function THexToBin():integer;
begin
 a:=Tdata and $01;
 b:=Tdata and $02;
 b:=b shr 1;
 b:=b*10;
 c:=Tdata and $04;
 c:=c shr 2;
 c:=c*100;
 d:=Tdata and $08;
 d:=d shr 3;
 d:=d*1000;
 e:=Tdata and $010;
 e:=e shr 4;
 e:=e*10000;
 f:=Tdata and $20;
 f:=f shr 5;
 f:=f*100000;
 g:=Tdata and $40;
 g:=g shr 6;
 g:=g*1000000;
 h:=Tdata and $80;
 h:=h shr 7;
 h:=h*10000000;
m:=h+g+f+e+d+c+b+a;
result:=m;
end;

function SetupCOMPort: Boolean;
const
 RxBufferSize = 256;
 TxBufferSize = 256;
var
 DCB: TDCB;
 Config: string;
 CommTimeouts: TCommTimeouts;
begin
 Result := True;

 if not SetupComm(ComFile, RxBufferSize, TxBufferSize) then
   Result := False;

 if not GetCommState(ComFile, DCB) then
   Result := False;

 // define the baudrate, parity,...
 // hier die Baudrate, Parität usw. konfigurieren

 Config := "baud=1200 parity=n data=8 stop=1";

 if not BuildCommDCB(@Config[1], DCB) then
   Result := False;

 if not SetCommState(ComFile, DCB) then
   Result := False;

 with CommTimeouts do
 begin
   ReadIntervalTimeout         := 0;
   ReadTotalTimeoutMultiplier  := 0;
   ReadTotalTimeoutConstant    := 1000;
   WriteTotalTimeoutMultiplier := 0;
   WriteTotalTimeoutConstant   := 1000;
 end;

 if not SetCommTimeouts(ComFile, CommTimeouts) then
   Result := False;
end;

function OpenCOMPort: Boolean;
var
 DeviceName: array[0..80] of Char;
begin
  StrPCopy(DeviceName, "COM1:");
   ComFile := CreateFile(DeviceName,
   GENERIC_READ or GENERIC_WRITE,
   0,
   nil,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   0);

 if ComFile = INVALID_HANDLE_VALUE then
   Result := False
 else
   Result := True;
 WriteFile(ComFile, datatosend[1], Length("30"), BytesWritten, nil);
end;

procedure TForm1.DrawGraphics();
begin
 Series2.AddXY(t, data);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 t0:=0.0;
 dt:=0.01;
 t:=t0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Series2.Clear;
t0:=0.0;
dt:=0.01;
t:=t0;
timer1.Enabled:=true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
 gg: integer;
begin
 t:=t+dt;
 OpenComPort();
 SetupComPort();
 edit1.Text:=IntToStr(Inp32($3f8));
 Data:=StrToInt(Edit1.Text);
 CloseHandle(ComFILE);

 //Recieved Data in Binary
 gg:=HexToBin();
 if(h=0)then
 begin
 edit2.Text:="0"+IntToStr(g+f+e+d+c+b+a);
  if(g=0)then
  begin
  edit2.Text:="00"+IntToStr(f+e+d+c+b+a);
   if(f=0)then
   begin
   edit2.Text:="000"+IntToStr(e+d+c+b+a);
    if(e=0)then
    begin
    edit2.Text:="0000"+IntToStr(d+c+b+a);
     if(d=0)then
     begin
     edit2.Text:="00000"+IntToStr(c+b+a);
      if(c=0)then
      begin
      edit2.Text:="000000"+IntToStr(b+a);
       if(b=0)then
       begin
       edit2.Text:="0000000"+IntToStr(a);
        if(a=0)then
        begin
        edit2.Text:="00000000";
        end;
       end;
      end;
     end;
    end;
   end;
  end;
 end
 else
 edit2.Text:=IntToStr(gg);
 //Recieved Data in Binary
  DrawGraphics();
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
 timer1.Enabled:=false;
end;

//Start of Transmitting Data
procedure TForm1.Button3Click(Sender: TObject);
var
 kk: integer;
begin
 OpenComPort();
 SetupComPort();
 TData:=StrToInt(edit3.Text);
 out32($3f8, TData);

 //Recieved Data in Binary
 kk:=THexToBin();
 if(h=0)then
 begin
 edit4.Text:="0"+IntToStr(g+f+e+d+c+b+a);
  if(g=0)then
  begin
  edit4.Text:="00"+IntToStr(f+e+d+c+b+a);
   if(f=0)then
   begin
   edit4.Text:="000"+IntToStr(e+d+c+b+a);
    if(e=0)then
    begin
    edit4.Text:="0000"+IntToStr(d+c+b+a);
     if(d=0)then
     begin
     edit4.Text:="00000"+IntToStr(c+b+a);
      if(c=0)then
      begin
      edit4.Text:="000000"+IntToStr(b+a);
       if(b=0)then
       begin
       edit4.Text:="0000000"+IntToStr(a);
        if(a=0)then
        begin
        edit4.Text:="00000000";
        end;
       end;
      end;
     end;
    end;
   end;
  end;
 end
 else
 edit4.Text:=IntToStr(kk);
 //Recieved Data in Binary
CloseHandle(ComFILE);
end;

//Application is close
procedure TForm1.Button2Click(Sender: TObject);
begin
 Application.Terminate;
end;

end.


 
Сергей М. ©   (2008-12-01 08:28) [9]


> Уянга


Шедевр программистской мысли.


 
KilkennyCat ©   (2008-12-01 11:19) [10]

Вау.


 
tesseract ©   (2008-12-01 11:48) [11]

Даа.... я в школе писал наверно лучше.


 
clickmaker ©   (2008-12-01 13:56) [12]

а мне нравится
то, что после //Recieved Data in Binary - это просто натюрморт в коде


 
KilkennyCat ©   (2008-12-01 21:17) [13]


> clickmaker ©   (01.12.08 13:56) [12]

Что именно? сей комментарий встречается четырежды :)


 
Германн ©   (2008-12-02 10:40) [14]

А мне нравятся две процедуры HexToBin. Вот только на стенку повесить не могу. Обои жалко портить. :(


 
Anatoly Podgoretsky ©   (2008-12-02 11:09) [15]

Обои жалко, а психику не жалеешь, а зря - обои можно переклеить, а мозги не заменишь.


 
KilkennyCat ©   (2008-12-02 23:50) [16]


> Германн ©   (02.12.08 10:40) [14]

Во-первых, функции, а во-вторых, одна. Вторая - THexToBin


 
Германн ©   (2008-12-03 00:07) [17]


> KilkennyCat ©   (02.12.08 23:50) [16]

И все равно нравятся!
:)


 
Дмитрий Белькевич ©   (2008-12-06 12:34) [18]

>Я пользуюсь вот этим http://synapse.ararat.cz/files/synaser.zip (класс TBlockSerial) - простая обертка над Windows API, которая прячет внутри себя эти громоздкие вызовы.

Спасибо. Как раз начинаем плотно ком юзать - видимо, самое оно, что бы всё то же самое не писать.

>Недостаток - все вызовы блокирующие (при обрыве линии и плохом проектировании приложения может надолго завесить всю программу)

Лечится дополнительным потоком.

Уянга - красавица :)


 
kulibin   (2009-01-10 21:16) [19]

>2)Я использовал WinAPI функцию для управления COM портом >SetCommState в которую передавал Handle  
>hndCOM:=CreateFile(PChar("COM1"),GENERIC_READ
>+GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

А кто теб сказал что он COM1, а не COM5 например?



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

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

Наверх




Память: 0.53 MB
Время: 0.012 c
4-1228124695
markers
2008-12-01 12:44
2010.03.21
System Error 5


15-1262617930
Копир
2010-01-04 18:12
2010.03.21
Delphi


6-1215009957
FireMan_Alexey
2008-07-02 18:45
2010.03.21
Proxy-Server вопрос по RFC2068


6-1214832907
Галинка
2008-06-30 17:35
2010.03.21
Sckets: почему так получается


4-1228570622
Саня
2008-12-06 16:37
2010.03.21
как потушить монитор , Windows Xp