0

我正在使用具有适用于 Windows 的本机软件的 FTDI 设备,但没有适用于 Linux 的软件。我正在尝试使用pylibftdi. 我想翻译C# code设备制造商提供的并且据称可以工作(不清楚是否属实)但没有成功。到目前为止,我已经完成了以下工作:

  1. 根据这些说明安装了 Linux D2XX 驱动程序。安装成功。

  2. 按照此处此处的说明使 FTDI 设备能够连接到 Linux 系统。

  3. 将 FTDI 设备插入 Linux 系统 USB 端口后:

$ lsusb
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 002: ID 04f2:0833 Chicony Electronics Co., Ltd KU-0833 Keyboard
**Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC**
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

粗体设备 ( Bus 001 Device 006: ID 0403:6001) 是我想从中读取的设备。

  1. 然后安装pylibftdi并验证设备是否可以通过pylibftdiAPI 读取:
$ python3
Python 3.9.5 (default, Jun  4 2021, 12:28:51) 
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, pylibftdi as ftdi
>>> print(ftdi.Driver().list_devices())
[('FTDI', 'Cognionics Quick-20 20CH 1706Q20N', 'AI2SUN90')]
  1. 很明显,设备已连接并被识别。但是,当我尝试从设备中读取数据时,我收到了空数组:
>>> d = ftdi.Device()
>>> vars(d)
{'_opened': True, 'driver': <pylibftdi.driver.Driver object at 0x7fd819320910>, 'fdll': <CDLL 'libftdi.so.1', handle 557bc3ca6560 at 0x7fd8190aee80>, 'device_id': None, 'mode': 'b', 'encoding': 'latin1', 'encoder': <encodings.latin_1.IncrementalEncoder object at 0x7fd819320a60>, 'decoder': <encodings.latin_1.IncrementalDecoder object at 0x7fd8190aefd0>, '_baudrate': 9600, 'interface_select': None, 'device_index': 0, 'list_index': None, 'ctx': <ctypes.c_char_Array_1024 object at 0x7fd819342c40>}
>>> d.read(100)
b''
>>> d.read(100)
b''
>>> d.read(100)
b''
  1. C# 代码(由制造商提供)据称可以工作,但我无法对其进行测试。似乎最简单的方法是将其转换为python但即使这样也具有挑战性,因为我不知道如何复制ftdi正在使用的常量和函数调用。提供的C#代码是:
UInt32 ftDevCount = 0;
ftStatus = ftDev.GetNumberOfDevices(ref ftDevCount);

ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[ftDevCount];
ftStatus = ftDev.GetDeviceList(ftdiDeviceList);
String[] deviceNames = new String[ftDevCount];

for (int c = 0; c < ftDevCount; c++)
{
deviceNames[c] = ftdiDeviceList[c].Description.ToString();
}

Connecting to a device and configuring the serial port settings

if (ftDev.OpenBySerialNumber(ftdiDeviceList[devID].SerialNumber) == FTDI.FT_STATUS.FT_OK)
{    ftDev.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
    ftDev.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);
    ftDev.SetLatency(2);
    ftDev.SetBaudRate((uint)3000000);

    connectedName = ftdiDeviceList[devID].Description.ToString();

    return true;
}
else
{
    return false; //failed to open!

}

public byte ReadByte()
{
    UInt32 bytesRead = 0;
    byte[] t_data = new byte[1];
    ftDev.Read(t_data, 1, ref bytesRead);
    return t_data[0];
}

public void WriteByte(byte dat)
{
    UInt32 bytesWritten = 0;
    byte[] data = new byte[1];
    data[0] = dat;
    ftDev.Write(data, 1, ref bytesWritten);
}

//wait for sync byte 0xFF
while (byteInterface.ReadByte() != 255) {};

//read packet counter
int packetCount = byteInterface.ReadByte();

//read the 20 EEG channels
int NumEEG = 20;
for (int c = 0; c < NumEEG; c++)
{
    msb =  byteInterface.ReadByte();
    lsb2 = byteInterface.ReadByte();
    lsb1 = byteInterface.ReadByte();

    int tempEEG = (msb << 24) | (lsb2 << 17) | (lsb1 << 10);
}

int NumACC = 3;
//read the 3 ACC channels
for (int c = 0; c < NumACC; c++)
{
    msb =  byteInterface.ReadByte();
    lsb2 = byteInterface.ReadByte();
    lsb1 = byteInterface.ReadByte();

    int tempACC = (msb << 24) | (lsb2 << 17) | (lsb1 << 10);
}


//read packet tail
int impStatus = byteInterface.ReadByte();

//read battery voltage
int batteryByte = byteInterface.ReadByte();

//read trigger
int trigger = (byteInterface.ReadByte()<<8) + byteInterface.ReadByte();
  1. 根据pylibftdigithub repo 中的文档,我可以找到一些包装函数调用以及一些常量,但我不知道如何只打开设置片段,例如:
ftDev.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
ftDev.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);
ftDev.SetLatency(2);
ftDev.SetBaudRate((uint)3000000);

进入某事python。我想我可以使用 重置波特率d.baudrate = 3000000,我可以使用更改延迟计时器,d.ftdi_fn.ftdi_set_latency_timer(2)但我不知道如何设置数据特征,常量的含义(FTDI.FT_DATA_BITS.FT_BITS_8等),以及如何设置与C#代码相同的流量控制.

  1. 其他 SO 帖子也参考了此处找到的 D2XX 程序员指南,但没有看到将其应用于此问题的方法

任何建议,将不胜感激。

4

1 回答 1

0

作为对评论的回应和后续回答:

从个人经验来看,我无法证实 D2XX 比 VCP 更可靠的说法,第二个只是部分正确:例如,在大多数情况下 IIRC 可以使用 VID:PID 组合。

我强烈建议坚持使用更简单的 VCP + pyserial 解决方案。但是,如果您真的想要(或需要)使用 pylibftdi,您可以查看https://github.com/codedstructure/pylibftdi/blob/4662ebe069eefd5a89709d4165e3be808cad636c/docs/advanced_usage.rst - 它描述了如何直接访问未公开的功能. 命名稍有不同,例如 ftdi_setflowctrl 而不是 SetFlowControl,但您会明白的。只需检查https://www.intra2net.com/en/developer/libftdi/documentation/ftdi_8c.html

于 2022-01-05T19:58:27.140 回答