基于 Libnodave 的上位机与西门子 S7200PPI 通讯

期刊: 创新科技研究 DOI: PDF下载

许士亚 1 阳剑 2

南京钢铁股份有限公司江苏南京110819 东北大学信息科学与工程学院辽宁沈阳110819

摘要

本文提出一种基于 LIBNODAVE 的 PC 端上位机与西门子 S7200PLC 的通讯方法。给出了基于 C#的上位机监控软件与 S7-200 系列 PLC 进行 PPI 通讯的具体实现。分析及测试结果表明,这种通讯方法是一 种可行、低成本、可拓展性强的设计方案。


关键词

LIBNODAVE; 上位机; S7200 PLC; PPI

正文


西门子 PLC 在工业领域具有广泛的应用,其   S7200 系列主要应用于小型控制系统中,有时需要通  过上位机进行监控,以监视过程运行状态、调节设定  及进行其它操作。S7200PLC 监控可采用的方式通常  包括西门子 WinCCPRODAVE、第三方组态软件如  组态王、OPC Server 等。通讯接口形式为 PPI 或工业  以太网等。但这些通讯方式通常需要安装具有较高授  权费用的软件, 甚至需要配装相应硬件。因此,本  文提出一种基于 LIBNODAVE 的开源免费的通讯方案。


本文首先对 LIBNODAVE 进行了简要介绍,然后 结合 C#语言给出基于 LIBNODAVE 的西门子 S7200 上位机的开发方法。

1   LIBNODAVE 概述

LIBNODAVE 是德国人 Thomas Hergenhahn 开发 的一款可与西门子 S7-200/300/400 系列 PLC 进行通 讯的开源、免费的函数库, 遵循 GNU 库公用许可证 版本 2 及以上。它可运行在 Windows、Linux 及 Unix 操作系统上。其开发工作始于 2002 年,目前版本为


2014   LIBNODAVE-0.8.5.1     Sourceforge 网站上下载到最新的版本。LIBNODAVE 提供了与西门子 S7-200、300 和 400 系列 PLC 以及 与上述西门子 PLC 兼容的 PLC 产品(如艾莫迅 PLC) 的进行数据交换。它可以访问通过 PLC 程序能访问 的存储区域:位存储区、数据块、输入/输出映像区、

定时器和计数器等。另外, LIBNODAVE 还可以读取 PLC 程序中的功能块。支持的西门子通讯硬件设备有 MPI 适配 器、TS     IBH/MHJ-NetLink

CP243/343/443 以及内建了以太网支持的 PLC。目前, LIBNODAVE 已经可以结合 C、C++、C#、VB.NET  VBPascalDelphiPerl 来使用,LIBNODAVE   软件包里提供了相应的测试例子,但是功能并不完善。 此外,LIBNODAVE 还有一个不足是开发文档不够完  整,并且比较分散,有些地方需要结合源码来理解。  虽然 LIBNODAVE 版本还没达到 1.0,但是其当前的  功能已足够满足一般的应用了, 而且可以进一步通   TkQt 等跨平台 GUI 软件将 LIBNODAVE 的上  位机功能拓展到嵌入式系统中去,从而进一步降低成  本和扩大它的应用范围。

2   基于 LIBNODAVE 的建立上位机与 S7200  PPI 通讯连接

.net 下建立与西门子 S7200PLC 的通讯,首先 最好进行一定的封装,本文采用 C#语言,封装的类  PLCItem。主要参数设置及连接相关函数定义如下:

功能

主要代码

引用

using System.Runtime.InteropServices;//DllImport 调用非托管 DLL 函数需要该引用支持

数据

项定 

private libnodave.daveOSserialType fds; private libnodave.daveInterface di;

public libnodave.daveConnection dc; static int localPPI = 0;

static int plcPPI = 2;

private int _errorCode;

private bool _connected;

连接 PLC

public bool ConnectPLC(string portnum, string baud, int parity)

{

if (_connected) disconnectPLC();

fds.rfd = libnodave.setPort(portnum, baud, parity );

 


 


fds.wfd=fds.rfd;

if (fds.rfd > 0) {

di = new libnodave.daveInterface(fds, "IF1", localPPI, libnodave.daveProtoPPI,

libnodave.daveSpeed187k);

di.setTimeout(1000000);

dc = new libnodave.daveConnection(di, plcPPI, 0, 0);

if (0 == dc.connectPLC()) { _connected = true;

return true; } }

return false; }

断开 PLC

