delphi6中的OPC接口问题

时间:2020-12-12 17:37:10
各位高手:我现在用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, 出现接口不支持这种情况,但是测试中我只连一个读或者写,难道读和写中间有联系?

希望哪位高手不吝赐教!!!

2 个解决方案

#1


楼主,这个问题你解决了吗,怎么解决的

#2


感觉你这个问题不是OPC服务器的问题,和你用了线程有关系?

OPC现在用的少了,特别是基于COM的,实际运用中OPC会产生莫明其妙的错误,弄得你目瞪口呆。

如果可以的话,如果西门子PLC端是你们自己做的话,可以用串口、PPI、PROFIBUS等等

#1


楼主,这个问题你解决了吗,怎么解决的

#2


感觉你这个问题不是OPC服务器的问题,和你用了线程有关系?

OPC现在用的少了,特别是基于COM的,实际运用中OPC会产生莫明其妙的错误,弄得你目瞪口呆。

如果可以的话,如果西门子PLC端是你们自己做的话,可以用串口、PPI、PROFIBUS等等