![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Программирование устройства через COM-port [D7, WinXP]
Rafa © (2008-08-05 17:14:00)Мне требуется написать программу для отправки команды в хексе на одно промышленное устройство (контроллер "Квант-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 дайте ссылку на компонент.
Заранее спасибо...
kulibin (2009-01-10 21:16:00) [1]>2)Я использовал WinAPI функцию для управления COM портом >SetCommState в которую передавал Handle
>hndCOM:=CreateFile(PChar('COM1'),GENERIC_READ
>+GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
А кто теб сказал что он COM1, а не COM5 например?
Дмитрий Белькевич (2008-12-06 12:34:00) [2]>Я пользуюсь вот этим http://synapse.ararat.cz/files/synaser.zip(класс TBlockSerial) - простая обертка над Windows API, которая прячет внутри себя эти громоздкие вызовы.
Спасибо. Как раз начинаем плотно ком юзать - видимо, самое оно, что бы всё то же самое не писать.
>Недостаток - все вызовы блокирующие (при обрыве линии и плохом проектировании приложения может надолго завесить всю программу)
Лечится дополнительным потоком.
Уянга - красавица :)
Германн (2008-12-03 00:07:00) [3]
> KilkennyCat © (02.12.08 23:50) [16]
И все равно нравятся!
:)
KilkennyCat (2008-12-02 23:50:00) [4]
> Германн © (02.12.08 10:40) [14]
Во-первых, функции, а во-вторых, одна. Вторая - THexToBin
Anatoly Podgoretsky (2008-12-02 11:09:00) [5]Обои жалко, а психику не жалеешь, а зря - обои можно переклеить, а мозги не заменишь.
Германн (2008-12-02 10:40:00) [6]А мне нравятся две процедуры HexToBin. Вот только на стенку повесить не могу. Обои жалко портить. :(
KilkennyCat (2008-12-01 21:17:00) [7]
> clickmaker © (01.12.08 13:56) [12]
Что именно? сей комментарий встречается четырежды :)
clickmaker (2008-12-01 13:56:00) [8]а мне нравится
то, что после //Recieved Data in Binary - это просто натюрморт в коде
tesseract (2008-12-01 11:48:00) [9]Даа.... я в школе писал наверно лучше.
KilkennyCat (2008-12-01 11:19:00) [10]Вау.
Сергей М. (2008-12-01 08:28:00) [11]
> Уянга
Шедевр программистской мысли.
Уянга (2008-12-01 07:58:00) [12]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.
Viktorious (2008-08-07 00:08:00) [13]Если есть переходник 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;
brother (2008-08-06 13:21:00) [14]> чему передавать команду? COM порту, USB порту или драйверу
> переходника?
если после установки драйвера появился новый com порт, то ему иначе usb а дальше забота дравера)
tesseract (2008-08-06 12:23:00) [15]
> просто не видел такой ошибки для COM порта
Описался :-) Порт всегда конечно существует. Там ERROR_ALREADY_OPEN вроде должно стоять, точно не помню сейчас.
Variant (2008-08-06 12:04:00) [16]
> 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 10:52:00) [17]
> Будь то передача в 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;
KilkennyCat (2008-08-05 22:19:00) [18]не совсем угадал :) - эта точнее
http://www.torry.net/pages.php?id=198
KilkennyCat (2008-08-05 22:14:00) [19]
> 1)Самое важное что мне надо знать, это чему передавать команду?
> COM порту, USB порту или драйверу переходника?
COM порту
> 2)...> может это быть из-за неверных параметров в структуре?
Разумеется. В том числе из-за неправильного имени порта.
3) http://www.torry.net/pages.php?id=1223