public void disconnectPLC() {

if (dc != null)

{

dc.disconnectPLC();

}

libnodave.closePort(fds.rfd); _connected = false;

}

3   读写数据的核心函数方法

读数 

public int ReadBytes(AreaType area, int db, int address, int numBytes, byte[]buf)

{

if (area !=AreaType.daveDB) db = 0;

return dc.readBytes((int)area, db, address, numBytes, buf);

}

写数 

[DllImport("libnodave.dll"/*, PreserveSig=false */ )]

public static extern void davePut8At(byte[]b, int pos, int v);

[DllImport("libnodave.dll"/*, PreserveSig=false */ )]

public static extern void davePut16At(byte[]b, int pos, int v);

[DllImport("libnodave.dll"/*, PreserveSig=false */ )]

public static extern void davePut32At(byte[]b, int pos, int v);

 


 



[DllImport("libnodave.dll"/*, PreserveSig=false */ )]

public static extern void davePutFloatAt(byte[]b, int pos, float v);

 

public bool WriteBytes(AreaType area, int db, int address, int numBytes, byte[]buf)

{

if (area != AreaType.daveDB) db = 0;

_errorCode = dc.writeBytes((int)area, db, address, numBytes , buf);

return 0 == _errorCode; }

相关

数据

区常

量定 

public enum AreaType : int {

daveSysInfo = 0x3,  // System info of 200 family daveSysFlags = 0x5, //    System flags of 200  family

daveAnaIn = 0x6,        // analog inputs of 200 family

daveAnaOut = 0x7, // analog outputs of 200 family

daveP = 0x80,     // direct peripheral access daveInputs = 0x81,  // Output

daveOutputs = 0x82, // Input

daveFlags = 0x83,   // M memory

daveDB = 0x84,        // data blocks

daveDI = 0x85,    // instance data blocks daveLocal = 0x86,  // not tested

daveV = 0x87,      // don't know what it is daveCounter = 28,  // S7 counters

daveTimer = 29,         // S7 timers

daveCounter200 = 30,    // IEC counters (200 family)

daveTimer200 = 31, // IEC timers (200 family) }

4   上位机编程范例

连接PLC:

if (plc1.ConnectPLC("COM3", "9600", 'E'))

{ MessageBox.Show("PLC连接成功!"); }//串口号根据实际 情况设置

else MessageBox.Show("PLC连接失败!");

断开PLC连接:if (plc1.connected) plc1.disconnectPLC();

 


读取 MB5,MW6,MD8,MD14,数据类型分别为 Byte Int, Dint, Real:

byte[]buf=new byte[11];

plc1.ReadBytes(AreaType.daveFlags, 0, 5, 11,buf);

byte MB5 = (byte)plc1.dc.getS8();

short MW6 = (short) plc1.dc.getS16();

int MD8 = plc1.dc.getS32();

float MD14 = plc1.dc.getFloatAt(9);

读位数据:

bool M5_3 = 0!=(MB5 & (1 << 3)); //获取M5.3

写入 MB5,MW6, MD8, MD14:

byte[]buf = new byte[11];

byte MB5 = 8;

short MW6 =2;

int MD8 = 3;

float MD14 =4;

PLCItem.davePut8At(buf, 0, MB5);

PLCItem.davePut16At(buf, 1, MW6);

PLCItem.davePut32At(buf, 3, MD8);

PLCItem.davePutFloatAt(buf,9, MD14);

plc1.WriteBytes(AreaType.daveFlags, 0, 5, 20, buf); 写位数据:

MB5 |= (byte)((MB5_3 ? 1 : 0) << 3);//设置M5.3

5   结论

本文提出一种基于 Libnodave 的上位机与西门子 S7200PLC 进行 PPI 通讯的开源、免费方案。该方案 适用于使用西门子 S7200 或兼容 S7200 的其他 PLC 的场合,主要用于相应硬件的低成本、灵活度高的监 控软件的开发。

参考文献

[1]孙书欢, 孔祥成, 吴雪婷. 西门子 PLC 设备开 源驱动库libnodave 的研究与改进[J]. 核电子学与探测 技术, 2013(07):64-68.

[2]周广颖, 张金金, 闫隆. 基于 LIBNODAVE  上位机 与西门子 PLC 的通信 [J]. 微计算机信息, 2010(31): 36-38.

[3]魏立新, 冯曦, 王洪庆, et al. LIBNODAVE  PLC 上位机监控软件中的运用[J]. 仪表技术与传感器, 2014(07):86-88.

Corresponding author: YANG Jian



...


阅读全文