Advantech 硬件控制卡的 c# 接口函数
最近要用到 Advantech 的 PCI-1752、PCI-1754 卡,但却苦于没有 c# 的调用接口函数。这两天接连奋战,根据 Delphi 的调用接口给转换掉,终于调试出来了,辛苦。
现共享一下主要的接口部分,免得大家多走弯路。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Hardware.Advantech.Interface
{
#region PT_DEVLIST
/// <summary>
/// 安装在主机上所有的自动控制板卡设备结构。
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
public struct PT_DEVLIST
{
public UInt32 dwDeviceNum;
/// <summary>
/// 设备名,50个字符长。
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=50)]
public string szDeviceName;
/// <summary>
/// 设备的端口数,一般为8个端口。
/// </summary>
public Int16 nNumOfSubdevices;
}
/// <summary>
/// 用于 DRV_DeviceGetList 调用返回的设备列表结构。
/// 这一块真难改呀~~,耗费了我一整个晚上的时间~~~~~~~
/// 网上也找不到资料,最可气的是.Net带的函数都不支持结构数组,只好变相再来一个结构了~~
/// xiefang 2007/09/02
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct PT_DEVLISTARRAY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = AdvantechAPI.MaxEntries)]
public PT_DEVLIST[] Devices;
}
#endregion
#region PT_DeviceGetFeatures
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DeviceGetFeatures
{
public IntPtr Buffer;
public int Size;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct GainListBlob
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)]
public byte[] gainArr;
}
/// <summary>
/// Define hardware board(device) features.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct DEVFEATURES
{
/// <summary>
/// device driver version, array[0..7]
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string szDriverVer;
/// <summary>
/// device driver name, array[0..MAX_DRIVER_NAME_LEN-1]
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = AdvantechAPI.MAX_DRIVER_NAME_LEN)]
public string szDriverName;
/// <summary>
/// board ID, DWORD 4 bytes
/// </summary>
public uint dwBoardID;
/// <summary>
/// Max. number of differential channel
/// </summary>
public ushort usMaxAIDiffChl;
/// <summary>
/// Max. number of single-end channel
/// </summary>
public ushort usMaxAISiglChl;
/// <summary>
/// Max. number of D/A channel
/// </summary>
public ushort usMaxAOChl;
/// <summary>
/// Max. number of digital out channel
/// </summary>
public ushort usMaxDOChl;
/// <summary>
/// Max. number of digital input channel
/// </summary>
public ushort usMaxDIChl;
/// <summary>
/// specifies if programmable or not
/// </summary>
public ushort usDIOPort;
/// <summary>
/// Max. number of Counter/Timer channel
/// </summary>
public ushort usMaxTimerChl;
/// <summary>
/// Max number of alram channel
/// </summary>
public ushort usMaxAlarmChl;
/// <summary>
/// number of bits for A/D converter
/// </summary>
public ushort usNumADBit;
/// <summary>
/// A/D channel width in bytes.
/// </summary>
public ushort usNumADByte;
/// <summary>
/// number of bits for D/A converter.
/// </summary>
public ushort usNumDABit;
/// <summary>
/// D/A channel width in bytes.
/// </summary>
public ushort usNumDAByte;
/// <summary>
/// Max. number of gain code
/// </summary>
public ushort usNumGain;
/// <summary>
/// Gain listing array[0..15]
/// </summary>
public GainListBlob glGainList;
/// <summary>
/// Permutation array[0..3]
/// Bit 0: Software AI
/// Bit 1: DMA AI
/// Bit 2: Interrupt AI
/// Bit 3: Condition AI
/// Bit 4: Software AO
/// Bit 5: DMA AO
/// Bit 6: Interrupt AO
/// Bit 7: Condition AO
/// Bit 8: Software DI
/// Bit 9: DMA DI
/// Bit 10: Interrupt DI
/// Bit 11: Condition DI
/// Bit 12: Software DO
/// Bit 13: DMA DO
/// Bit 14: Interrupt DO
/// Bit 15: Condition DO
/// Bit 16: High Gain
/// Bit 17: Auto Channel Scan
/// Bit 18: Pacer Trigger
/// Bit 19: External Trigger
/// Bit 20: Down Counter
/// Bit 21: Dual DMA
/// Bit 22: Monitoring
/// Bit 23: QCounter
/// </summary>
public uint dwPermutation0;
public uint dwPermutation1;
public uint dwPermutation2;
public uint dwPermutation3;
}
#endregion
/// <summary>
/// 写入设备的数据结构。
/// </summary>
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DioWritePortByte
{
[FieldOffset(0)]
public short Port;
[FieldOffset(2)]
public short Mask;
[FieldOffset(4)]
public short State;
}
/// <summary>
/// 读取IO设备的数据结构。
/// </summary>
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DioReadPortByte
{
[FieldOffset(0)]
public short Port;
[FieldOffset(4)]
public IntPtr value;
}
/// <summary>
/// 硬件调用的 API 函数封装类。
/// </summary>
public static class AdvantechAPI
{
/// <summary>
/// 最大设备个数
/// </summary>
public const short MaxEntries = 255;
public const short MaxDevices = 255;
public const short MAX_DRIVER_NAME_LEN = 16;
#region interface
/// <summary>
/// 获取设备列表。
/// </summary>
/// <param name="deviceList">返回的设备列表清单数组</param>
/// <param name="maxEntries">最大的设备数</param>
/// <param name="outEntries">返回的设备数</param>
/// <returns>返回值为 0 则表示执行成功,否则执行失败。</returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceGetList(IntPtr deviceList, Int16 maxEntries, ref short outEntries);
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceGetFeatures(int DriverHandle, ref PT_DeviceGetFeatures lpDeviceGetFeatures);
/// <summary>
/// 获取设备列表个数,我就基本用不到它,姑且留着。
/// </summary>
/// <param name="numOfDevices"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
public static extern int DRV_DeviceGetNumOfList(ref short numOfDevices);
/// <summary>
/// 打开设备。
/// </summary>
/// <param name="deviceNum">设备号</param>
/// <param name="driverHandle">设备句柄</param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceOpen(uint deviceNum, ref int deviceHandle);
/// <summary>
/// 关闭设备。
/// </summary>
/// <param name="deviceHandle"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceClose(ref int deviceHandle);
/// <summary>
/// 向端口写数字信号。
/// </summary>
/// <param name="DriverHandle"></param>
/// <param name="lpDioWritePortByte"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DioWritePortByte(int driverHandle, ref PT_DioWritePortByte lpDioWritePortByte);
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DioReadPortByte(int driverHandle, ref PT_DioReadPortByte lpDioReadPortByte);
#endregion
/// <summary>
/// 打开设备
/// </summary>
/// <param name="deviceNum">设备号</param>
/// <param name="deviceHandle">设备句柄</param>
/// <returns>返回错误代码,如果无错误,则返回0。</returns>
public static int OpenDevice(uint deviceNum, ref int deviceHandle)
{
return DRV_DeviceOpen(deviceNum, ref deviceHandle);
}
/// <summary>
/// 关闭设备。
/// </summary>
/// <param name="deviceHandle"></param>
public static void CloseDevice(int deviceHandle)
{
DRV_DeviceClose(ref deviceHandle);
}
/// <summary>
/// 获取主机上安装的设备列表。
/// </summary>
/// <returns>返回错误代码,如果无错误,则返回0。</returns>
public static int GetDeviceList(out PT_DEVLISTARRAY deviceList, ref short outEntries)
{
deviceList = new PT_DEVLISTARRAY();
int _DeviceListLenght = Marshal.SizeOf(deviceList);
IntPtr _DeviceListPoint = Marshal.AllocHGlobal(_DeviceListLenght);
//打开设备的检查过程
int errorCode = AdvantechAPI.DRV_DeviceGetList(_DeviceListPoint, MaxEntries, ref outEntries);
deviceList = (PT_DEVLISTARRAY)Marshal.PtrToStructure(_DeviceListPoint, typeof(PT_DEVLISTARRAY));
Marshal.FreeHGlobal(_DeviceListPoint);
return errorCode;
}
public static int GetFeatures(int deviceHandle, out DEVFEATURES outDevFeatures)
{
int iLength;
int ErrCde = 0;
PT_DeviceGetFeatures ptDevGetFeatures = new PT_DeviceGetFeatures();
outDevFeatures = new DEVFEATURES();
outDevFeatures.szDriverVer = "?";
outDevFeatures.szDriverName = "?";
iLength = Marshal.SizeOf(outDevFeatures);
//and reserve the space
IntPtr DevFeaturesPointer = Marshal.AllocHGlobal(iLength);
//Copy the pointer into the struct
ptDevGetFeatures.Buffer = DevFeaturesPointer;
//and get the features
ErrCde = DRV_DeviceGetFeatures(deviceHandle, ref ptDevGetFeatures);
if (ErrCde == 0)
{
outDevFeatures = (DEVFEATURES)Marshal.PtrToStructure(DevFeaturesPointer, typeof(DEVFEATURES));
}
else
{
//Error
}
Marshal.FreeHGlobal(DevFeaturesPointer);
return ErrCde;
}
/// <summary>
/// 数字信号按端口输出。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="port"></param>
/// <param name="value"></param>
/// <param name="mask"></param>
/// <returns></returns>
public static int Digital_WriteByteToPort(int deviceHandle, short port, short value, short mask)
{
PT_DioWritePortByte data = new PT_DioWritePortByte();
data.Port = port;
data.State = value;
data.Mask = mask;
return DRV_DioWritePortByte(deviceHandle, ref data);
}
public static int Digital_WriteByteToPort(int deviceHandle, short port, short value)
{
return Digital_WriteByteToPort(deviceHandle, port, value, 255);
}
/// <summary>
/// 从指定的端口获取数据。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="port"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int Digital_ReadByteFromPort(int deviceHandle, short port, out short value)
{
int error = 0;
short tempValue = 0;
IntPtr vpoint = Marshal.AllocHGlobal(Marshal.SizeOf(tempValue));
try
{
Marshal.StructureToPtr(tempValue, vpoint, false);
PT_DioReadPortByte data = new PT_DioReadPortByte();
data.Port = port;
data.value = vpoint;
error = DRV_DioReadPortByte(deviceHandle, ref data);
tempValue = (short)Marshal.PtrToStructure(vpoint, typeof(short));
value = tempValue;
}
finally
{
Marshal.FreeHGlobal(vpoint);
}
return error;
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Hardware.Advantech.Interface
{
#region PT_DEVLIST
/// <summary>
/// 安装在主机上所有的自动控制板卡设备结构。
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
public struct PT_DEVLIST
{
public UInt32 dwDeviceNum;
/// <summary>
/// 设备名,50个字符长。
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=50)]
public string szDeviceName;
/// <summary>
/// 设备的端口数,一般为8个端口。
/// </summary>
public Int16 nNumOfSubdevices;
}
/// <summary>
/// 用于 DRV_DeviceGetList 调用返回的设备列表结构。
/// 这一块真难改呀~~,耗费了我一整个晚上的时间~~~~~~~
/// 网上也找不到资料,最可气的是.Net带的函数都不支持结构数组,只好变相再来一个结构了~~
/// xiefang 2007/09/02
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct PT_DEVLISTARRAY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = AdvantechAPI.MaxEntries)]
public PT_DEVLIST[] Devices;
}
#endregion
#region PT_DeviceGetFeatures
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DeviceGetFeatures
{
public IntPtr Buffer;
public int Size;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct GainListBlob
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)]
public byte[] gainArr;
}
/// <summary>
/// Define hardware board(device) features.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct DEVFEATURES
{
/// <summary>
/// device driver version, array[0..7]
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string szDriverVer;
/// <summary>
/// device driver name, array[0..MAX_DRIVER_NAME_LEN-1]
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = AdvantechAPI.MAX_DRIVER_NAME_LEN)]
public string szDriverName;
/// <summary>
/// board ID, DWORD 4 bytes
/// </summary>
public uint dwBoardID;
/// <summary>
/// Max. number of differential channel
/// </summary>
public ushort usMaxAIDiffChl;
/// <summary>
/// Max. number of single-end channel
/// </summary>
public ushort usMaxAISiglChl;
/// <summary>
/// Max. number of D/A channel
/// </summary>
public ushort usMaxAOChl;
/// <summary>
/// Max. number of digital out channel
/// </summary>
public ushort usMaxDOChl;
/// <summary>
/// Max. number of digital input channel
/// </summary>
public ushort usMaxDIChl;
/// <summary>
/// specifies if programmable or not
/// </summary>
public ushort usDIOPort;
/// <summary>
/// Max. number of Counter/Timer channel
/// </summary>
public ushort usMaxTimerChl;
/// <summary>
/// Max number of alram channel
/// </summary>
public ushort usMaxAlarmChl;
/// <summary>
/// number of bits for A/D converter
/// </summary>
public ushort usNumADBit;
/// <summary>
/// A/D channel width in bytes.
/// </summary>
public ushort usNumADByte;
/// <summary>
/// number of bits for D/A converter.
/// </summary>
public ushort usNumDABit;
/// <summary>
/// D/A channel width in bytes.
/// </summary>
public ushort usNumDAByte;
/// <summary>
/// Max. number of gain code
/// </summary>
public ushort usNumGain;
/// <summary>
/// Gain listing array[0..15]
/// </summary>
public GainListBlob glGainList;
/// <summary>
/// Permutation array[0..3]
/// Bit 0: Software AI
/// Bit 1: DMA AI
/// Bit 2: Interrupt AI
/// Bit 3: Condition AI
/// Bit 4: Software AO
/// Bit 5: DMA AO
/// Bit 6: Interrupt AO
/// Bit 7: Condition AO
/// Bit 8: Software DI
/// Bit 9: DMA DI
/// Bit 10: Interrupt DI
/// Bit 11: Condition DI
/// Bit 12: Software DO
/// Bit 13: DMA DO
/// Bit 14: Interrupt DO
/// Bit 15: Condition DO
/// Bit 16: High Gain
/// Bit 17: Auto Channel Scan
/// Bit 18: Pacer Trigger
/// Bit 19: External Trigger
/// Bit 20: Down Counter
/// Bit 21: Dual DMA
/// Bit 22: Monitoring
/// Bit 23: QCounter
/// </summary>
public uint dwPermutation0;
public uint dwPermutation1;
public uint dwPermutation2;
public uint dwPermutation3;
}
#endregion
/// <summary>
/// 写入设备的数据结构。
/// </summary>
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DioWritePortByte
{
[FieldOffset(0)]
public short Port;
[FieldOffset(2)]
public short Mask;
[FieldOffset(4)]
public short State;
}
/// <summary>
/// 读取IO设备的数据结构。
/// </summary>
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
internal struct PT_DioReadPortByte
{
[FieldOffset(0)]
public short Port;
[FieldOffset(4)]
public IntPtr value;
}
/// <summary>
/// 硬件调用的 API 函数封装类。
/// </summary>
public static class AdvantechAPI
{
/// <summary>
/// 最大设备个数
/// </summary>
public const short MaxEntries = 255;
public const short MaxDevices = 255;
public const short MAX_DRIVER_NAME_LEN = 16;
#region interface
/// <summary>
/// 获取设备列表。
/// </summary>
/// <param name="deviceList">返回的设备列表清单数组</param>
/// <param name="maxEntries">最大的设备数</param>
/// <param name="outEntries">返回的设备数</param>
/// <returns>返回值为 0 则表示执行成功,否则执行失败。</returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceGetList(IntPtr deviceList, Int16 maxEntries, ref short outEntries);
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceGetFeatures(int DriverHandle, ref PT_DeviceGetFeatures lpDeviceGetFeatures);
/// <summary>
/// 获取设备列表个数,我就基本用不到它,姑且留着。
/// </summary>
/// <param name="numOfDevices"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
public static extern int DRV_DeviceGetNumOfList(ref short numOfDevices);
/// <summary>
/// 打开设备。
/// </summary>
/// <param name="deviceNum">设备号</param>
/// <param name="driverHandle">设备句柄</param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceOpen(uint deviceNum, ref int deviceHandle);
/// <summary>
/// 关闭设备。
/// </summary>
/// <param name="deviceHandle"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DeviceClose(ref int deviceHandle);
/// <summary>
/// 向端口写数字信号。
/// </summary>
/// <param name="DriverHandle"></param>
/// <param name="lpDioWritePortByte"></param>
/// <returns></returns>
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DioWritePortByte(int driverHandle, ref PT_DioWritePortByte lpDioWritePortByte);
[DllImport("adsapi32.dll", CharSet = CharSet.Ansi)]
static extern int DRV_DioReadPortByte(int driverHandle, ref PT_DioReadPortByte lpDioReadPortByte);
#endregion
/// <summary>
/// 打开设备
/// </summary>
/// <param name="deviceNum">设备号</param>
/// <param name="deviceHandle">设备句柄</param>
/// <returns>返回错误代码,如果无错误,则返回0。</returns>
public static int OpenDevice(uint deviceNum, ref int deviceHandle)
{
return DRV_DeviceOpen(deviceNum, ref deviceHandle);
}
/// <summary>
/// 关闭设备。
/// </summary>
/// <param name="deviceHandle"></param>
public static void CloseDevice(int deviceHandle)
{
DRV_DeviceClose(ref deviceHandle);
}
/// <summary>
/// 获取主机上安装的设备列表。
/// </summary>
/// <returns>返回错误代码,如果无错误,则返回0。</returns>
public static int GetDeviceList(out PT_DEVLISTARRAY deviceList, ref short outEntries)
{
deviceList = new PT_DEVLISTARRAY();
int _DeviceListLenght = Marshal.SizeOf(deviceList);
IntPtr _DeviceListPoint = Marshal.AllocHGlobal(_DeviceListLenght);
//打开设备的检查过程
int errorCode = AdvantechAPI.DRV_DeviceGetList(_DeviceListPoint, MaxEntries, ref outEntries);
deviceList = (PT_DEVLISTARRAY)Marshal.PtrToStructure(_DeviceListPoint, typeof(PT_DEVLISTARRAY));
Marshal.FreeHGlobal(_DeviceListPoint);
return errorCode;
}
public static int GetFeatures(int deviceHandle, out DEVFEATURES outDevFeatures)
{
int iLength;
int ErrCde = 0;
PT_DeviceGetFeatures ptDevGetFeatures = new PT_DeviceGetFeatures();
outDevFeatures = new DEVFEATURES();
outDevFeatures.szDriverVer = "?";
outDevFeatures.szDriverName = "?";
iLength = Marshal.SizeOf(outDevFeatures);
//and reserve the space
IntPtr DevFeaturesPointer = Marshal.AllocHGlobal(iLength);
//Copy the pointer into the struct
ptDevGetFeatures.Buffer = DevFeaturesPointer;
//and get the features
ErrCde = DRV_DeviceGetFeatures(deviceHandle, ref ptDevGetFeatures);
if (ErrCde == 0)
{
outDevFeatures = (DEVFEATURES)Marshal.PtrToStructure(DevFeaturesPointer, typeof(DEVFEATURES));
}
else
{
//Error
}
Marshal.FreeHGlobal(DevFeaturesPointer);
return ErrCde;
}
/// <summary>
/// 数字信号按端口输出。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="port"></param>
/// <param name="value"></param>
/// <param name="mask"></param>
/// <returns></returns>
public static int Digital_WriteByteToPort(int deviceHandle, short port, short value, short mask)
{
PT_DioWritePortByte data = new PT_DioWritePortByte();
data.Port = port;
data.State = value;
data.Mask = mask;
return DRV_DioWritePortByte(deviceHandle, ref data);
}
public static int Digital_WriteByteToPort(int deviceHandle, short port, short value)
{
return Digital_WriteByteToPort(deviceHandle, port, value, 255);
}
/// <summary>
/// 从指定的端口获取数据。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="port"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int Digital_ReadByteFromPort(int deviceHandle, short port, out short value)
{
int error = 0;
short tempValue = 0;
IntPtr vpoint = Marshal.AllocHGlobal(Marshal.SizeOf(tempValue));
try
{
Marshal.StructureToPtr(tempValue, vpoint, false);
PT_DioReadPortByte data = new PT_DioReadPortByte();
data.Port = port;
data.value = vpoint;
error = DRV_DioReadPortByte(deviceHandle, ref data);
tempValue = (short)Marshal.PtrToStructure(vpoint, typeof(short));
value = tempValue;
}
finally
{
Marshal.FreeHGlobal(vpoint);
}
return error;
}
}
}
PCI_Base:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
namespace Hardware.Advantech
{
using System.Runtime.InteropServices;
using Hardware.Advantech.Interface;
/// <summary>
/// PCI 硬件的基础类。
/// </summary>
[ToolboxItem(false), DefaultProperty("Connected")]
public partial class PCI_Base : Component
{
#region 公共静态变量
/// <summary>
/// 获取主机上能检测到的设备个数,这个设备数量包括输入设备以及输出设备。
/// </summary>
private static short _OutEntries = 0;
private static PT_DEVLISTARRAY _DeviceList;
#endregion
private string _DeviceName = string.Empty;
private int _DeviceIndex = -1;
private int _PortCount = 0;
private uint _DeviceNum = 0;
private bool _Connected = false;
protected int _DeviceHandle = -1;
protected DEVFEATURES _DevFeatures;
public PCI_Base()
{
InitializeComponent();
}
public PCI_Base(IContainer container)
{
container.Add(this);
InitializeComponent();
}
#region 公共属性
#region 静态全局属性
/// <summary>
/// 获取主机上能检测到的设备个数,这个设备数量包括输入设备以及输出设备。
/// </summary>
public static short OutEntries
{
get { return _OutEntries; }
}
/// <summary>
///
/// </summary>
public static PT_DEVLISTARRAY DeviceList
{
get { return _DeviceList; }
}
#endregion
/// <summary>
/// 获取设备名称。
/// </summary>
[Browsable(false)]
public string DeviceName
{
get { return _DeviceName; }
}
/// <summary>
/// 获取设备索引。
/// </summary>
[Browsable(false)]
public int DeviceIndex
{
get { return _DeviceIndex; }
}
/// <summary>
/// 获取设备端口数。
/// </summary>
[Browsable(false)]
public int PortCount
{
get { return _PortCount; }
}
/// <summary>
/// 获取设备数。
/// </summary>
[Browsable(false)]
public uint DeviceNum
{
get { return _DeviceNum; }
}
/// <summary>
/// 获取设备的识别名。
/// </summary>
[Browsable(false)]
public virtual string DeviceSymbol
{
get { return ""; }
}
/// <summary>
/// 获取或设置连接属性。
/// </summary>
[Description("获取或设置连接属性。"), DefaultValue(false)]
public bool Connected
{
get { return _Connected; }
set
{
if (value)
{
//打开设备的检查过程
if (_OutEntries <= 0)
{
if (!RefreshDeviceList()) return;
}
_DeviceIndex = GetDeviceIndex();
//如果找到设备的索引,则继续查找端口号
if (_DeviceIndex != -1)
{
_DeviceName = PCI_Base.DeviceList.Devices[_DeviceIndex].szDeviceName;
int portCount = _DeviceList.Devices[_DeviceIndex].nNumOfSubdevices;
if (portCount > AdvantechAPI.MaxDevices) portCount = AdvantechAPI.MaxDevices;
_DeviceNum = _DeviceList.Devices[_DeviceIndex].dwDeviceNum;
//打开设备
if (!IsError(AdvantechAPI.OpenDevice(_DeviceNum, ref _DeviceHandle)))
{
_PortCount = GetPortCount(_DeviceHandle, out _DevFeatures);
_Connected = value;
}
}
}
else
{
AdvantechAPI.CloseDevice(_DeviceHandle);
_DeviceIndex = -1;
_PortCount = 0;
_DeviceNum = 0;
_DeviceHandle = -1;
_DeviceName = "";
_Connected = value;
}
//触发连接变更事件
if (OnConnectionChanged != null) OnConnectionChanged(this, EventArgs.Empty);
}
}
#endregion
#region 方法
/// <summary>
/// 检查错误代码是否是发生了错误。
/// </summary>
/// <param name="errorCode"></param>
/// <returns>如果是错误,则返回 True,否则返回 False。</returns>
protected bool IsError(int errorCode)
{
if (errorCode != 0)
MessageBox.Show("Error");
return errorCode != 0;
}
/// <summary>
/// 更新设备列表。该方法一般在创建基于 PCI_BASE 的对象时会自动进行调用,以创建
/// 主机上存在的设备列表。除非需要手工刷新,否则,不应直接调用该方法。
/// </summary>
public static bool RefreshDeviceList()
{
Debug.WriteLine("Execute RefreshDeviceList");
//打开设备的检查过程
return AdvantechAPI.GetDeviceList(out _DeviceList, ref _OutEntries) == 0;
}
/// <summary>
/// 获取设备索引号
/// </summary>
/// <returns></returns>
protected int GetDeviceIndex()
{
int iIndex = -1;
for (int i = 0; i < OutEntries; i++)
{
string sDeviceName = PCI_Base.DeviceList.Devices[i].szDeviceName.ToUpper().Trim();
if (sDeviceName.StartsWith(DeviceSymbol.ToUpper()))
{
iIndex = i;
break;
}
}
return iIndex;
}
/// <summary>
/// 获取端口数量,不应直接使用。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="deviceFeatures"></param>
/// <returns></returns>
protected virtual int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
deviceFeatures = new DEVFEATURES();
return 0;
}
private short ReadData(short port)
{
short value = 255;
IsError(AdvantechAPI.Digital_ReadByteFromPort(_DeviceHandle, port, out value));
return value;
}
private void WriteData(short port, short value)
{
WriteData(port, value, 255);
}
private void WriteData(short port, short value, short mask)
{
IsError(AdvantechAPI.Digital_WriteByteToPort(_DeviceHandle, port, value, mask));
}
/// <summary>
/// 清除所有端口数据。
/// </summary>
public void Clear()
{
for (short i = 0; i < PortCount; i++)
this[i] = 0;
}
/// <summary>
/// 获取或设置指定端口数据。
/// </summary>
/// <param name="port">端口号,范围:0..最大端口 - 1。</param>
/// <returns>端口值</returns>
public short this[short port]
{
get
{
return ReadData(port);
}
set
{
WriteData(port, value);
}
}
/// <summary>
/// 获取或设置指定端口指定位的值。
/// </summary>
/// <param name="port">端口号,范围:0..最大端口 - 1。</param>
/// <param name="bit">端口中指定的位,范围:0..7。</param>
/// <returns></returns>
public bool this[short port, int bit]
{
get
{
short a = (short)Math.Pow(2, bit);
int[] dt = new int[1] { (int) this[port] };
BitArray result = new BitArray(dt);
if (result.Length > bit)
{
return result[bit];
}
else return false;
}
set
{
if (value)
{
short a = (short)Math.Pow(2, bit);
this[port] |= a;
}
else
{
short a = (short)(255 - (short)Math.Pow(2, bit));
this[port] &= a;
}
}
}
#endregion
#region 公共事件
/// <summary>
/// 触发连接变更事件
/// </summary>
public event EventHandler OnConnectionChanged;
#endregion
}
}
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
namespace Hardware.Advantech
{
using System.Runtime.InteropServices;
using Hardware.Advantech.Interface;
/// <summary>
/// PCI 硬件的基础类。
/// </summary>
[ToolboxItem(false), DefaultProperty("Connected")]
public partial class PCI_Base : Component
{
#region 公共静态变量
/// <summary>
/// 获取主机上能检测到的设备个数,这个设备数量包括输入设备以及输出设备。
/// </summary>
private static short _OutEntries = 0;
private static PT_DEVLISTARRAY _DeviceList;
#endregion
private string _DeviceName = string.Empty;
private int _DeviceIndex = -1;
private int _PortCount = 0;
private uint _DeviceNum = 0;
private bool _Connected = false;
protected int _DeviceHandle = -1;
protected DEVFEATURES _DevFeatures;
public PCI_Base()
{
InitializeComponent();
}
public PCI_Base(IContainer container)
{
container.Add(this);
InitializeComponent();
}
#region 公共属性
#region 静态全局属性
/// <summary>
/// 获取主机上能检测到的设备个数,这个设备数量包括输入设备以及输出设备。
/// </summary>
public static short OutEntries
{
get { return _OutEntries; }
}
/// <summary>
///
/// </summary>
public static PT_DEVLISTARRAY DeviceList
{
get { return _DeviceList; }
}
#endregion
/// <summary>
/// 获取设备名称。
/// </summary>
[Browsable(false)]
public string DeviceName
{
get { return _DeviceName; }
}
/// <summary>
/// 获取设备索引。
/// </summary>
[Browsable(false)]
public int DeviceIndex
{
get { return _DeviceIndex; }
}
/// <summary>
/// 获取设备端口数。
/// </summary>
[Browsable(false)]
public int PortCount
{
get { return _PortCount; }
}
/// <summary>
/// 获取设备数。
/// </summary>
[Browsable(false)]
public uint DeviceNum
{
get { return _DeviceNum; }
}
/// <summary>
/// 获取设备的识别名。
/// </summary>
[Browsable(false)]
public virtual string DeviceSymbol
{
get { return ""; }
}
/// <summary>
/// 获取或设置连接属性。
/// </summary>
[Description("获取或设置连接属性。"), DefaultValue(false)]
public bool Connected
{
get { return _Connected; }
set
{
if (value)
{
//打开设备的检查过程
if (_OutEntries <= 0)
{
if (!RefreshDeviceList()) return;
}
_DeviceIndex = GetDeviceIndex();
//如果找到设备的索引,则继续查找端口号
if (_DeviceIndex != -1)
{
_DeviceName = PCI_Base.DeviceList.Devices[_DeviceIndex].szDeviceName;
int portCount = _DeviceList.Devices[_DeviceIndex].nNumOfSubdevices;
if (portCount > AdvantechAPI.MaxDevices) portCount = AdvantechAPI.MaxDevices;
_DeviceNum = _DeviceList.Devices[_DeviceIndex].dwDeviceNum;
//打开设备
if (!IsError(AdvantechAPI.OpenDevice(_DeviceNum, ref _DeviceHandle)))
{
_PortCount = GetPortCount(_DeviceHandle, out _DevFeatures);
_Connected = value;
}
}
}
else
{
AdvantechAPI.CloseDevice(_DeviceHandle);
_DeviceIndex = -1;
_PortCount = 0;
_DeviceNum = 0;
_DeviceHandle = -1;
_DeviceName = "";
_Connected = value;
}
//触发连接变更事件
if (OnConnectionChanged != null) OnConnectionChanged(this, EventArgs.Empty);
}
}
#endregion
#region 方法
/// <summary>
/// 检查错误代码是否是发生了错误。
/// </summary>
/// <param name="errorCode"></param>
/// <returns>如果是错误,则返回 True,否则返回 False。</returns>
protected bool IsError(int errorCode)
{
if (errorCode != 0)
MessageBox.Show("Error");
return errorCode != 0;
}
/// <summary>
/// 更新设备列表。该方法一般在创建基于 PCI_BASE 的对象时会自动进行调用,以创建
/// 主机上存在的设备列表。除非需要手工刷新,否则,不应直接调用该方法。
/// </summary>
public static bool RefreshDeviceList()
{
Debug.WriteLine("Execute RefreshDeviceList");
//打开设备的检查过程
return AdvantechAPI.GetDeviceList(out _DeviceList, ref _OutEntries) == 0;
}
/// <summary>
/// 获取设备索引号
/// </summary>
/// <returns></returns>
protected int GetDeviceIndex()
{
int iIndex = -1;
for (int i = 0; i < OutEntries; i++)
{
string sDeviceName = PCI_Base.DeviceList.Devices[i].szDeviceName.ToUpper().Trim();
if (sDeviceName.StartsWith(DeviceSymbol.ToUpper()))
{
iIndex = i;
break;
}
}
return iIndex;
}
/// <summary>
/// 获取端口数量,不应直接使用。
/// </summary>
/// <param name="deviceHandle"></param>
/// <param name="deviceFeatures"></param>
/// <returns></returns>
protected virtual int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
deviceFeatures = new DEVFEATURES();
return 0;
}
private short ReadData(short port)
{
short value = 255;
IsError(AdvantechAPI.Digital_ReadByteFromPort(_DeviceHandle, port, out value));
return value;
}
private void WriteData(short port, short value)
{
WriteData(port, value, 255);
}
private void WriteData(short port, short value, short mask)
{
IsError(AdvantechAPI.Digital_WriteByteToPort(_DeviceHandle, port, value, mask));
}
/// <summary>
/// 清除所有端口数据。
/// </summary>
public void Clear()
{
for (short i = 0; i < PortCount; i++)
this[i] = 0;
}
/// <summary>
/// 获取或设置指定端口数据。
/// </summary>
/// <param name="port">端口号,范围:0..最大端口 - 1。</param>
/// <returns>端口值</returns>
public short this[short port]
{
get
{
return ReadData(port);
}
set
{
WriteData(port, value);
}
}
/// <summary>
/// 获取或设置指定端口指定位的值。
/// </summary>
/// <param name="port">端口号,范围:0..最大端口 - 1。</param>
/// <param name="bit">端口中指定的位,范围:0..7。</param>
/// <returns></returns>
public bool this[short port, int bit]
{
get
{
short a = (short)Math.Pow(2, bit);
int[] dt = new int[1] { (int) this[port] };
BitArray result = new BitArray(dt);
if (result.Length > bit)
{
return result[bit];
}
else return false;
}
set
{
if (value)
{
short a = (short)Math.Pow(2, bit);
this[port] |= a;
}
else
{
short a = (short)(255 - (short)Math.Pow(2, bit));
this[port] &= a;
}
}
}
#endregion
#region 公共事件
/// <summary>
/// 触发连接变更事件
/// </summary>
public event EventHandler OnConnectionChanged;
#endregion
}
}
PCI_1752:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Text;
namespace Hardware.Advantech
{
using Hardware.Advantech.Interface;
/// <summary>
/// 输出卡类。
/// </summary>
[ToolboxItem(true)]
public partial class PCI_1752 : PCI_Base
{
public PCI_1752()
{
InitializeComponent();
}
public PCI_1752(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public override string DeviceSymbol
{
get { return "PCI-1752"; }
}
protected override int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
int portCount = 0;
if (!IsError(AdvantechAPI.GetFeatures(deviceHandle, out deviceFeatures)))
{
portCount = _DevFeatures.usMaxDOChl / 8;
}
return portCount;
}
}
}
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Text;
namespace Hardware.Advantech
{
using Hardware.Advantech.Interface;
/// <summary>
/// 输出卡类。
/// </summary>
[ToolboxItem(true)]
public partial class PCI_1752 : PCI_Base
{
public PCI_1752()
{
InitializeComponent();
}
public PCI_1752(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public override string DeviceSymbol
{
get { return "PCI-1752"; }
}
protected override int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
int portCount = 0;
if (!IsError(AdvantechAPI.GetFeatures(deviceHandle, out deviceFeatures)))
{
portCount = _DevFeatures.usMaxDOChl / 8;
}
return portCount;
}
}
}
PCI_1754:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
namespace Hardware.Advantech
{
using Hardware.Advantech.Interface;
/// <summary>
/// 输入卡类。
/// </summary>
[ToolboxItem(true), DefaultEvent("DataInput")]
public partial class PCI_1754 : PCI_Base
{
int _interval = 100;
public PCI_1754()
{
InitializeComponent();
}
public PCI_1754(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public override string DeviceSymbol
{
get { return "PCI-1754"; }
}
protected override int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
int portCount = 0;
if (!IsError(AdvantechAPI.GetFeatures(deviceHandle, out deviceFeatures)))
{
portCount = _DevFeatures.usMaxDIChl / 8;
}
return portCount;
}
#region Thread
/// <summary>
/// 获取或设置读信号线程的间隔时间,单位为毫秒。
/// </summary>
[Browsable(true), Description("获取或设置读信号线程的间隔时间,单位为毫秒。"), DefaultValue(100)]
public int Interval
{
get
{
return _interval;
}
set
{
_interval = value;
}
}
/// <summary>
/// 启动读线程。
/// </summary>
public void StartReadWork()
{
backgroundReadWorker.RunWorkerAsync();
}
/// <summary>
/// 停止读线程。
/// </summary>
public void StopReadWork()
{
backgroundReadWorker.CancelAsync();
}
private void backgroundReadWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
do
{
for (short i = 0; i < PortCount; i++)
{
for (short j = 0; j < 8; j++)
{
if (this[i, j] == true)
{
if (DataInput != null)
{
DataInput(this, i, j);
}
}
}
}
System.Threading.Thread.Sleep(_interval);
}
while (!worker.CancellationPending);
e.Cancel = true;
}
private void backgroundReadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
//MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
//触发停止事件。
}
else
{
// Finally, handle the case where the operation
// succeeded.
//正常结束。
}
}
public event RaiseDataInput DataInput;
#endregion
}
public delegate void RaiseDataInput(object sender, short port, short bit);
}
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
namespace Hardware.Advantech
{
using Hardware.Advantech.Interface;
/// <summary>
/// 输入卡类。
/// </summary>
[ToolboxItem(true), DefaultEvent("DataInput")]
public partial class PCI_1754 : PCI_Base
{
int _interval = 100;
public PCI_1754()
{
InitializeComponent();
}
public PCI_1754(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public override string DeviceSymbol
{
get { return "PCI-1754"; }
}
protected override int GetPortCount(int deviceHandle, out DEVFEATURES deviceFeatures)
{
int portCount = 0;
if (!IsError(AdvantechAPI.GetFeatures(deviceHandle, out deviceFeatures)))
{
portCount = _DevFeatures.usMaxDIChl / 8;
}
return portCount;
}
#region Thread
/// <summary>
/// 获取或设置读信号线程的间隔时间,单位为毫秒。
/// </summary>
[Browsable(true), Description("获取或设置读信号线程的间隔时间,单位为毫秒。"), DefaultValue(100)]
public int Interval
{
get
{
return _interval;
}
set
{
_interval = value;
}
}
/// <summary>
/// 启动读线程。
/// </summary>
public void StartReadWork()
{
backgroundReadWorker.RunWorkerAsync();
}
/// <summary>
/// 停止读线程。
/// </summary>
public void StopReadWork()
{
backgroundReadWorker.CancelAsync();
}
private void backgroundReadWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
do
{
for (short i = 0; i < PortCount; i++)
{
for (short j = 0; j < 8; j++)
{
if (this[i, j] == true)
{
if (DataInput != null)
{
DataInput(this, i, j);
}
}
}
}
System.Threading.Thread.Sleep(_interval);
}
while (!worker.CancellationPending);
e.Cancel = true;
}
private void backgroundReadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
//MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
//触发停止事件。
}
else
{
// Finally, handle the case where the operation
// succeeded.
//正常结束。
}
}
public event RaiseDataInput DataInput;
#endregion
}
public delegate void RaiseDataInput(object sender, short port, short bit);
}