|
|
/**********************************************************************************
|
|
|
* Class for Communicate to PLC with Prodave
|
|
|
* Create by J0YANG
|
|
|
* Last Modify Date:2009-08-11
|
|
|
* ********************************************************************************/
|
|
|
|
|
|
/****************************与PLC通讯应用实例****************************************
|
|
|
为保证数据的一致性,可以使用一个定时器,触发时间设为PLC扫描周期,在其触发事件中,把需要用到的PLC变量
|
|
|
一次性读取.建立与PLC的连接,示例如下
|
|
|
PLCConnParam[] Conn=new PLCConnParam[2]; //MPI网中有2个PLC,地址分别为2,3
|
|
|
Conn[0] .Addres=2; Conn[0].Slot=2; Conn[0].Rack=0;
|
|
|
Conn[1] .Addres=3; Conn[1].Slot=2; Conn[1].Rack=0;
|
|
|
errCode= DCProdave.Open(1,Conn); //建立连接
|
|
|
errCode= DCProdave.ActiveConn(1); //激活第一个连接
|
|
|
errCode= DCProdave.GetDBByteData(2, 0, 6, buf, 0); //DB2.DBW0--DBW5 共6个字节的变量,从buf的0位存储
|
|
|
if(errCode!=0){//DCLog.Write(DCProdave.GetErrInfo(errCode),"log.txt");}//如果返回值不=0,则将错误写入日志
|
|
|
* *********************************************************************************/
|
|
|
|
|
|
using System;
|
|
|
using System.Text;
|
|
|
using System.Collections;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Runtime.InteropServices; //DllImport需要用到的库
|
|
|
|
|
|
namespace DCProdaveCS
|
|
|
{
|
|
|
#region 定义结构体[连接PLC所需参数]
|
|
|
public struct PLCConnParam
|
|
|
{
|
|
|
public byte Addres; // 定义CPU的MPI/DP地址
|
|
|
//public byte SegmentId; // 保留为0
|
|
|
public byte Rack; // 定义CPU的机架号
|
|
|
public byte Slot; // 定义CPU的槽号
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 定义枚举类型[PLC的存储区域编号]
|
|
|
public enum PLCBlockType
|
|
|
{
|
|
|
I = 1, //Input bytes
|
|
|
Q = 2, //Output bytes
|
|
|
M = 3, //Flag bytes
|
|
|
T = 4, //Timer words
|
|
|
Z = 5, //Counter words
|
|
|
D = 6, //Data from DB
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
public class DCProdave
|
|
|
{
|
|
|
/// <summary>静态构造函数
|
|
|
/// 在创建第一个实例或引用任何静态成员,函数之前,将自动调用静态构造函数来初始化类
|
|
|
/// </summary>
|
|
|
static DCProdave(){ }
|
|
|
|
|
|
#region 导入w95_s7.dll中的通讯函数
|
|
|
|
|
|
/// <summary>与PLC建立连接,该函数必须在其他所有函数调用之前被调用
|
|
|
/// 在一个MPI网络中若有多个CPU时,可指定多个连接列。最后一列的所有参数须置0,以标志参数列结束。
|
|
|
/// e.g.一个MPI网中有两个CPU,他们的MPI地址分别为2和3,槽号均为2,机架号均为0,则可按如下方式调用:
|
|
|
/// byte[,] btr={{2,0,2,0},{3,0,2,0},{0,0,0,0}}; int err=load_tool(1, "s7online",btr);
|
|
|
/// </summary>
|
|
|
/// <param name="nr">连接数,在DOS,WIN3.1最多可以有4个,在WIN95以上最多可以有16个</param>
|
|
|
/// <param name="device">与PLC通讯的设备名称,一般为S7ONLINE</param>
|
|
|
/// <param name="adr_table">参数列表,4个值分别为MPI/DP地址,保留值=0,槽号,机架号</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int load_tool(byte nr, string device, byte[,] adr_table);
|
|
|
|
|
|
/// <summary>断开与PLC的连接,必须退出数采软件之前调用,否则PLC的连接一直被占用,影响下次连接
|
|
|
/// </summary>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int unload_tool();
|
|
|
|
|
|
/// <summary>激活与MPI网中的哪个CPU通讯,load_tool后默认激活第一个CPU连接
|
|
|
/// 其参数与load_tool中参数adr_table所传递的连接参数顺序对应譬如byte[,] btr={{2,0,2,0},{3,0,2,0},{0,0,0,0}}
|
|
|
/// new_ss(1)则激活第1个连接即与MPI地址为2的PLC通讯,类似的new_ss(2)则激活与MPI地址为3的PLC通讯,
|
|
|
/// </summary>
|
|
|
/// <param name="no">连接号,对应于参数adr_table所传递的连接参数顺序</param>
|
|
|
/// <returns>0正常返回,非0为错误号,若激活的连接在MPI网中没有,则返回错误号517</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int new_ss(byte no);
|
|
|
|
|
|
|
|
|
/// <summary>从DB中读取BYTE数组(长度是WORD倍数,即双BYTE)
|
|
|
/// </summary>
|
|
|
/// <param name="dbno">DB块号</param>
|
|
|
/// <param name="dwno">DBW起始编号,=0表示DBW0,=1表示DBW2,跨度为WORD</param>
|
|
|
/// <param name="anzahl">读取的WORD长度(1个WORD==2个BYTE)</param>
|
|
|
/// <param name="buffer">返回值,BYTE型buffer</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int db_read(int dbno, int dwno, ref int anzahl, byte[] buffer);
|
|
|
|
|
|
/// <summary>从DB中读取INT数据(DBW:INT16 或者 DBD:INT32),最多4个字节的整数
|
|
|
/// </summary>
|
|
|
/// <param name="dbno">DB块号</param>
|
|
|
/// <param name="dwno">DBW起始编号,0表示DBW0,1表示DBW2,跨度为WORD</param>
|
|
|
/// <param name="anzahl">读取的WORD长度(1个WORD==2个BYTE) 2:DBW , 4:DBD</param>
|
|
|
/// <param name="buffer">返回值,int型整数(十进制)</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int db_read(int dbno, int dwno, ref int anzahl, ref int buffer);
|
|
|
|
|
|
/// <summary>从DB中读取BYTE数组(字节数可以是任意长度的)
|
|
|
/// </summary>
|
|
|
/// <param name="blockno">DB块号</param>
|
|
|
/// <param name="no">DBB起始编号,0表示DBB0,1表示DBB1,跨度为BYTE</param>
|
|
|
/// <param name="amount">读取的BYTE长度(任意长度,可以为奇数)</param>
|
|
|
/// <param name="buffer">返回值,BYTE型buffer</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int d_field_read(int blockno, int no, int amount, byte[] buffer);
|
|
|
|
|
|
/// <summary>测试DB块的状态 0:存在 !0:不存在
|
|
|
/// </summary>
|
|
|
/// <param name="buffer">buffer[123]!=0表明存在DB123</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int db_buch(ushort[] buffer);
|
|
|
|
|
|
|
|
|
/// <summary>读取PLC中的M字节数据
|
|
|
/// </summary>
|
|
|
/// <param name="no">指定M字节号,譬如要读取MB10的值,则指定no等于10</param>
|
|
|
/// <param name="anzahl">指定读取的字节数,譬如需要读取MB10至MB14之间的值,则可指定为5</param>
|
|
|
/// <param name="buffer">返回获取的值,这是一个十进制的值,如果需要获取某一个M位的状态,需要把它转换成二进制</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int m_field_read(int no, int anzahl, byte[] buffer);
|
|
|
|
|
|
/// <summary>获取MB变量的位状态值
|
|
|
/// </summary>
|
|
|
/// <param name="mbno"> 指定M字节号</param>
|
|
|
/// <param name="bitno"> 指定位号,范围为0-7,返回值</param>
|
|
|
/// <param name="retwert"> 大于0表示该位为1,=0表示该位为0</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int mb_bittest(int mbno, int bitno, ref byte retwert);
|
|
|
|
|
|
/// <summary>读取Output值
|
|
|
/// </summary>
|
|
|
/// <param name="no">QB号</param>
|
|
|
/// <param name="anzahl">读出多少个QB字节</param>
|
|
|
/// <param name="buffer">返回读出的值,十进制</param>
|
|
|
/// <returns></returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int a_field_read(int no, int anzahl, byte[] buffer);
|
|
|
|
|
|
/// <summary>读取Input的值
|
|
|
/// </summary>
|
|
|
/// <param name="no">IB号</param>
|
|
|
/// <param name="anzahl">读出多少个IB字节</param>
|
|
|
/// <param name="buffer">返回读出的值,十进制</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int e_field_read(int no, int anzahl, byte[] buffer);
|
|
|
|
|
|
/// <summary> 获取PLC的运行状态
|
|
|
/// </summary>
|
|
|
/// <param name="buffer">返回0或者1, 0表示Run;1表示Stop或者Restart</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
[DllImport("w95_s7.dll")]
|
|
|
private extern static int ag_zustand(ref byte buffer);
|
|
|
|
|
|
#region 往PLC写入数据,在数采系统中不允许的函数
|
|
|
//复位MB变量的位状态,指定M字节号,指定位号范围为0-7
|
|
|
//[DllImport("w95_s7.dll")] private extern static int mb_resetbit(short mbno, short bitno);
|
|
|
|
|
|
//置位MB变量的位状态,指定M字节号,指定位号,范围为0-7
|
|
|
//[DllImport("w95_s7.dll")] private extern static int mb_setbit(short mbno, short bitno);
|
|
|
|
|
|
// 写入Output值,no为QB号,anzahl为有多少个QB字节需要写入,buffer为指定写入的值
|
|
|
//[DllImport("w95_s7.dll")] private extern static int a_field_write(int no, int anzahl, byte[] buffer);
|
|
|
|
|
|
/// <summary>向DB中写入数据
|
|
|
/// </summary>
|
|
|
/// <param name="dbno">指定DB块号</param>
|
|
|
/// <param name="dwno">指定写入的起始字序号,=0表示DBW0,=1表示DBW2</param>
|
|
|
/// <param name="anzahl">指定写入的对象有多少个字</param>
|
|
|
/// <param name="buffer">写入值</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
//[DllImport("w95_s7.dll")] private extern static int db_write(int dbno, int dwno, ref int anzahl, ref long buffer);
|
|
|
|
|
|
/// <summary>向PLC中的M字节写入值
|
|
|
/// </summary>
|
|
|
/// <param name="no">指定M字节号,比如要读取MB10的值,则指定no等于10</param>
|
|
|
/// <param name="anzahl">指定写入的字节数</param>
|
|
|
/// <param name="buffer">向PLC中写入的值,十进制数据</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
//[DllImport("w95_s7.dll")] private extern static int m_field_write(short no, short anzahl, ref long buffer);
|
|
|
#endregion
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
#region 自定义与PLC的通讯函数,在w95_s7.dll的基础上进行封装
|
|
|
|
|
|
/// <summary>建立连接,同一个连接只容许调用一次
|
|
|
/// </summary>
|
|
|
/// <param name="connNo">连接号connNo为1-4</param>
|
|
|
/// <param name="connParam">连接参数,PLCConnParam定义的参数结构体</param>
|
|
|
/// <returns>返回10进制错误号,0表示没有错误</returns>
|
|
|
public static int Open(byte connNo, PLCConnParam[] connParam)
|
|
|
{
|
|
|
int PLCCPUCnt = connParam.Length;
|
|
|
if (PLCCPUCnt <= 0) //传递参数不正确
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
byte[,] btr = new byte[PLCCPUCnt + 1, 4]; //多分配1个,用于存放0作为连接结束标记
|
|
|
//转换连接表
|
|
|
for (int i = 0; i < connParam.Length; i++)
|
|
|
{
|
|
|
btr[i, 0] = connParam[i].Addres;
|
|
|
btr[i, 1] = 0;
|
|
|
btr[i, 2] = connParam[i].Slot;
|
|
|
btr[i, 3] = connParam[i].Rack;
|
|
|
}
|
|
|
btr[connParam.Length, 0] = 0;
|
|
|
btr[connParam.Length, 1] = 0;
|
|
|
btr[connParam.Length, 2] = 0;
|
|
|
btr[connParam.Length, 3] = 0;
|
|
|
//调用初始化函数,打开连接
|
|
|
int errCode = load_tool(connNo, "S7ONLINE", btr);
|
|
|
return errCode;
|
|
|
}
|
|
|
|
|
|
/// <summary>断开与PLC的连接,必须退出数采软件之前调用,否则PLC的连接一直被占用,影响下次连接
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public static int Close()
|
|
|
{
|
|
|
return unload_tool();
|
|
|
}
|
|
|
|
|
|
/// <summary>激活连接,设定与MPI网中的哪一个CPU通讯
|
|
|
/// </summary>
|
|
|
/// <param name="connNO">与load_tool中的参数adr_table所传递的连接参数顺序对应</param>
|
|
|
/// <returns>若激活的连接在MPI网中没有,则返回错误号517</returns>
|
|
|
public static int ActiveConn(int connNO)
|
|
|
{
|
|
|
return new_ss((byte)connNO);
|
|
|
}
|
|
|
|
|
|
/// <summary>从DB块中读取整型数据
|
|
|
/// 要读取DB2.DBW6,则DB块号为2,DBB号为6,字节长度为2
|
|
|
/// 要读取DB2.DBD6,则DB块号为2,DBB号为6,字节长度为4
|
|
|
/// </summary>
|
|
|
/// <param name="DBBlockNO">DB块号,如:DB2</param>
|
|
|
/// <param name="DBBNO">DBB的起始字节号,如DBW2则从2开始读,由于是WORD(2个BYTE),DBB号必须为偶数</param>
|
|
|
/// <param name="DBByteAmount">要读取的BYTE数,必须是偶数(这里只能是2和4,在PLC中只有DBW,DBD两种整数)</param>
|
|
|
/// <param name="buffer">INT32型缓存区,存储读取的十进制数据</param>
|
|
|
/// <returns>返回值 0:成功 非0:错误代码</returns>
|
|
|
public static int GetDBInt32Data(int DBBlockNO, int DBBNO, int DBByteAmount, ref int buffer)
|
|
|
{
|
|
|
int DBWNO = DBBNO / 2;
|
|
|
int DBWordAmount = DBByteAmount / 2;
|
|
|
int errCode = db_read(DBBlockNO, DBWNO, ref DBWordAmount, ref buffer);
|
|
|
byte[] bbuf = new byte[4];
|
|
|
GetByteFromInt32(buffer, bbuf, true);
|
|
|
buffer = bbuf[0] * 0x1000000 + bbuf[1] * 0x10000 + bbuf[2] * 0x100 + bbuf[3];
|
|
|
return errCode;
|
|
|
}
|
|
|
|
|
|
/// <summary>读取DB块的WORD数据
|
|
|
/// </summary>
|
|
|
/// <param name="DBBlockNO">DB块号,如:DB2</param>
|
|
|
/// <param name="DBWNO">DBW的起始字节号,如DBW2则从2开始读,由于是WORD(2个BYTE),DBW号必须为偶数</param>
|
|
|
/// <param name="DBWordAmount">要读取的WORD数,如从DBW2--DBW5,共2个WORD(4个BYTE)</param>
|
|
|
/// <param name="buffer">BYTE型缓存区,存储读取的数据</param>
|
|
|
/// <returns>返回值 0:成功 非0:错误代码</returns>
|
|
|
public static int GetDBWordData(int DBBlockNO , int DBWNO , int DBWordAmount , byte[] buffer)
|
|
|
{
|
|
|
return db_read(DBBlockNO, DBWNO, ref DBWordAmount, buffer);
|
|
|
}
|
|
|
|
|
|
/// <summary>读取DB块的BYTE数据
|
|
|
/// </summary>
|
|
|
/// <param name="DBBlockNO">DB块号,如:DB2</param>
|
|
|
/// <param name="DBBNO">DB数据的起始字节,如DBB2则从2开始读</param>
|
|
|
/// <param name="DBByteAmount">要读取的字节数,如从DBB2--DBB5,共4个字节</param>
|
|
|
/// <param name="buffer">BYTE型缓存区,存储读取的数据</param>
|
|
|
/// <param name="StartIndex">数据缓存区的起始位置</param>
|
|
|
/// <returns>返回值 0:成功 非0:错误代码</returns>
|
|
|
public static int GetDBByteData(int DBBlockNO, int DBBNO, int DBByteAmount, byte[] buffer, int StartIndex)
|
|
|
{
|
|
|
byte[] bBufTemp = new byte[DBByteAmount];
|
|
|
int errCode=d_field_read(DBBlockNO, DBBNO, DBByteAmount, bBufTemp);
|
|
|
for(int i=0;i<DBByteAmount;i++)
|
|
|
{
|
|
|
buffer[i+StartIndex] = bBufTemp[i] ;
|
|
|
}
|
|
|
return errCode;
|
|
|
}
|
|
|
|
|
|
/// <summary>从M区读取位状态数据
|
|
|
/// </summary>
|
|
|
/// <param name="MBlockNO">M区号,如M10</param>
|
|
|
/// <param name="MBitNO">要读取的位号,如M10.2则位号为2</param>
|
|
|
/// <param name="MBitState">位状态, 0:false,1:true</param>
|
|
|
/// <returns>0正常,非0为错误号</returns>
|
|
|
public static int GetMBitData(int MBlockNO, int MBitNO,ref bool MBitState)
|
|
|
{
|
|
|
int errCode;
|
|
|
if (MBlockNO >= 0 && MBitNO >= 0 && MBitNO <=7 )
|
|
|
{
|
|
|
byte rtn = 0;
|
|
|
errCode = mb_bittest(MBlockNO, MBitNO, ref rtn);
|
|
|
MBitState = (rtn == 0) ? false : true;
|
|
|
return errCode;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return -1; //越界,超出8个字节
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>从M,I,Q区中读取字节数组
|
|
|
/// </summary>
|
|
|
/// <param name="blockType">Block类别,在枚举PLCBlockType中定义,如要读取M区的值,则blockType=PLCBlockType.M</param>
|
|
|
/// <param name="BlockNO">区号,如IB10,MB10...</param>
|
|
|
/// <param name="ByteAmount">要读取的字节数量,如IB10--IB14共5个字节</param>
|
|
|
/// <param name="bbuf">byte[]类型的buffer</param>
|
|
|
/// <param name="StartIndex">byte[]存储的起始位置</param>
|
|
|
/// <returns>0正常返回,非0为错误号</returns>
|
|
|
public static int GetMIQByteData(PLCBlockType blockType, int BlockNO, int ByteAmount, byte[] bbuf, int StartIndex)
|
|
|
{
|
|
|
int errCode = 0;
|
|
|
byte[] bBufTemp = new byte[ByteAmount]; //局部变量,不用担心内存释放的问题. C++程序员看到"new"估计很谨慎.
|
|
|
switch (blockType) //根据块类别,调用相应的块读取函数.
|
|
|
{
|
|
|
case PLCBlockType.M: errCode = m_field_read(BlockNO, ByteAmount, bBufTemp); break;
|
|
|
case PLCBlockType.I : errCode = e_field_read(BlockNO, ByteAmount, bBufTemp); break;
|
|
|
case PLCBlockType.Q: errCode = a_field_read(BlockNO, ByteAmount, bBufTemp); break;
|
|
|
}
|
|
|
for (int i = 0; i < ByteAmount; i++) //由于C#中对指针有所限制,从数组指定的起始位置,逐个赋值.
|
|
|
{
|
|
|
bbuf[i + StartIndex] = bBufTemp[i];
|
|
|
}
|
|
|
return errCode;
|
|
|
}
|
|
|
|
|
|
/// <summary>从long型数据中提取byte字节数组
|
|
|
/// </summary>
|
|
|
/// <param name="lbuf">源数据(long型)</param>
|
|
|
/// <param name="bbuf">字节数组,存放提取的Byte数据</param>
|
|
|
/// <param name="startIndex">起始位置</param>
|
|
|
/// <param name="ByteAmount">提取的字节数</param>
|
|
|
/// <param name="isBigEndian">long型源数据是否高位优先,如果不是,则进行反向提取</param>
|
|
|
public static void GetByteFromInt32(int ibuf, byte[] bbuf , bool isBigEndian)
|
|
|
{
|
|
|
if (isBigEndian) //高位优先,则反向提取.
|
|
|
{
|
|
|
for (int i = 0; i <=3; i++) //Int32只有4个字节
|
|
|
{
|
|
|
bbuf[i] = (byte)(ibuf & 0x000000ff); //取低位字节
|
|
|
ibuf >>= 8; //右移8位
|
|
|
}
|
|
|
}
|
|
|
else //低位优先,按顺序提取.
|
|
|
{
|
|
|
for (int i = 3; i >= 0; i--)
|
|
|
{
|
|
|
bbuf[i] = (byte)(ibuf & 0x000000ff);
|
|
|
ibuf >>= 8;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>从Byte数据中取得所有bit的值(1Byte=8Bit , false:0 , true:1)
|
|
|
/// </summary>
|
|
|
/// <param name="byteData">源数据(Byte型),其中的8个bit位,从右到左0--7编号</param>
|
|
|
/// <param name="bitArray">bit数组,存放Byte中的8个bit的值,0:false, 1:true</param>
|
|
|
/// <param name="startIndex">在bit数组中存放的起始位置</param>
|
|
|
public static void GetBitFromByte(byte byteData, bool[] bitArray, int startIndex)
|
|
|
{
|
|
|
byte[] byteArray = new byte[1];
|
|
|
byteArray[0] = byteData;
|
|
|
System.Collections.BitArray BA = new System.Collections.BitArray(byteArray);
|
|
|
for (int i = 0; i <= 7; i++) //依次取8个位,逐个赋值
|
|
|
{
|
|
|
bitArray[startIndex + i] = BA.Get(i);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>从Byte数据中取得某一位bit的值(false:0 , true:1)
|
|
|
/// </summary>
|
|
|
/// <param name="byteData">源数据(Byte型),其中的8个bit位,从右到左0--7编号</param>
|
|
|
/// <param name="bitNo">bit位编号,从右到左以0--7编号</param>
|
|
|
/// <param name="bitData">bit值,以bool型返回,false:0 , true:1</param>
|
|
|
public static void GetBitFromByte(byte byteData, int bitNo, ref bool bitData)
|
|
|
{
|
|
|
if (bitNo >= 0 && bitNo <= 7) //位号必须在0~7之间
|
|
|
{
|
|
|
byte[] byteArray = new byte[1];
|
|
|
byteArray[0] = byteData;
|
|
|
System.Collections.BitArray BA = new System.Collections.BitArray(byteArray);
|
|
|
bitData = BA.Get(bitNo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>根据错误代码返回错误信息
|
|
|
/// 例如int errCode=ActiveConn(1); sring errInfo = GetErrInfo(err);
|
|
|
/// </summary>
|
|
|
/// <param name="errCode">错误码</param>
|
|
|
/// <returns>错误信息</returns>
|
|
|
public static string GetErrInfo(int errCode)
|
|
|
{
|
|
|
switch (errCode)
|
|
|
{
|
|
|
case -1: return "User-Defined Error!"; //自定义错误,主要是参数传递错误!
|
|
|
case 0x0000: return "Success";
|
|
|
case 0x0001: return "Load dll failed";
|
|
|
case 0x00E1: return "User max";
|
|
|
case 0x00E2: return "SCP entry";
|
|
|
case 0x00E7: return "SCP board open";
|
|
|
case 0x00E9: return "No Windows server";
|
|
|
case 0x00EA: return "Protect";
|
|
|
case 0x00CA: return "SCP no resources";
|
|
|
case 0x00CB: return "SCP configuration";
|
|
|
case 0x00CD: return "SCP illegal";
|
|
|
case 0x00CE: return "SCP incorrect parameter";
|
|
|
case 0x00CF: return "SCP open device";
|
|
|
case 0x00D0: return "SCP board";
|
|
|
case 0x00D1: return "SCP software";
|
|
|
case 0x00D2: return "SCP memory";
|
|
|
case 0x00D7: return "SCP no meas";
|
|
|
case 0x00D8: return "SCP user mem";
|
|
|
case 0x00DB: return "SCP timeout";
|
|
|
case 0x00F0: return "SCP db file does not exist";
|
|
|
case 0x00F1: return "SCP no global dos memory";
|
|
|
case 0x00F2: return "SCP send not successful";
|
|
|
case 0x00F3: return "SCP receive not successful";
|
|
|
case 0x00F4: return "SCP no device available";
|
|
|
case 0x00F5: return "SCP illegal subsystem";
|
|
|
case 0x00F6: return "SCP illegal opcode";
|
|
|
case 0x00F7: return "SCP buffer too short";
|
|
|
case 0x00F8: return "SCP buffer1 too short";
|
|
|
case 0x00F9: return "SCP illegal protocol sequence";
|
|
|
case 0x00FA: return "SCP illegal PDU arrived";
|
|
|
case 0x00FB: return "SCP request error";
|
|
|
case 0x00FC: return "SCP no license";
|
|
|
case 0x0101: return "Connection is not established / parameterized";
|
|
|
case 0x010a: return "Negative Acknowledgment received / timeout errors";
|
|
|
case 0x010c: return "Data not available or locked";
|
|
|
case 0x012A: return "No system memory left";
|
|
|
case 0x012E: return "Incorrect parameter";
|
|
|
case 0x0132: return "No storage space in the DPRAM";
|
|
|
case 0x0200: return "xx";
|
|
|
case 0x0201: return "Falsche Schnittstelle angegeben";
|
|
|
case 0x0202: return "Incorrect interface indicated";
|
|
|
case 0x0203: return "Toolbox already installed";
|
|
|
case 0x0204: return "Toolbox with other compounds already installed";
|
|
|
case 0x0205: return "Toolbox is not installed";
|
|
|
case 0x0206: return "Handle can not be set";
|
|
|
case 0x0207: return "Data segment can not be blocked";
|
|
|
case 0x0209: return "Erroneous data field";
|
|
|
case 0x0300: return "Timer init error";
|
|
|
case 0x0301: return "Com init error";
|
|
|
case 0x0302: return "Module is too small, DW does not exist";
|
|
|
case 0x0303: return "Block boundary erschritten, number correct";
|
|
|
case 0x0310: return "Could not find any hardware";
|
|
|
case 0x0311: return "Hardware defective";
|
|
|
case 0x0312: return "Incorrect configuration parameters";
|
|
|
case 0x0313: return "Incorrect baud rate/interrupt vector";
|
|
|
case 0x0314: return "HSA incorrectly parameterized";
|
|
|
case 0x0315: return "Address already assigned";
|
|
|
case 0x0316: return "Device already assigned";
|
|
|
case 0x0317: return "Interrupt not available";
|
|
|
case 0x0318: return "Interrupt occupied";
|
|
|
case 0x0319: return "SAP not occupied";
|
|
|
case 0x031A: return "Could not find any remote station";
|
|
|
case 0x031B: return "syni error";
|
|
|
case 0x031C: return "System error";
|
|
|
case 0x031D: return "Error in buffer size";
|
|
|
case 0x0320: return "DLL/VxD not found";
|
|
|
case 0x0321: return "DLL function error";
|
|
|
case 0x0330: return "Version conflict";
|
|
|
case 0x0331: return "Com config error";
|
|
|
case 0x0332: return "smc timeout";
|
|
|
case 0x0333: return "Com not configured";
|
|
|
case 0x0334: return "Com not available";
|
|
|
case 0x0335: return "Serial drive in use";
|
|
|
case 0x0336: return "No connection";
|
|
|
case 0x0337: return "Job rejected";
|
|
|
case 0x0380: return "Internal error";
|
|
|
case 0x0381: return "Device not in Registry";
|
|
|
case 0x0382: return "L2 driver not in Registry";
|
|
|
case 0x0384: return "L4 driver not in Registry";
|
|
|
case 0x03FF: return "System error";
|
|
|
case 0x4001: return "Connection is not known";
|
|
|
case 0x4002: return "Connection is not established";
|
|
|
case 0x4003: return "Connection is being established";
|
|
|
case 0x4004: return "Connection is collapsed";
|
|
|
case 0x0800: return "Toolbox occupied";
|
|
|
case 0x8001: return "in this mode is not allowed";
|
|
|
case 0x8101: return "Hardware error";
|
|
|
case 0x8103: return "Object Access not allowed";
|
|
|
case 0x8104: return "Context is not supported";
|
|
|
case 0x8105: return "ungtige Address";
|
|
|
case 0x8106: return "Type (data) is not supported";
|
|
|
case 0x8107: return "Type (data) is not consistent";
|
|
|
case 0x810A: return "Object does not exist";
|
|
|
case 0x8301: return "Memory on CPU is not sufficient";
|
|
|
case 0x8404: return "grave error";
|
|
|
case 0x8500: return "Incorrect PDU Size";
|
|
|
case 0x8702: return "Invalid address";
|
|
|
case 0xA0CE: return "User occupied";
|
|
|
case 0xA0CF: return "User does not pick up";
|
|
|
case 0xA0D4: return "Connection not available because modem prevents immediate redial (waiting time before repeat dial not kept to) ";
|
|
|
case 0xA0D5: return "No dial tone";
|
|
|
case 0xD201: return "Syntax error module name";
|
|
|
case 0xD202: return "Syntax error function parameter";
|
|
|
case 0xD203: return "Syntax error Bausteshortyp";
|
|
|
case 0xD204: return "no memory module in eingeketteter";
|
|
|
case 0xD205: return "Object already exists";
|
|
|
case 0xD206: return "Object already exists";
|
|
|
case 0xD207: return "Module available in the EPROM";
|
|
|
case 0xD209: return "Module does not exist";
|
|
|
case 0xD20E: return "no module present";
|
|
|
case 0xD210: return "Block number is too big";
|
|
|
case 0xD241: return "Protection level of function is not sufficient";
|
|
|
case 0xD406: return "Information not available";
|
|
|
case 0xEF01: return "Wrong ID2";
|
|
|
case 0xFFFE: return "unknown error FFFE hex";
|
|
|
case 0xFFFF: return "Timeout error. Interface KVD";
|
|
|
default: return "Unkonw error";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
}
|