首页 > 解决方案 > 无法使用 i2c 从 FTDI FT201X 中获取数据

问题描述

我有一个项目使用 FTDI FT201X 作为 USB 到 i2c 从机,而 i2c 主机是 AVR 微控制器。我在 Windows 10 机器上使用 WPF Core 3.1 C#。基本上,使用 FTDI 芯片的所有东西都可以正常工作,只是无论我如何尝试,我都无法成功地将数据从 PC 发送到 FTDI 芯片。D2XX 写入函数说它成功并且没有返回错误,但是当我尝试读取时缓冲区中永远没有任何数据。

从那以后,我编写了一个小型测试程序以试图隔离问题,但问题仍然存在。基本上,当单击按钮时,我们通过序列号打开设备,我们向设备的缓冲区写入命令,与 AVR 握手以使其知道读取,然后等待 AVR 将握手引脚驱动为低电平,这意味着它已收到数据。

public class USBLibrary
{
    byte targetDeviceCount = 0;
    FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OK;
    public FTDI connectedUSBDevice;

    // Called from button click event
    public void ConnectUSB()
    {
        bool isOK = true; 
        byte numOfBytes = 1;
        uint bytesWritten = 0;
        bool usbInPinIsHigh = false;        // Tracks USB In Pin
        byte lowMask = 0b00010000;          // CBUS 0 is output (4-7), all pins low (0-3) (Default Setting)
        byte highMask = 0b00010001;         // CBUS 0 is output (4-7), CBUS 3 is high
        byte inPinMask = 0b00001000;        // AND with pin states to get input pin value (Bus3)
        byte pinStates = 0;                 // Used to get the current pin values
        double timeout = 0;

        // Create new instance of the FTDI device class
        connectedUSBDevice = new FTDI();

        // Determine the number of FTDI devices connected to the machine
        ftStatus = connectedUSBDevice.OpenBySerialNumber("P00001");

        /*** Write to Device ***/
        byte[] firmwareCmd = new byte[numOfBytes];

        firmwareCmd[0] = 128;       // 128 is Get Firmware Command
        // firmwareCmd[1] = 61;        // Just Testing

        // Write Firmware Command to Tx buffer
        ftStatus = connectedUSBDevice.Write(firmwareCmd, numOfBytes, ref bytesWritten);
        Trace.WriteLine(bytesWritten);

        // Handshake with Device
        isOK = DeviceHandshake(lowMask, highMask, inPinMask);

        // Check if handshake failed
        if (isOK == false)
        {
            return;
        }

        Task.Delay(10);

        // Wait until message is sent
        while ((usbInPinIsHigh == false) && (timeout <= 1000))
        {
            Task.Delay(1);

            // Check for USB In pin to go high. Signals FW transfer is complete and to retrieve.
            ftStatus = connectedUSBDevice.GetPinStates(ref pinStates);

            // Is input pin high or low?
            if ((pinStates & inPinMask) == inPinMask)       // In pin high
            {
                usbInPinIsHigh = true;                      // Means uC finished sending data
            }

            timeout++;
        }

        // TEST: displays timeout amount for testing
        Trace.WriteLine("Timeout=" + timeout);

        ftStatus = connectedUSBDevice.Close();
    }
}

注意:对于这段代码,为了清楚起见,我删除了很多错误检查代码。此外,握手代码没有显示,因为它不应该是相关的:提高输出引脚,听 AVR 提高输出引脚,降低输出引脚,听 AVR 降低输出引脚。

在 AVR 方面,我们只需轮询 FT201X 的引脚变高,然后与芯片握手。然后我们简单地阅读。读取函数始终返回 0。

我怀疑问题出在 i2c 上,因为有 3 个 IO 扩展器芯片控制 LED 和按钮,我们可以读取和写入这些芯片。此外,FT 芯片有一个名为 Get USB State 的功能,您可以在其中通过发送命令并通过 i2c 读取结果来查看设备的状态。当我这样做时,我总是回到正确的 0x03“已配置”状态。所以我们可以通过i2c从芯片中读取。

还有一个函数将返回缓冲区中等待读取的字节数......当我这样做时,它总是说 0 字节。

为了更好地衡量,我用新的芯片更换了芯片,以防它坏了,我们又得到了相同的结果。

除了使用 FT_Prog 之外,我在设置芯片方面还有什么遗漏吗,比如初始化程序或设置寄存器之类的?或者我是否需要以某种方式将我写入的字节推到队列的前面或其他东西才能被读取?有人以前见过这样的事情吗?

鉴于我没有影响结果,我要么错过了过程中的关键部分,要么他们的驱动程序/芯片版本有问题。已经 3 周了,我没有想法,而且我的头发因撕掉大块而变得斑驳。请救救我的头发。

标签: c#usbi2cftdi

解决方案


检查延迟计时器设置。本文档https://www.ftdichip.com/Support/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf对此进行了描述。在第 3.3 节中,您将找到描述应用程序无法使用任何数据的场景的部分。

“当主机控制器等待上述情况之一发生时,我们的驱动程序没有收到任何数据,因此用户的应用程序也没有收到任何数据。数据,如果有的话,只有在上述条件之一发生后才最终传输。”</p>

如果您遇到此问题,您可以使用延迟计时器来解决它。尝试将其设置为 1ms,它的最低值。如果您的数据具有分隔符,请考虑将其设置为事件字符,您可能会获得更好的结果。


推荐阅读