各位高手:我現在用delphi6.0編OPC程式時,想實作寫入或讀取西門子PLC中的資料,現在遇到這樣一個現象,不知各位高手有沒有遇到過?
我定義了一個PLCCLASS類(PlcClass.pas),類中包含OPC的讀寫函式:
function plc_read_byte():integer;
function plc_write_word(ym:array of word):integer;
function Tplc.plc_read_byte():integer;
var
i:integer;
begin
result := -1;
for i:=0 to 5 do
begin
HR := ReadOPCGroupItemValue(GroupIf, jubinr[i],ItemValuer[i], ItemQuality);
end;
HR := 0;
if Succeeded(HR) then
begin
result := 1;
end
else
begin
result := -1;
exit;
end;
end;
function Tplc.plc_write_word(ym:array of word):integer;
var
i:integer;
begin
result :=-1;
HR := WriteOPCGroupItemValue(GroupIf,jubinw[0],ym[0]);
if Succeeded(HR) then
begin
result := 1;
showmessage('寫入成功');
end
else
begin
result := -1;
exit;
end;
end;
同步讀和同步寫函式中變數及介面都定義在全域變數中(GOLBALVAR.pas)中。因為讀和寫的項不同,我在一個表單(st.pas)中制作了2個按鈕實作連接讀和連接寫,呼叫opcutils.pas中的各個函式,分別是;
procedure Tst_form.BitBtnCWClick(Sender: TObject);
var
i:integer;
begin
xiangnamew[0] := 'S7:[S7 connection_1]DB1,WORD0';
xiangnamew[1] := 'S7:[S7 connection_1]DB1,WORD2';
xiangnamew[2] := 'S7:[S7 connection_1]DB1,WORD4';
xiangnamew[3] := 'S7:[S7 connection_1]DB1,WORD6';
HR := GroupAddItem(GroupIf,xiangname[0], 0, VT_EMPTY,Item0Handle,ItemType); //函式在OPCutils.pas中
for i := 0 to 3 do
begin
HR := GroupAddItem(GroupIf,xiangnamew[i], 0, VT_EMPTY,Item0Handle,ItemType); //函式
end;
if Succeeded(HR) then
begin
memo1.Lines.add('添加資料item成功!');
end
else
begin
memo1.Lines.add('添加資料item失敗!');
Exit;
end;
jubinw[i] := Item0Handle;
end;
end;
procedure Tst_form.BitBtnCRClick(Sender: TObject);
var
i:integer;
begin
xiangnamer[0] := 'S7:[S7 connection_3]DB1,byte0';
xiangnamer[1] := 'S7:[S7 connection_3]DB1,byte2';
xiangnamer[2] := 'S7:[S7 connection_3]DB1,byte4';
xiangnamer[3] := 'S7:[S7 connection_3]DB1,byte6';
xiangnamer[4] := 'S7:[S7 connection_3]DB1,byte8';
xiangnamer[5] := 'S7:[S7 connection_3]DB1,byte10';
HR := GroupAddItem(GroupIf,xiangname[0], 0, VT_EMPTY,Item0Handle,ItemType); //函式在OPCutils.pas中
for i := 0 to 5 do
begin
HR := GroupAddItem(GroupIf,xiangnamer[i], 0, VT_EMPTY,Item0Handle,ItemType); //函式在OPCutils.pas中
jubinr[i] := Item0Handle;
end;
if Succeeded(HR) then
begin
memo1.Lines.add('添加資料item成功!');
end
else
begin
memo1.Lines.add('添加資料item失敗!');
Exit;
end;
end;
連接讀和寫都能成功,連接寫成功后,我創建了一個執行緒,呼叫plcclass 中的function Tplc.plc_write_word(ym:array of word):integer;,能夠將資料成功寫入。
關閉程式后,重新運行,只連接讀,并連接讀成功,同樣是執行緒,呼叫plcclass中的function plc_write_word(ym:array of word):integer; 就會報錯,大致意思是EintfCastError with message ’Interface not supported’,程式停在下面標紅的地方(在OPCutiIs中):
function ReadOPCGroupItemValue(GroupIf: IUnknown; ItemServerHandle: OPCHANDLE;
var ItemValue: string; var ItemQuality: Word): HResult;
var
SyncIOIf: IOPCSyncIO;
Errors: PResultList;
ItemValues: POPCITEMSTATEARRAY;
begin
Result := E_FAIL;
try
SyncIOIf := GroupIf as IOPCSyncIO;
except
SyncIOIf := nil;
end;
if SyncIOIf <> nil then
begin
Result := SyncIOIf.Read(OPC_DS_CACHE, 1, @ItemServerHandle, ItemValues,
Errors);
if Succeeded(Result) then
begin
Result := Errors[0];
CoTaskMemFree(Errors);
ItemValue := VarToStr(ItemValues[0].vDataValue);
ItemQuality := ItemValues[0].wQuality;
VariantClear(ItemValues[0].vDataValue);
CoTaskMemFree(ItemValues);
end;
end;
end;
后來,我在Form中增加一個按鈕,實作在只連接讀后,單擊這個按鈕直接呼叫function ReadOPCGroupItemValue(GroupIf: IUnknown; ItemServerHandle: OPCHANDLE;
var ItemValue: string; var ItemQuality: Word): HResult;
就能獨到OPC中的資料。
現在的問題有2個:
1. 同樣是在執行緒中實作,為什么同步寫能成功,同步讀就讀不到資料(同步讀和同步寫是分開進行測驗的)?
2. 同樣是同步讀,放在執行緒中會報錯,放在按鈕單擊觸發中就能讀到資料?
后來我想有2個可能,
1. delphi6環境的問題,我看網上很多OPC案例是在delphi7環境中實作,不知道有哪位高手出來指教?
2. 懷疑是添加服務器的時候出的錯,呼叫同一個Groupif, 出現介面不支持這種情況,但是測驗中我只連一個讀或者寫,難道讀和寫中間有聯系?
希望哪位高手不吝賜教!!!
uj5u.com熱心網友回復:
樓主,這個問題你解決了嗎,怎么解決的uj5u.com熱心網友回復:
感覺你這個問題不是OPC服務器的問題,和你用了執行緒有關系?OPC現在用的少了,特別是基于COM的,實際運用中OPC會產生莫明其妙的錯誤,弄得你目瞪口呆。
如果可以的話,如果西門子PLC端是你們自己做的話,可以用串口、PPI、PROFIBUS等等
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/133600.html
標籤:網絡通信/分布式開發
上一篇:sqlserver中超時問題
