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

CH341DLL.DLL + I2C not works properly with VB.NET

我写 VB.NET class 来实现 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 次,结果是:

可以看出,CH341 设备在该行中写入了不可预测的值。这不是 DLL 错误,因为其他应用程序使用此方法并且结果是正确的。请注意,其他方法,例如CH341ReadI2C()CH341WriteI2C(),reads/writes 每次只有一个字节,在我的代码中是正确的。

出现这种行为的可能原因是什么?可能是我编组的写缓冲区不正确?正确的方法是如何做到这一点?

如果您使用的是 this,则原始声明为:

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

由于缓冲区参数是 PVOID,您应该能够直接将它们编组为字节数组:

<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 时非常有用,因为它通常可以让您按原样传递数组。