西门子PLC的通信协议主要是PPI、MPI、Profibus、CP243/CP343/CP443 网络协议,prodave是早期完成的程序接口,除了网络协议外其它的主要协议都支持,SoftNet是西门子最新推出的通信协议接口,稳定,并且大而全,目前西门子所有主流的协议都支持(我的blog文章:西门子Softnet驱动的成功开发已经做了简单介绍),由于好多朋友对prodave都比较关注,所以我这里专门写篇blog来简单介绍一下。

        我所知道的最新的Prodave的版本是V5.5,完整版的要45兆左右,由于出的比较早,所以动态库“W95_s7.dll”的名称保留至今,我最早接触是在01~02年,不过当时版本好像不到V5.5,与S7-200通信很不稳定,并且访问周期比较长。给我的感觉Prodave好像专门为S7-300制作的(从库函数的声明可以看出),连S7-300相对而言比较顺利。

       组态王、力控好多主流工控软件访问西门子PLC都是通过Prodave或Softnet的,可以在驱动程序中看到熟悉的W95_s7.dll,所以通信能力大家还是应该放心的。

       题外话,对嵌入式系统,如WinCE,由于不能直接使用Prodave和Softnet,所以要实现与西门子PLC通信,一般只有破解了(西门子的通信协议都是保密的,并且也是加密的,一般不公开给客户),目前实现的较好的主要有PPI,MPI(需要MPI适配器,不同适配器通信协议有一定区别),CP243,CP343/CP443。

      下面是我在开发相关西门子通信程序时,做的一个VC测试程序,仅供参考(Prodave简版驱动和相关测试代码,我已经上传,文章后面附下载连接)。 

   
   
   
   
  1. void CTestDlg::OnProdave()   
  2. {  
  3.     int iRes;  
  4.     CString myStr;  
  5.     signed char Buffer[2048];  
  6.  
  7.     WORD *Buffer_int = (WORD *)Buffer;  
  8.     unsigned char *Buffer_byte = (unsigned char *)Buffer;    //WORD wValue;  
  9.  
  10.     //m_field_read MB200  
  11.     iRes=m_field_read(200,1,Buffer);  
  12.  
  13.     if(iRes==0)  
  14.     {  
  15.         m_Dis.SetSel(100000,100000);  
  16.         m_Dis.ReplaceSel(" ");  
  17.  
  18.         myStr.Format("MB200=%3d",Buffer_byte[0]);  
  19.         m_Dis.ReplaceSel(myStr);  
  20.  
  21.         UpdateData(false);  
  22.     }  
  23.     else 
  24.     {  
  25.         //myStr.Format("m_field_read error no:%d",iRes);  
  26.         AfxMessageBox(ErrString(iRes));          
  27.     }  
  28.  
  29.     //m_field_read  
  30.     iRes=m_field_read(100,1,Buffer);  
  31.  
  32.     if(iRes==0)  
  33.     {  
  34.         m_Dis.SetSel(100000,100000);  
  35.         m_Dis.ReplaceSel(" ");  
  36.         myStr.Format("MB100=%3d",Buffer_byte[0]);  
  37.  
  38.         m_Dis.ReplaceSel(myStr);  
  39.  
  40.         UpdateData(false);  
  41.     }  
  42.     else 
  43.     {  
  44.         AfxMessageBox(ErrString(iRes));          
  45.     }      
  46.  
  47.     //m_field_read  
  48.     iRes=a_field_read(0,1,Buffer);  
  49.  
  50.     if(iRes==0)  
  51.     {  
  52.         m_Dis.SetSel(100000,100000);  
  53.         m_Dis.ReplaceSel(" ");  
  54.         myStr.Format("QB0=%3d",Buffer_byte[0]);  
  55.  
  56.         m_Dis.ReplaceSel(myStr);  
  57.  
  58.         UpdateData(false);  
  59.     }  
  60.     else 
  61.     {  
  62.         AfxMessageBox(ErrString(iRes));          
  63.     }  
  64.  
  65.     //写数据 MB110  
  66.     unsigned long value;  
  67.     value=100;  
  68.     memcpy(Buffer,&value,4);  
  69.  
  70.     iRes=m_field_write(111,1,Buffer);  
  71.     if(iRes==0)  
  72.     {  
  73.         m_Dis.SetSel(100000,100000);  
  74.         m_Dis.ReplaceSel(" ");  
  75.         myStr.Format("MB110=%3d",Buffer[0]);  
  76.         m_Dis.ReplaceSel(myStr);  
  77.         UpdateData(false);  
  78.     }  
  79.     else 
  80.     {  
  81.         AfxMessageBox(ErrString(iRes));          
  82.     }  
  83.  
  84.     //写数据 MB4  
  85.     BYTE value1;  
  86.     value1=33;  
  87.     memcpy(Buffer,&value,1);  
  88.     iRes=m_field_write(4,1,Buffer);  
  89.     if(iRes==0)  
  90.     {  
  91.         m_Dis.SetSel(100000,100000);  
  92.         m_Dis.ReplaceSel(" ");  
  93.         myStr.Format("MD4=%3d",Buffer[0]);  
  94.         m_Dis.ReplaceSel(myStr);  
  95.         UpdateData(false);  
  96.     }  
  97.     else 
  98.     {  
  99.         AfxMessageBox(ErrString(iRes));          
  100.     }  
  101. }  
  102.  
  103. void CTestDlg::OnLoad()   
  104. {  
  105.     adr_table_type myTable[2];  
  106.     myTable[0].adr=3;  
  107.     myTable[0].segmentid=0;  
  108.     myTable[0].slotno=2;  
  109.     myTable[0].rackno=0;  
  110.     myTable[1].adr=0;  
  111.     myTable[1].segmentid=0;  
  112.     myTable[1].slotno=2;  
  113.     myTable[1].rackno=0;  
  114.     int iRes;  
  115.     CString myStr;  
  116.     //初始化ProDave300  
  117.     iRes=load_tool(1,"S7ONLINE",myTable);  
  118.     if(iRes==0)  
  119.     {  
  120.         m_Dis.SetSel(30000,30000);  
  121.         m_Dis.ReplaceSel(" ");  
  122.         m_Dis.ReplaceSel("load_tool ok!");  
  123.         UpdateData(false);  
  124.     }  
  125.     else 
  126.     {  
  127.         AfxMessageBox(ErrString(iRes));  
  128.         unload_tool();  
  129.         return;          
  130.     }      
  131. }  
  132.  
  133. void CTestDlg::OnUnloadtool()   
  134. {  
  135.     int iRes;  
  136.     CString myStr;  
  137.     iRes=unload_tool();  
  138.     if(iRes==0)  
  139.     {  
  140.         m_Dis.SetSel(30000,30000);  
  141.         m_Dis.ReplaceSel(" ");  
  142.         m_Dis.ReplaceSel("unload_tool ok!");  
  143.         m_Dis.ReplaceSel(" ");  
  144.         UpdateData(false);  
  145.     }  
  146.     else 
  147.     {  
  148.         AfxMessageBox(ErrString(iRes));          
  149.     }      
  150. }  
  151.  
  152. void CTestDlg::OnStatus()   
  153. {  
  154.     int iRes;  
  155.     CString myStr;  
  156.     char  myInfo[512];  
  157.     iRes=ag_zustand(myInfo);  
  158.     if(iRes==0)  
  159.     {  
  160.         m_Dis.SetSel(30000,30000);  
  161.         m_Dis.ReplaceSel(" ");  
  162.         m_Dis.ReplaceSel("ag_zustand ok!");  
  163.         UpdateData(false);  
  164.         if(myInfo[0]==0)  
  165.         {  
  166.             m_Dis.ReplaceSel(" ");  
  167.             m_Dis.ReplaceSel("RUN");  
  168.         }  
  169.         else 
  170.         {  
  171.             m_Dis.ReplaceSel(" ");  
  172.             m_Dis.ReplaceSel("STOP");  
  173.         }  
  174.         UpdateData(false);  
  175.     }  
  176.     else 
  177.     {  
  178.         AfxMessageBox(ErrString(iRes));          
  179.     }      
  180. }  
  181. LPSTR CTestDlg::ErrString(WORD wErrCode)  
  182. {  
  183.     LPSTR myStr1;  
  184.     switch(wErrCode)  
  185.     {  
  186.     case 517:  
  187.         {  
  188.             return "PRODAVE not initialized.";  
  189.             break;  
  190.         }  
  191.     case 787:  
  192.         {  
  193.             return "Incorrect rate/Interrupt vector.";  
  194.             break;  
  195.         }  
  196.     case 789:  
  197.         {  
  198.             return "MPI Address error.";  
  199.             break;  
  200.         }  
  201.     case 800:  
  202.     case 818:  
  203.         {  
  204.             return "hardware fault.";  
  205.             break;  
  206.         }  
  207.     case 820:  
  208.         {  
  209.             return "com not avaliable.";  
  210.             break;  
  211.         }  
  212.     case 898:  
  213.     case 900:  
  214.         {  
  215.             return "no driver or device found.";  
  216.             break;  
  217.         }  
  218.     case 16386:  
  219.         {  
  220.             return "Connection not established.";  
  221.             break;  
  222.         }  
  223.     default:  
  224.         {  
  225.             CString myStr;  
  226.             myStr.Format("%d",wErrCode);  
  227.             myStr1=myStr.GetBuffer(0);  
  228.             myStr.ReleaseBuffer();  
  229.             return myStr1;  
  230.         }  
  231.     }  
  232. }  
  233.  
  234. void CTestDlg::OnNewss()   
  235. {  
  236.     //激活连接  
  237.     int iRes;  
  238.     iRes=new_ss(1);  
  239.     if(iRes==0)  
  240.     {  
  241.         m_Dis.SetSel(100000,100000);  
  242.         m_Dis.ReplaceSel(" ");  
  243.         m_Dis.ReplaceSel("new_ss ok!");  
  244.         UpdateData(false);  
  245.     }  
  246.     else 
  247.     {  
  248.         AfxMessageBox(ErrString(iRes));  
  249.         unload_tool();  
  250.         return;  
  251.     }      
  252. }  
  253.  
  254. void CTestDlg::OnAginfo()   
  255. {  
  256.     //读PLC信息  
  257.     int iRes;  
  258.     char  myInfo[512];  
  259.     iRes=ag_info(&myInfo[0] );  
  260.     if(iRes==0)  
  261.     {  
  262.         m_Dis.SetSel(100000,100000);  
  263.         m_Dis.ReplaceSel(" ");  
  264.         m_Dis.ReplaceSel("ag_info ok!");  
  265.         UpdateData(false);  
  266.  
  267.         m_Dis.ReplaceSel(" ");  
  268.         m_Dis.ReplaceSel(&myInfo[4]);  
  269.  
  270.         UpdateData(false);  
  271.     }  
  272.     else 
  273.     {  
  274.         AfxMessageBox(ErrString(iRes));  
  275.         unload_tool();  
  276.         return;  
  277.     }      
  278. }  
  279.  

prodave 测试程序:http://download.csdn.net/source/228758

Prodave简版驱动:http://download.csdn.net/source/228765