简介:我有一个.dll,它有一些我试图在C#应用程序中使用的功能。其中一个功能不能正常工作并返回一个"无效的参数"状态。
我猜这是一个编组问题。
这是.dll标题:
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long long uint64;
typedef signed char int8;
typedef signed short int16;
typedef signed long long int64;
#ifndef _MSC_VER
typedef unsigned char bool;
#endif
#ifdef __x86_64__
typedef unsigned int uint32;
typedef signed int int32;
#else
typedef unsigned long uint32;
typedef signed long int32;
#endif
typedef enum I2C_ClockRate_t{
I2C_CLOCK_STANDARD_MODE = 100000, /* 100kb/sec */
I2C_CLOCK_FAST_MODE = 400000, /* 400kb/sec */
I2C_CLOCK_FAST_MODE_PLUS = 1000000, /* 1000kb/sec */
I2C_CLOCK_HIGH_SPEED_MODE = 3400000 /* 3.4Mb/sec */
}I2C_CLOCKRATE;
/* Channel configuration information */
typedef struct ChannelConfig_t
{
I2C_CLOCKRATE ClockRate;
uint8 LatencyTimer;
uint32 Options;
}ChannelConfig;
/******************************************************************************/
/******************************************************************************/
/* Function declarations */
/******************************************************************************/
FTDI_API FT_STATUS I2C_GetNumChannels(uint32 *numChannels);
FTDI_API FT_STATUS I2C_GetChannelInfo(uint32 index,
FT_DEVICE_LIST_INFO_NODE *chanInfo);
FTDI_API FT_STATUS I2C_OpenChannel(uint32 index, FT_HANDLE *handle);
FTDI_API FT_STATUS I2C_InitChannel(FT_HANDLE handle, ChannelConfig *config);
FTDI_API FT_STATUS I2C_CloseChannel(FT_HANDLE handle);
FTDI_API FT_STATUS I2C_DeviceRead(FT_HANDLE handle, uint32 deviceAddress,
uint32 sizeToTransfer, uint8 *buffer, uint32 *sizeTransfered, uint32 options);
FTDI_API FT_STATUS I2C_DeviceWrite(FT_HANDLE handle, uint32 deviceAddress,
uint32 sizeToTransfer, uint8 *buffer, uint32 *sizeTransfered, uint32 options);
FTDI_API void Init_libMPSSE(void);
FTDI_API void Cleanup_libMPSSE(void);
FTDI_API FT_STATUS FT_WriteGPIO(FT_HANDLE handle, uint8 dir, uint8 value);
FTDI_API FT_STATUS FT_ReadGPIO(FT_HANDLE handle,uint8 *value);
所以我已经制作了一个C#包装器来使用这些功能:
#region Declaration of general drivers methods
/// <summary>
/// This function gets the number of I2C channels that are connected to the host system. The number of ports available in each of these chips is different.
/// </summary>
/// <param name="numChannels">The number of channels connected to the host</param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_GetNumChannels(
ref uint numChannels
);
/// <summary>
/// This function takes a channel index (valid values are from 0 to the value returned by I2C_GetNumChannels – 1 ) and provides information about the channel in the form of a populated FT_DEVICE_LIST_INFO_NODE structure
/// </summary>
/// <param name="index">Index of the channel </param>
/// <param name="chanInfo">Pointer to FT_DEVICE_LIST_INFO_NODE structure</param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_GetChannelInfo(
uint index,
ref FTDI.FT_DEVICE_INFO_NODE chanInfo
);
/// <summary>
/// This function opens the indexed channel and provides a handle to it. Valid values for the index of channel can be from 0 to the value obtained using I2C_GetNumChannels – 1).
/// </summary>
/// <param name="index">Index of the channel</param>
/// <param name="handle">Pointer to the handle of type FT_HANDLE</param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_OpenChannel(
uint index,
ref ulong handle
);
/// <summary>
/// This function initializes the channel and the communication parameters associated with it.
/// </summary>
/// <param name="handle">Handle of the channel </param>
/// <param name="config">Pointer to ChannelConfig structure. Members of ChannelConfig structure contains the values for I2C master clock, latency timer and Options</param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_InitChannel(
ulong handle,
[MarshalAs(UnmanagedType.Struct)] ref C_Types.ChannelConfig config
);
/// <summary>
/// Closes a channel and frees all resources that were used by it
/// </summary>
/// <param name="handle">Handle of the channel </param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_CloseChannel(
ulong handle
);
/// Options summary
/// This parameter specifies data transfer options. The bit positions defined for each of these options are:
/// BIT0: if set then a start condition is generated in the I2C bus before the transfer begins. A bit mask is defined for this options in file ftdi_i2c.h as I2C_TRANSFER_OPTIONS_START_BIT
/// BIT1: if set then a stop condition is generated in the I2C bus after the transfer ends. A bit mask is defined for this options in file ftdi_i2c.h as I2C_TRANSFER_OPTIONS_STOP_BIT
/// BIT2: reserved (only used in I2C_DeviceWrite)
/// BIT3: some I2C slaves require the I2C master to generate a NAK for the last data byte read. Setting this bit enables working with such I2C slaves. The bit mask defined for this bit is I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE
/// BIT4: setting this bit will invoke a multi byte I2C transfer without having delays between the START, ADDRESS, DATA and STOP phases. Size of the transfer in parameters sizeToTransfer and sizeTransfer red are in bytes. The bit mask defined for this bit is I2C_TRANSFER_OPTIONS_FAST_TRANSFER_BYTES*
/// BIT5: setting this bit would invoke a multi bit transfer without having delays between the START, ADDRESS, DATA and STOP phases. Size of the transfer in parameters sizeToTransfer and sizeTransfer red are in bytes. The bit mask defined for this bit is I2C_TRANSFER_OPTIONS_FAST_TRANSFER_BITS*
/// BIT6: the deviceAddress parameter is ignored if this bit is set. This feature may be useful in generating a special I2C bus conditions that do not require any address to be passed. Setting this bit is effective only when either 2C_TRANSFER_OPTIONS_FAST_TRANSFER_BYTES or I2C_TRANSFER_OPTIONS_FAST_TRANSFER_BITS is set. The bit mask defined for this bit is I2C_TRANSFER_OPTIONS_NO_ADDRESS*
/// BIT7–BIT31:reserved
/// For more information see the AN_177_User_Guide_For_LibMPSSE-I2C.pdf
/// <summary>
/// This function reads the specified number of bytes from an addressed I2C slave
/// </summary>
/// <param name="handle">Handle of the channel </param>
/// <param name="deviceAddress">Address of the I2C slave. This is a 7bit value and it should not contain the data direction bit, i.e. the decimal value passed should be always less than 128</param>
/// <param name="sizeToTransfer">Number of bytes to be read </param>
/// <param name="buffer">Pointer to the buffer where data is to be read</param>
/// <param name="sizeTransfered">Pointer to variable containing the number of bytes read</param>
/// <param name="options">cf Options</param>
/// <returns>Returns status code of type FT_STATUS</returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_DeviceRead(
ulong handle,
uint deviceAddress,
uint sizeToTransfer,
ref byte buffer,
ref uint sizeTransfered,
uint options
);
/// <summary>
/// This function writes the specified number of bytes to an addressed I2C slave.
/// </summary>
/// <param name="handle">Handle of the channel</param>
/// <param name="deviceAddress">Address of the I2C slave. This is a 7bit value and it should not contain the data direction bit, i.e. the decimal value passed should be always less than 128</param>
/// <param name="sizeToTransfer">Number of bytes to be written</param>
/// <param name="buffer">Pointer to the buffer from where data is to be written</param>
/// <param name="sizeTransfered">Pointer to variable containing the number of bytes written</param>
/// <param name="options">cf Options</param>
/// <returns></returns>
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_DeviceWrite(
ulong handle,
uint deviceAddress,
uint sizeToTransfer,
ref byte[] buffer,
ref uint sizeTransfered,
uint options
);
#endregion
我已设法使用I2C_GetNumChannels,I2C_OpenChannel和I2C_CloseChannel函数,但我被困在I2C_InitChannel上。
提醒:
.dll:
FTDI_API FT_STATUS I2C_InitChannel(FT_HANDLE handle, ChannelConfig *config);
包装器:
[DllImport("libMPSSE.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static FTDI.FT_STATUS I2C_InitChannel(
ulong handle,
[MarshalAs(UnmanagedType.Struct)] ref C_Types.ChannelConfig config
);
这是C#结构实现:
/// <summary>
/// I2C Clockrate enum for PC I2C Connection
/// </summary>
public enum I2C_ClockRate
{
I2C_CLOCK_STANDARD_MODE = 100000, /* 100kb/sec */
I2C_CLOCK_FAST_MODE = 400000, /* 400kb/sec */
I2C_CLOCK_FAST_MODE_PLUS = 1000000, /* 1000kb/sec */
I2C_CLOCK_HIGH_SPEED_MODE = 3400000 /* 3.4Mb/sec */
};
/// <summary>
/// Channel configuration information for PC I2C Connection
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct ChannelConfig
{
public I2C_ClockRate ClockRate;
public byte LatencyTimer;
public uint Options;
public ChannelConfig(I2C_ClockRate pClockRate, byte pLatencyTimer, uint pOptions)
{
ClockRate = pClockRate;
LatencyTimer = pLatencyTimer;
Options = pOptions;
}
public ChannelConfig(I2C_ClockRate pClockRate, byte pLatencyTimer)
{
ClockRate = pClockRate;
LatencyTimer = pLatencyTimer;
Options = 0x00000000;
}
}
问题是dll函数返回_ftStatus说:&#34;参数无效&#34;。
我猜这是因为我没有正确编组我的功能,但我无法确定我的错误在哪里。