我编写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次,结果是:

可以看到,物理上的CH341设备会在行中写入不可预测的值。这不是DLL错误,因为其他应用程序使用此方法,并且结果是正确的。注意,其他方法,例如CH341ReadI2C()和CH341WriteI2C(),每次只读/写一个字节,在我的代码中是正确的。
这种行为的可能原因是什么?可能是,我编组的写缓冲区不正确?怎么做才是正确的呢?
发布于 2018-09-09 15:34:45
如果您使用的是这,则原始声明是:
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/调用时非常有用,因为它通常允许您按原样传递数组。
https://stackoverflow.com/questions/52244846
复制相似问题