傳送16進制資料至PLC端 |
尚未結案
|
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
大家好!
以下是VB的寫法:
Private Sub Command3_Click()
Dim s(22) As Byte
s(0) = &H5
s(1) = &H30
s(2) = &H31
s(3) = &H46
s(4) = &H46
s(5) = &H42
s(6) = &H57
s(7) = &H30
s(8) = &H59
s(9) = &H30
s(10) = &H30
s(11) = &H30
s(12) = &H30
s(13) = &H30
s(14) = &H38
s(15) = &H30
s(16) = &H31
s(17) = &H30
s(18) = &H31
s(19) = &H30
s(20) = &H31
s(21) = &H30
s(22) = &H31
MSComm1.Output = s
End Sub 請問在DELPHI應該如何寫?
我是這樣寫的,好像不對!請各位幫忙指點一下,謝謝!
var
Form1: TForm1;
sbuf: array[1..256] of byte; procedure TForm1.Button3Click(Sender: TObject);
begin
sbuf[1] := $05;
sbuf[2] := $30;
sbuf[3] := $31;
sbuf[4] := $46;
sbuf[5] := $46;
sbuf[6] := $42;
sbuf[7] := $52;
sbuf[8] := $31;
sbuf[9] := $58;
sbuf[10] := $30;
sbuf[11] := $30;
sbuf[12] := $30;
sbuf[13] := $30;
sbuf[14] := $30;
sbuf[15] := $38;
sbuf[16] := $30;
sbuf[17] := $31;
sbuf[18] := $30;
sbuf[19] := $31;
sbuf[20] := $30;
sbuf[21] := $31;
sbuf[22] := $30;
sbuf[23] := $31;
senddata; //傳送資料
end; 發表人 - zxy666666 於 2005/03/14 15:25:16
|
yorkland
高階會員 發表:2 回覆:138 積分:108 註冊:2004-12-17 發送簡訊給我 |
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
|
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
sbuf[1] := byte($05);是可以執行的,不過應該沒有必要這樣用吧! 妳試試看下面的程式可不可以Run
var Form1: TForm1; sbuf: array[0..22] of byte; begin sbuf[0] := $05; sbuf[1] := $30; sbuf[2] := $31; sbuf[3] := $46; sbuf[4] := $46; sbuf[5] := $42; sbuf[6] := $52; sbuf[7] := $31; sbuf[8] := $58; sbuf[9] := $30; sbuf[10] := $30; sbuf[11] := $30; sbuf[12] := $30; sbuf[13] := $30; sbuf[14] := $38; sbuf[15] := $30; sbuf[16] := $31; sbuf[17] := $30; sbuf[18] := $31; sbuf[19] := $30; sbuf[20] := $31; sbuf[21] := $30; sbuf[22] := $31; senddata; //傳送資料 end;Ian |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
各位大大好!
我現在有如下程序,點"傳送資料",PLC端接收信號燈有亮一下(即表示有與PC通訊).但是寫入到PLC端Y0-Y7的值不起作用.按理來說如果寫入正確會亮4個燈,對嗎?請問哪裡出問題了呢?還是程式中的senddata代碼有錯誤?
注:我用SPcomm控制,並與PLC端的設定一致:波特率-9600,校驗位-NONE,數據位-8位,停止位--1位 var
Form1: TForm1;
viewstring: string;
i: integer;
rbuf, sbuf: array[0..22] of byte; procedure TForm1.FormCreate(Sender: TObject);
begin
Comm1.StartComm; //開啟通訊埠
end; procedure TForm1.Button1Click(Sender: TObject);
begin
Comm1.StopComm; //關閉通訊埠
end; procedure Tform1.senddata; //發送資料
var
i: integer;
commflg: boolean;
begin
viewstring:='';
commflg:=true;
for i:=0 to 22 do
begin
if not form1.Comm1.WriteCommData(@sbuf[i],1) then
begin
commflg:=false; //發送失敗
break;
end ;
sleep(2); //發送位元組間的延遲時間
viewstring:=viewstring+inttohex(sbuf[i],2)+' '; //發送的位元組
end;
viewstring:='發送'+viewstring;
form1.Memo2.Lines.Add(viewstring);
form1.Memo2.Lines.Add('');
if not commflg then messagedlg('發送失敗!',mterror,[mbyes],0);
end; procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word); //通訊埠接收資料
var
i: integer;
begin
viewstring:='';
move(buffer^,rbuf,bufferlength); //接受buffer中的位元組
for i:=1 to bufferlength do
viewstring:=viewstring+ inttohex(rbuf[i],2)+' '; //接收到的位元組
viewstring:='接收<<'+ viewstring;
memo1.lines.add(viewstring);
memo2.Lines.Add('數據接收OK!');
end; procedure TForm1.Button2Click(Sender: TObject);
begin
Comm1.StartComm; //開啟通訊埠
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
//要傳送的16進位資料至PLC端(即寫入Y0-Y7的值),值為:ENQ 01 FF BW 0 Y0000 08 01010101
sbuf[0] := $05; // ENQ
sbuf[1] := $30; // 0
sbuf[2] := $31; // 1
sbuf[3] := $46; // F
sbuf[4] := $46; // F
sbuf[5] := $42; // B
sbuf[6] := $57; // W
sbuf[7] := $30; // 0
sbuf[8] := $59;
sbuf[9] := $30;
sbuf[10] := $30;
sbuf[11] := $30;
sbuf[12] := $30;
sbuf[13] := $30;
sbuf[14] := $38;
sbuf[15] := $30;
sbuf[16] := $31;
sbuf[17] := $30;
sbuf[18] := $31;
sbuf[19] := $30;
sbuf[20] := $31;
sbuf[21] := $30;
sbuf[22] := $31;
senddata;
end;
另VB寫法:測試正常,PLC端有亮4個燈.
Private Sub Command1_Click()
MSComm1.PortOpen = True
Command1.Enabled = False
End Sub Private Sub Command3_Click()
Dim s(22) As Byte
s(0) = &H5
s(1) = &H30
s(2) = &H31
s(3) = &H46
s(4) = &H46
s(5) = &H42
s(6) = &H57
s(7) = &H30
s(8) = &H59
s(9) = &H30
s(10) = &H30
s(11) = &H30
s(12) = &H30
s(13) = &H30
s(14) = &H38
s(15) = &H30
s(16) = &H31
s(17) = &H30
s(18) = &H31
s(19) = &H30
s(20) = &H31
s(21) = &H30
s(22) = &H31
MSComm1.Output = s
End Sub 請各位幫忙小妹一下,謝謝了!
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
|
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
嗨!l630521您好!
以下是我改用MSComm控件寫的部分代碼如下: var
Form1: TForm1;
s: array[0..22] of byte; procedure TForm1.Button1Click(Sender: TObject);
begin
mscomm1.PortOpen := true ;
Button1.Enabled := false;
end; procedure TForm1.Button3Click(Sender: TObject);
begin
sbuf[0] := $05; // ENQ
sbuf[1] := $30; // 0
sbuf[2] := $31; // 1
sbuf[3] := $46; // F
sbuf[4] := $46; // F
sbuf[5] := $42; // B
sbuf[6] := $57; // W
sbuf[7] := $30; // 0
sbuf[8] := $59;
sbuf[9] := $30;
sbuf[10] := $30;
sbuf[11] := $30;
sbuf[12] := $30;
sbuf[13] := $30;
sbuf[14] := $38;
sbuf[15] := $30;
sbuf[16] := $31;
sbuf[17] := $30;
sbuf[18] := $31;
sbuf[19] := $30;
sbuf[20] := $31;
sbuf[21] := $30;
sbuf[22] := $31;
Mscomm1.Output := s ;
end; 可是在編譯的時候Mscomm1.Output := s這一行,出現錯誤:[Error] Unit1.pas(85): Incompatible types: 'OleVariant' and 'Array' 請問如何解決呢?感謝您的幫助
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
妳試試看下面的程式碼是否可行
var S: Variant; begin S := VarArrayCreate([0, 22], varByte); s[0] := $05; // ENQ s[1] := $30; // 0 s[2] := $31; // 1 s[3] := $46; // F s[4] := $46; // F s[5] := $42; // B s[6] := $57; // W s[7] := $30; // 0 s[8] := $59; s[9] := $30; s[10] := $30; s[11] := $30; s[12] := $30; s[13] := $30; s[14] := $38; s[15] := $30; s[16] := $31; s[17] := $30; s[18] := $31; s[19] := $30; s[20] := $31; s[21] := $30; s[22] := $31; Mscomm1.Output := s ; end;我還沒有用comport傳過這種型態的資料,之前都是直接傳字串, 例: MSComm1.Output := 'ENQ 01 FF BW 0 Y0000 08 01010101'這以看到這種方式我也不是很懂,只能從抄妳的程式碼去解決! Ian |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
hi,l630521,您好!感謝你的回復,參考你幫忙修改的代碼編譯沒有問題了,但是PLC端只是接收到信號,不理會傳送的資料,即沒有回應.(注:我不懂PLC,我負責PLC部分的同事說,只要將字串資料'ENQ01FFBW0Y00000801010101'先再換為16進位值再傳至PLC端應該就沒有問題了(VB測試可以).其中ENQ的16進位值為05H,0-30H,1-31H,F-46H,F-46H...L因為他不懂DELPHI,VB編程,只有這樣跟我說了,而我也是新手...
對了,請問有沒有別的方法或函數將'ENQ01FFBW0Y00000801010101'轉為16進位資料?謝謝
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
不用刻意轉為 16 進位表示
var S: Variant; begin S := VarArrayCreate([0, 22], varByte); s[0] := $05; // ENQ s[1] := $30; // 0 s[2] := $31; // 1 s[3] := $46; // F s[4] := $46; // F s[5] := $42; // B s[6] := $57; // W s[7] := $30; // 0 ...以上其實可用如下的寫法: var S: Variant; begin S := VarArrayCreate([0, 22], varByte); s[0] := $05; // ENQ s[1] := '0'; s[2] := '1'; s[3] := 'F'; s[4] := 'F'; s[5] := 'B'; s[6] := 'W'; s[7] := '0'; ...當然像 $05 這種不可視字元就得用 16 進位表示了. -- |
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
再試試看下面的程式碼
var s: String[22]; I: Integer; A: String; begin s[0] := Char($05); // ENQ s[1] := Char($30); // 0 s[2] := Char($31); // 1 s[3] := Char($46); // F s[4] := Char($46); // F s[5] := Char($42); // B s[6] := Char($57); // W s[7] := Char($30); // 0 s[8] := Char($59); s[9] := Char($30); s[10] := Char($30); s[11] := Char($30); s[12] := Char($30); s[13] := Char($30); s[14] := Char($38); s[15] := Char($30); s[16] := Char($31); s[17] := Char($30); s[18] := Char($31); s[19] := Char($30); s[20] := Char($31); s[21] := Char($30); s[22] := Char($31); ShowMessage(S); for I := 0 to 22 do A := A s[I]; ShowMessage(A); Mscomm1.Output := s ; MSComm1.Output := A; end;我試了一下,不知為何S會被截斷,所以我再用一個A來取得完整的字串, 如果用S不行就試看看A,這應該就會是妳所要傳到PLC的字串了! Ian |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
引言: 不用刻意轉為 16 進位表示hagar兄,你好!你說不用刻意用16進制表示?但是我同事說,要傳16進制資料至PLC,否則PLC不理會.所以我就想是不是先轉換成16進位值再送至PLC端,或者送一串字符('ENQ01FFBW0Y00000801010101'),再直接轉16進制的值送至PLC端呢?我想你可能比較懂串口編程與PLC吧(記得cashxin2002大大跟我說過,你是這方面的高手呢.)可不可以教我另外的辦法測試PC與PLC的簡單通訊呢?請問有沒有這方面的范例程式啊?謝謝!var S: Variant; begin S := VarArrayCreate([0, 22], varByte); s[0] := $05; // ENQ s[1] := $30; // 0 s[2] := $31; // 1 s[3] := $46; // F s[4] := $46; // F s[5] := $42; // B s[6] := $57; // W s[7] := $30; // 0 ...以上其實可用如下的寫法:var S: Variant; begin S := VarArrayCreate([0, 22], varByte); s[0] := $05; // ENQ s[1] := '0'; s[2] := '1'; s[3] := 'F'; s[4] := 'F'; s[5] := 'B'; s[6] := 'W'; s[7] := '0'; ...當然像 $05 這種不可視字元就得用 16 進位表示了. -- |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
引言: 再試試看下面的程式碼l630521你好,我也試過上述程式碼,S字串顯示不完整,只顯示為'01FFB',如果按你的程式碼,傳送的只是字串是嗎?不過我要傳16進制資料至PLC. 哎,反正到現在就是試不出來PC與PLC的正常通訊.不知怎麼辦好了.var s: String[22]; I: Integer; A: String; begin s[0] := Char($05); // ENQ s[1] := Char($30); // 0 s[2] := Char($31); // 1 s[3] := Char($46); // F s[4] := Char($46); // F s[5] := Char($42); // B s[6] := Char($57); // W s[7] := Char($30); // 0 s[8] := Char($59); s[9] := Char($30); s[10] := Char($30); s[11] := Char($30); s[12] := Char($30); s[13] := Char($30); s[14] := Char($38); s[15] := Char($30); s[16] := Char($31); s[17] := Char($30); s[18] := Char($31); s[19] := Char($30); s[20] := Char($31); s[21] := Char($30); s[22] := Char($31); ShowMessage(S); for I := 0 to 22 do A := A s[I]; ShowMessage(A); Mscomm1.Output := s ; MSComm1.Output := A; end;我試了一下,不知為何S會被截斷,所以我再用一個A來取得完整的字串, 如果用S不行就試看看A,這應該就會是妳所要傳到PLC的字串了! Ian |
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
引言: hagar兄,你好!你說不用刻意用16進制表示?但是我同事說,要傳16進制資料至PLC,否則PLC不理會.所以我就想是不是先轉換成16進位值再送至PLC端,或者送一串字符('ENQ01FFBW0Y00000801010101'),再直接轉16進制的值送至PLC端呢?我想你可能比較懂串口編程與PLC吧(記得cashxin2002大大跟我說過,你是這方面的高手呢.)可不可以教我另外的辦法測試PC與PLC的簡單通訊呢?請問有沒有這方面的范例程式啊?謝謝!我想 16 進制或一般文字只是給人看的 其實送出去給機器看的還是 0 或 1 吧 但是所表示的是一樣的東西 因此寫法可以用很多種, 比方說 s 個字串值為 abc 可以直接用 s := 'abc'; 或用 s := 'a' 'b' 'c'; 或用 s := Char($61) Char($62) Char($63); 或者像宣告成 s: array[1..3] of Char 的方式 s[1] := 'a'; 或 s[1] := Char($61); 另外您說要送出的字串是 'ENQ01FFBW0Y00000801010101' 有問題的是 ENQ 字串與 Char($05) 是不同的 ENQ 字有 3 個 byte, 而 Char($05) 只有一個 byte 也就是確定您要送出 ENQ 這個三個字元 還是要送出 Char($05) 這個字元 另外 S 會被截斷的原因是 delphi 的字串是從 1 開始的 不是 0 開始的(0 沒錯的話是記錄 s 這個字串的長度) 因此指定 s[0] 的值話就會被截斷了. var s: String; // 不用刻意限制長度 A: String; begin s := ''; s := s Char($05); // ENQ Char($30); // 0 Char($31); // 1 Char($46); // F Char($46); // F Char($42); // B Char($57); // W Char($30); // 0 Char($59); Char($30); Char($30); Char($30); Char($30); Char($30); Char($38); Char($30); Char($31); Char($30); Char($31); Char($30); Char($31); Char($30); Char($31); // 或寫成 s := Char($05) '01FFBW0Y00000801010101'; 即可 ShowMessage(S); A := ''; // A 要給預設值 for I := 0 to 22 do A := A s[I]; ShowMessage(A); Mscomm1.Output := s ; MSComm1.Output := A; end;最後要判斷機器有沒有一正確收到 可以先用另外一台電腦當成 PLC 來檢查看看 -- |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
引言:引言: 再試試看下面的程式碼l630521你好,我也試過上述程式碼,S字串顯示不完整,只顯示為'01FFB',如果按你的程式碼,傳送的只是字串是嗎?不過我要傳16進制資料至PLC. 哎,反正到現在就是試不出來PC與PLC的正常通訊.不知怎麼辦好了. >>< face="Verdana, Arial, Helvetica"> 我所知的也就這樣了,不過hagar前輩也給我上了一課,接下來可能就要麻煩hagar前輩了! Ianvar s: String[22]; I: Integer; A: String; begin s[0] := Char($05); // ENQ s[1] := Char($30); // 0 s[2] := Char($31); // 1 s[3] := Char($46); // F s[4] := Char($46); // F s[5] := Char($42); // B s[6] := Char($57); // W s[7] := Char($30); // 0 s[8] := Char($59); s[9] := Char($30); s[10] := Char($30); s[11] := Char($30); s[12] := Char($30); s[13] := Char($30); s[14] := Char($38); s[15] := Char($30); s[16] := Char($31); s[17] := Char($30); s[18] := Char($31); s[19] := Char($30); s[20] := Char($31); s[21] := Char($30); s[22] := Char($31); ShowMessage(S); for I := 0 to 22 do A := A s[I]; ShowMessage(A); Mscomm1.Output := s ; MSComm1.Output := A; end;我試了一下,不知為何S會被截斷,所以我再用一個A來取得完整的字串, 如果用S不行就試看看A,這應該就會是妳所要傳到PLC的字串了! Ian |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
|
l630521
資深會員 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
|
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
引言: 非常感謝yorkland兄,l630521兄,hagar兄的相助,傳送16進制資料至PLC測試已OK. 之前l630521幫忙修改的代碼是可以的,問題是PLC端與MSComm控件設定沒有一致.所以PLC端沒有反應.(我同事後來有更改PLC的設定忘記告訴我,真是被他打敗了.呵呵) 另外hagar兄提供的方法兩種寫法都行,特別是: s := Char($05) '01FFBW0Y00000801010101'; 真是簡單又好用! 接下來我要測試與 > >>< face="Verdana, Arial, Helvetica"> 其實還可以這麼寫(試試吧): < class="code"> begin s := #5'01FFBW0Y00000801010101'; // 或 s := #$05'01FFBW0Y00000801010101'; end; -- |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
引言: 其實還可以這麼寫(試試吧): < class="code"> begin s := #5'01FFBW0Y00000801010101'; // 或 s := #$05'01FFBW0Y00000801010101'; end; --嗨,hagar兄你好,測試可以耶< >, 只是不太懂為什麼這麼寫也都可以呢?< > 想請問一下 #5(或#05)與#$05為什麼可以與字串'01FFBW0Y00000801010101'一起用?並且之間可以不用加號( ),(我試過加上' '也行). 謝謝! |
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
是 Delphi 內的表示方法吧
比方說 16 進位的 5 可以用如下的方式表示:
begin Char($5) 或 Char($05) Chr($5) 或 Chr($05) #5 或 #$05 end;如果超過 10 的話就要注意了 比方說 #13 與 #$13 兩個是不一樣的 有加 $ 的是 16 進位, 沒加的是 10 進位, 例: #13 與 #$13 兩者是代表不同的值 #13 等於 Char(13) #$13 等於 #19 等於 Char($13) 等於 Char(19) 注意到 #5'01FFBW0Y00000801010101' 的 #5 前面是沒有單引號的 再以 A 這個字元來說 可以直接用 A 來表示 或用 Char($41) 或 Chr($41) 來表示(這兩個是 16 進位表示) 或用 Char(65) 或 Chr(65) 來表示(這兩個是 10 進位表示) 或用 #$41 或 #65 來表示(前者為 16 進位表示,後者為 10 進位表示) -- 發表人 - hagar 於 2005/03/18 12:06:06 |
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
|
jery5540
一般會員 發表:0 回覆:1 積分:0 註冊:2005-03-20 發送簡訊給我 |
對於你的問題, 可能只需要一點觀念上的改變就較能理解了, 你可能知道PLC一般在處理資料時, 所用的是16位元的記憶體儲存方式, 也就是一次處理16個bit. 或DWORD, 也就是兩個字元. 所以當你在寫入&H30(48, "0"), 在該記憶體位置的值皆為00110000(8bit)(一般一個位址需填入兩個字元所以應填入&H0 &H30), 也就是說不管你要寫入的是什麼, 你的輸出串流應該滿足的條件是00000000 00110000(8bit), 至於什麼格式, 其實只是你方便看就好了, 機器只認得ON or OFF啦
|
zxy666666
中階會員 發表:108 回覆:150 積分:86 註冊:2005-01-14 發送簡訊給我 |
引言: 對於你的問題, 可能只需要一點觀念上的改變就較能理解了, 你可能知道PLC一般在處理資料時, 所用的是16位元的記憶體儲存方式, 也就是一次處理16個bit. 或DWORD, 也就是兩個字元. 所以當你在寫入&H30(48, "0"), 在該記憶體位置的值皆為00110000(8bit)(一般一個位址需填入兩個字元所以應填入&H0 &H30), 也就是說不管你要寫入的是什麼, 你的輸出串流應該滿足的條件是00000000 00110000(8bit), 至於什麼格式, 其實只是你方便看就好了, 機器只認得ON or OFF啦非常感謝jery5540前輩的指導 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |