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

Вниз

Программирование устройства через 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 вся ветка

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

Наверх





Память: 0.53 MB
Время: 0.004 c
1-1242222408
Гарик
2009-05-13 17:46
2010.03.21
Справка WinHelp в Дельфи 7


2-1263635338
OOO_leg
2010-01-16 12:48
2010.03.21
Компоненты


1-1242910957
Unknown user
2009-05-21 17:02
2010.03.21
TTypeInfo


2-1263711881
MK26
2010-01-17 10:04
2010.03.21
Помогите установить пароль на готовую уже программу (exe фаил)


1-1245049450
Priest
2009-06-15 11:04
2010.03.21
После установки D 2007 начались проблемы в D7





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