CH341DLL.DLL + I2C与VB.NET无法正常工作

问题描述 投票:0回答:1

我编写了VB.NET类来实现CH341DLL.DLL功能。方法CH341StreamI2C()用于流写入和读入设备。这样我从DLL导入了方法CH341StreamI2C():

<DllImport("CH341DLL.DLL", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function CH341StreamI2C(ByVal iIndex As Integer, ByVal iWriteLength As Integer, ByRef iWriteBuffer As IntPtr, ByVal iReadLength As Integer, ByRef oReadBuffer As IntPtr) As Boolean
End Function

为了检查这种方法是如何工作的,我使用I2C湿度和温度传感器HTU21D。它的IIC地址是40h,温度变化的寄存器是E3h。所以我调用方法CH341StreamI2C(),如下所示:

Dim writeBuffer as Byte() = {&H40, &hE3} 'Address+Command
Dim s As String = Encoding.Unicode.GetString(writeBuffer)
Dim writeBufPtr As IntPtr = Marshal.StringToHGlobalAuto(s) 'Get pointer for write buffer
Dim wLen As Integer = writeBuffer.Length
Dim readBufPtr As IntPtr = IntPtr.Zero 'Init read pointer
Dim rLen as Integer = 3 'Sensor must return 3 bytes
Dim res As Boolean = CH341StreamI2C(0, wLen, writeBufPtr, rLen, readBufPtr)

我使用逻辑分析仪来查看SDA和SCL线路上的内容。结果是不可预测的。例如,如果调用前面的代码4次,那就是结果:

Lines SDA and SCL while CH341StreamI2C() calling

可以看出,物理CH341设备在线路中写入了不可预测的值。这不是DLL错误,因为其他应用程序使用此方法,结果是正确的。需要注意的是,其他方法,例如CH341ReadI2C()和CH341WriteI2C(),每次只读取/写入一个字节,在我的代码中行为正确。

这种行为的可能原因是什么?可能是,我编组的缓冲区不正确吗?如何正确地做到这一点?

vb.net marshalling dllimport i2c
1个回答
2
投票

如果this是您正在使用的,原始声明是:

BOOL WINAPI CH341StreamI2C(ULONG iIndex, ULONG iWriteLength, PVOID iWriteBuffer, ULONG iReadLength, PVOID oReadBuffer);

由于缓冲区参数是PVOIDs,您应该能够直接将它们封送到字节数组:

<DllImport("CH341DLL.DLL", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function CH341StreamI2C(ByVal iIndex As Integer, ByVal iWriteLength As Integer, ByVal iWriteBuffer As Byte(), ByVal iReadLength As Integer, ByVal oReadBuffer As Byte()) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

数组是引用类型(类),这意味着你总是通过它们的内存指针来引用它们。因此,当您将它们传递给函数(P / Invoked或不传递)时,您实际上是传递数组的指针,而不是数组本身。这在P / Invoking时非常有用,因为它通常允许您按原样传递数组。

© www.soinside.com 2019 - 2024. All rights reserved.