FT4232 USB-SPI python调试笔记

目录

DUT

硬件连接

 驱动

 调试程序

python库ftd2xx v1.1.2安装导入

需要特别注意的是:

调试结果

MSB/BIT/BYTES/CLK EDGE等设置命令如下表 

 附:参考资料


 

DUT

175块钱在淘宝上买的FT4232H Mini Module

硬件连接

选择USB自供电模式,无需外部电源

 驱动

经多台电脑验证,win10系统可以自动识别出FT4232H,自动安装驱动,无需手动安装。

 调试程序

python库ftd2xx v1.1.2安装导入

import ftd2xx as ftd
import sys, time
import ftd2xx as ftd

class FT4232SPI():
    def __init__(self, index):
        self.d = ftd.open(index) # 0(BDBUS)/1(CDBUS)/2(DDBUS)/3(ADBUS)

    def ftd_info(self):
        # print(ftd.getDeviceInfoDetail())
        # print("listDevices:", ftd.listDevices())
        # print("d:", self.d)
        print("getDeviceInfo:", self.d.getDeviceInfo()) #Get device information for an open device.
        # print("getDeviceInfoList:", self.d.getDeviceInfoList()) #'FTD2XX' object has no attribute 'getDeviceInfoList'
        print("getComPortNumber:", self.d.getComPortNumber()) #Retrieves the COM port associated with a device.
        print("getBitMode:", self.d.getBitMode()) #Gets the instantaneous value of the data bus.
        print("getStatus:", self.d.getStatus()) #Gets the device status including number of characters in the receive queue, number of characters in the
        #transmit queue, and the current event status.
        # print("getLatencyTimer:", self.d.getLatencyTimer()) #Get the current value of the latency timer.
        # print("getDriverVersion:", self.d.getDriverVersion()) #This function returns the D2XX driver version number.
        # print("GetLibraryVersion:", self.d.GetLibraryVersion()) #'FTD2XX' object has no attribute 'GetLibraryVersion'
        # print("getLibraryVersion:", ftd.getLibraryVersion())
        # print("getEventStatus:", self.d.getEventStatus())
        # print("getModemStatus:", self.d.getModemStatus()) #Gets the modem status and line status from the device.
        print("getQueueStatus:",self.d.getQueueStatus()) #Gets the number of bytes in the receive queue.

    def ftd_spi_init(self):
        self.d.resetDevice()  # Reset USB device
        self.d.setUSBParameters(65535, 65535)  # Set USB request transfer sizes to 64K
        self.d.setChars(False, 0, False, 0)  # Disable event and error characters
        self.d.setTimeouts(5000, 5000)  # Sets the read and write timeouts in milliseconds
        self.d.setLatencyTimer(1)  # Set the latency timer to 1mS (default is 16mS)
        self.d.setFlowControl(0x0100, 0, 0)
        self.d.setBitMode(0x0, 0x00)  # Reset controller
        self.d.setBitMode(0x0, 0x02)  # Enable MPSSE mode

    def ftd_spi_clkcfg(self, spiClkMHz):
        sentbuffer = (0x8a, 0x97, 0x8d)  # 0x8a:Disables the clk divide by 5 to allow for a 60MHz master clock.
        self.d.write(bytes(sentbuffer))
        div = int((60 / (spiClkMHz * 2)) - 1)  # Set SPI clock
        sentbuffer = (0x86, div % 256, div // 256)  # 0x86:Command to set clock divisor;div%256:L of clock divisor;div//256:H of colck divisor
        self.d.write(bytes(sentbuffer))

    def ftd_spi_w(self, chipID, spiEnbNum, addrHex, valueHex):
        '''
        spiEnbNum = 3/4/5/6/7使能DBUS3/4/5/6/7,spi_enb低电平有效
        '''
        opc_spi_w = 0x10
        if chipID == 'xxx':
            addrWH = 0x7f & addrHex >> 8  # write:最高位是'0'
            addrWL = 0xff & addrHex
            sentbuffer = (0x80, 0xff ^ 0x01 << spiEnbNum, 0xfb, opc_spi_w, 0x02, 0x00, addrWH, addrWL, valueHex, 0x80, 0xff, 0xfb)
            self.d.write(bytes(sentbuffer))
            
    def ftd_spi_r(self, chipID, spiEnbNum, addrHex):
        '''
        spiEnbNum = 3/4/5/6/7使能DBUS3/4/5/6/7,spi_enb低电平有效
        '''
        opc_spi_w = 0x10
        opc_spi_r = 0x20
        if chipID == 'xxx':
            addrRH = 0x80 | addrHex >> 8  # read:最高位是'1'
            addrRL = 0xff & addrHex
            sentbuffer = (0x80, 0xff ^ 0x01 << spiEnbNum, 0xfb, opc_spi_w, 0x01, 0x00, addrRH, addrRL, opc_spi_r, 0x00, 0x00, 0x80, 0xff, 0xfb)
            self.d.write(bytes(sentbuffer))
            print(self.d.getQueueStatus())
            buffRead = self.d.read(7, True)
            return buffRead

    def ftd_bitbang_init(self, mask, mode):
        '''
        mask:
        This sets up which bits are inputs and outputs. A bit value of
        0 sets the corresponding pin to an input, a bit value of 1 sets the corresponding pin to an output.
        In the case of CBUS Bit Bang, the upper nibble of this value controls which pins are inputs and outputs,
        while the lower nibble controls which of the outputs are high and low.
        mode = 0x1:Asynchronous Bit Bang
        mode = 0x4:Synchronous Bit Bang
        '''
        self.d.setBitMode(mask, mode)

    def ftd_bitbang_c_a(self, onNum):
        '''
        Asynchronous Bit-Bang mode is the same as BM-style Bit-Bang mode. On any channel configured in
        asynchronous bit-bang mode, data written to the device in the normal manner will be self-clocked onto the
        parallel I/O data pins (those which have been configured as outputs). Each I/O pin can be independently
        set as an input or an output. The rate that the data is clocked out at is controlled by the baud rate generator.
        For the data to change there has to be new data written, and the baud rate clock has to tick. If no new
        data is written to the channel, the pins will hold the last value written.
        '''
        pass

    def ftd_bitbang_c_s(self, onoffNums):
        '''
        The synchronous Bit-Bang mode will only update the output parallel I/O port pins whenever data is sent
        from the USB interface to the parallel interface. When this is done, data is read from the USB Rx FIFO
        buffer and written out on the pins. Data can only be received from the parallel pins (to the USB Tx FIFO
        interface) when the parallel interface has been written to.
        With Synchronous Bit-Bang mode, data will only be sent out by the FT4232H if there is space in the
        FT4232H USB TXFIFO for data to be read from the parallel interface pins. This Synchronous Bit-Bang mode
        will read the data bus parallel I/O pins first, before it transmits data from the USB RxFIFO. It is therefore 1
        byte behind the output, and so to read the inputs for the byte that you have just sent, another byte must
        be sent.
        '''
        pass

    def ftd_close(self):
        self.d.close()

    def ftd_spi_test(self):
        self.ftd_spi_init()
        self.ftd_spi_clkcfg(1) #SPICLK = 1MHz
        '''
        The MPSSE can be placed in loop-back mode for diagnostic purposes. 
        In addition to data being transmitted out of the DO pin, it is also connected internally to the DI pin.        
        #0x84:This will connect the TDI / DO output to the TDO / DI input for loopback testing.
        #0x85:This will disconnect the TDI output from the TDO input for loopback testing
        '''
        self.d.write('\x84') #仅能回读到写入的命令字,无法实现3线SPI功能

        # data = 0xab # Synchronize the MPSSE by sending a bogus opcode (0xAB)
        # print(d.read(1, True)) #The MPSSE will respond with "Bad Command" (0xFA) followed by the bogus opcode itself
        '''
        // Set initial states of the MPSSE interface 
        // - low byte, both pin directions and output values
        // Pin name Signal Direction Config Initial State Config
        // ADBUS0 TCK/SK output 1 high 1
        // ADBUS1 TDI/DO output 1 low 0
        // ADBUS2 TDO/DI input 0 0
        // ADBUS3 TMS/CS output 1 high 1
        // ADBUS4 GPIOL0 output 1 low 0
        // ADBUS5 GPIOL1 output 1 low 0
        // ADBUS6 GPIOL2 output 1 high 1
        // ADBUS7 GPIOL3 output 1 high 1        
        # data = (0x80, 0x01, 0xfb) #0x80:Set Data Bits Low Bytes(ADBUS 7-0);0x00:Value;0xfb:Direction TCK/SK, TDI/D0, TMS/CS output, TDO/DI and GPIOL0 -> GPIOL3 input
        # d.write(bytes(data))
        '''
        '''
        《AN108》
        3.3.1 Clock Data Bytes Out on +ve clock edge MSB first (no read)
        Use if CLK starts at '1'
        0x10,
        LengthL,
        LengthH,
        Byte1
        ..
        Byte65536 (max)
        This will clock out bytes on TDI/DO from 1 to 65536 depending on the Length bytes. A length of 0x0000 
        will do 1 byte and a length of 0xffff will do 65536 bytes. The data is sent MSB first. Bit 7 of the first byte 
        is placed on TDI/D0 then the CLK pin is clocked. The data will change to the next bit on the rising edge of 
        the CLK pin. No data is clocked into the device on TDO/DI.
        '''

        chipID = 'xxx'
        addr = 0x1c4
        value = 0xad
        EnbNum = 3
        self.ftd_spi_w(chipID, EnbNum, addr, value)
        print(self.ftd_spi_r(chipID, EnbNum, addr))

        DACONFF_xxx = 0x00
        addrlist = [0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5]
        for addr in addrlist:
            self.ftd_spi_w(chipID, EnbNum, addr, DACONFF_xxx)

        # self.ftd_info()

        self.ftd_close()

    def ftd_spi_enb_test(self):
        self.ftd_spi_init()
        self.ftd_spi_clkcfg(1) #SPICLK = 1MHz

        chipID = 'xxx'
        EnbNum = 7
        addr = 0x1c4
        value = 0xad

        self.ftd_spi_w(chipID, EnbNum, addr, value)

        self.ftd_close()

    def ftd_bitbang_test(self):
        self.ftd_bitbang_init(0xff, 0x1)
        self.d.write(bytes(0x01))
        self.ftd_close()

if __name__ == '__main__':
    adbus = FT4232SPI(3) # 0(BDBUS)/1(CDBUS)/2(DDBUS)/3(ADBUS)
    adbus.ftd_info()
    adbus.ftd_spi_test()
    #
    # bdbus = FT4232SPI(0) # 0(BDBUS)/1(CDBUS)/2(DDBUS)/3(ADBUS)
    # bdbus.ftd_info()
    # # bdbus.ftd_spi_enb_test()
    #
    # cdbus = FT4232SPI(1) # 0(BDBUS)/1(CDBUS)/2(DDBUS)/3(ADBUS)
    # cdbus.ftd_info()
    # # cdbus.ftd_bitbang_test()
    #
    # ddbus = FT4232SPI(2)  # 0(BDBUS)/1(CDBUS)/2(DDBUS)/3(ADBUS)
    # ddbus.ftd_info()

需要特别注意的是:

  • self.d = ftd.open(index) # 0(bdbus)/1(cdbus)/2(ddbus)/3(adbus),adbus对应的index不是“0”,而是“3”,所以,最好通过下面一组指令确认各个dbus对应的index
d1 = ftd.open(0)
print("getDeviceInfo:", d1.getDeviceInfo())

d2 = ftd.open(1)
print("getDeviceInfo:", d2.getDeviceInfo())

d3 = ftd.open(0)
print("getDeviceInfo:", d3.getDeviceInfo())

d4 = ftd.open(1)
print("getDeviceInfo:", d4.getDeviceInfo())
  • 单byte指令发送必须用如下形式——

self.d.write('\x84')

  • 多byte组合指令发送形式如下——

sentbuffer = (0x80, 0xff, 0xfb)

self.d.write(bytes(sentbuffer))

调试结果

MSB/BIT/BYTES/CLK EDGE等设置命令如下表 

详见《Command Processor for MPSSE and MCU Host Bus Emulation Modes

 附:参考资料

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
FT-4232可以配置为SPI设备。当FT4232H作为MPSSE设备时,DBUS0固定为CLK输出,DBUSD1固定为DO,DBUSD2固定为DI。其他DBUS口可以作为SPI的CS脚控制,因此理论上FT4232H可以一路通道控制5个SPI设备。\[1\] 要配置FT-4232SPI设备,可以使用FTDI提供的驱动程序。FTDI提供了免费的Virtual Com Port (VCP)和Direct (D2XX)驱动程序,这些驱动程序可以消除对额外驱动程序的需求。\[2\] SPI的CS控制可以通过GPIO的方式进行。可以使用以下代码实现SPI的CS控制: ```java /* * io: 3-7 low byte io, xDBUS3 - xDBUS7 * 8-15 high byte io, xCBUS0 - xCBUS7 * x - A or B * sel: true - select flash * false = deselect flash */ public void cs(byte io, boolean sel) { if(sel == true) { gpio.output((byte)io, mpsse_gpio.eLevel.Low); } else { gpio.output((byte)io, mpsse_gpio.eLevel.High); } } ``` 这段代码可以实现SPI的CS控制,通过设置GPIO口的输出电平来选择或取消选择SPI设备。\[3\] 因此,要配置FT-4232SPI设备,可以使用FTDI提供的驱动程序,并使用GPIO控制SPI的CS脚。 #### 引用[.reference_title] - *1* *3* [FT4232H Android开发 5 - USBSPI](https://blog.csdn.net/pq113_6/article/details/120863108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [linux中FT4232H设备驱动添加,USB转4串口芯片FT4232HL,FT4232HQ](https://blog.csdn.net/weixin_32330765/article/details/116815360)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值