Форум: "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