最近要用到 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);
}