我使用的是FT2232H-56Q。我想使用SPI通道。我下载了the libMPSSE-SPI example。
我正在使用示例示例" sample-static.c"。当我运行exe时,我总是收到这条消息:
按任意键继续。 。 。可用SPI通道数= 0
即使设备已连接,也会发生这种情况。
代码:
/*!
* \file sample-static.c
*
* \author FTDI
* \date 20110512
*
* Copyright © 2000-2014 Future Technology Devices International Limited
*
*
* THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Project: libMPSSE
* Module: SPI Sample Application - Interfacing 94LC56B SPI EEPROM
*
* Rivision History:
* 0.1 - 20110512 - Initial version
* 0.2 - 20110801 - Changed LatencyTimer to 255
* Attempt to open channel only if available
* Added & modified macros
* Included stdlib.h
* 0.3 - 20111212 - Added comments
* 0.41 - 20140903 - Fixed compilation warnings
* Added testing of SPI_ReadWrite()
*/
/******************************************************************************/
/* Include files */
/******************************************************************************/
/* Standard C libraries */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <assert.h>
//#include <vector.h>
#include <stdbool.h>
//#include <random>
/* OS specific libraries */
#ifdef _WIN32
#include<windows.h>
#endif
/* Include D2XX header*/
#include "ftd2xx.h"
/* Include libMPSSE header */
#include "libMPSSE_spi.h"
/******************************************************************************/
/* Macro and type defines */
/******************************************************************************/
/* Helper macros */
#define APP_CHECK_STATUS(exp) {if(exp!=FT_OK){printf("%s:%d:%s(): status(0x%x) \
!= FT_OK\n",__FILE__, __LINE__, __FUNCTION__,exp);exit(1);}else{;}};
#define CHECK_NULL(exp){if(exp==NULL){printf("%s:%d:%s(): NULL expression \
encountered \n",__FILE__, __LINE__, __FUNCTION__);exit(1);}else{;}};
/* Application specific macro definations */
#define SPI_DEVICE_BUFFER_SIZE 256
#define SPI_WRITE_COMPLETION_RETRY 10
#define START_ADDRESS_EEPROM 0x00 /*read/write start address inside the EEPROM*/
#define END_ADDRESS_EEPROM 0x10
#define RETRY_COUNT_EEPROM 10 /* number of retries if read/write fails */
#define CHANNEL_TO_OPEN 0 /*0 for first available channel, 1 for next... */
#define SPI_SLAVE_0 0
#define SPI_SLAVE_1 1
#define SPI_SLAVE_2 2
#define DATA_OFFSET 4
#define USE_WRITEREAD 0
/******************************************************************************/
/* Global variables */
/******************************************************************************/
static FT_HANDLE ftHandle;
static uint8 buffer[SPI_DEVICE_BUFFER_SIZE] = {0};
static FT_DEVICE_LIST_INFO_NODE *devList;
static uint32 numberChannels;
/******************************************************************************/
/* Public function definitions */
/******************************************************************************/
/**
* @brief Initializes the comBridge
* Must be called first
* @param[out] noChannels: Number of available channels
* @param[out] channelId[]: Description of the devices with their index being identical to the channel selector in all other functions
* @return Device status with FT_OK = 0
*/
FT_STATUS comBridge_initialize(uint32 *noChannels, char *channelId[]) {
Init_libMPSSE();
FT_STATUS status = FT_OK;
// get number of channels
status = SPI_GetNumChannels(noChannels);
numberChannels = *noChannels;
APP_CHECK_STATUS(status);
#ifdef VERBOSE
printf("ComBridge initialized\n");
printf(" SPI channels %d\n\n", *noChannels);
#endif // VERBOSE
// get channel infos
devList = (FT_DEVICE_LIST_INFO_NODE *)calloc(*noChannels, sizeof(FT_DEVICE_LIST_INFO_NODE));
for (uint32 channelIndex = 0; channelIndex < *noChannels; channelIndex++) {
status = SPI_GetChannelInfo(channelIndex, devList);
APP_CHECK_STATUS(status);
strcpy(channelId[channelIndex], devList->Description);
#ifdef VERBOSE
printf("Channel %d info\n", channelIndex);
printf(" Flags 0x%x\n", devList->Flags);
printf(" Type 0x%x\n", devList->Type);
printf(" ID 0x%x\n", devList->ID);
printf(" LocId 0x%x\n", devList->LocId);
printf(" SerialNumber %s\n", devList->SerialNumber);
printf(" Description %s\n", devList->Description);
//printf(" ftHandle=0x%x\n", (unsigned int)devList->ftHandle);
printf("\n");
#endif // VERBOSE
};
return status;
}
/**
* @brief Opens and initilizes a SPI channel
* Must be called after comBridge_initialize() and for each channel individually
* Latency = 255 ms, that "xDBUS3 of MPSSE is chip select" and that "chip select is active high" are predefined and cannot be changed manually
* @param[in] channel: Selects a channel via the index of the corresponding element in the channelId[] array
* @param[in] clockRate_Hz: Clock rate of the SPI bus in Hz (0..10 MHz)
* @param[in] spiMode: Selects SPI Mode (SPI_CONFIG_OPTION_MODE0 or SPI_CONFIG_OPTION_MODE3)
* @return Device status with FT_OK = 0
*/
FT_STATUS comBridge_setup(uint32 channel, uint32 clockRate_Hz, uint32 spiMode) {
FT_STATUS status = FT_OK;
assert(channel < numberChannels);
assert(clockRate_Hz <= 10000000);
assert((spiMode == SPI_CONFIG_OPTION_MODE0) | (spiMode == SPI_CONFIG_OPTION_MODE3));
status = SPI_OpenChannel(channel, &devList[channel].ftHandle);
APP_CHECK_STATUS(status);
ChannelConfig channelConf = {
5000, // ClockRate
255, // LatencyTime
SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW, // configOptions
0x00000000 // Pin
};
channelConf.ClockRate = clockRate_Hz;
channelConf.configOptions = spiMode | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW;
status = SPI_InitChannel(devList[channel].ftHandle, &channelConf);
APP_CHECK_STATUS(status);
#ifdef VERBOSE
printf("Channel %d opened\n", channel);
printf(" ClockRate %d\n", channelConf.ClockRate);
printf(" Latency %d\n", channelConf.LatencyTimer);
printf(" Config %d\n", channelConf.configOptions);
printf(" Pin %d\n\n", channelConf.Pin);
//printf(" Handle=%ld\n", (uint32)devList[channel].ftHandle);
#endif // VERBOSE
// sets all GPIO pins as input
status = FT_WriteGPIO(devList[channel].ftHandle, 0b00000000, 0b00000000);
APP_CHECK_STATUS(status);
return status;
}
/*!
* \brief Writes to EEPROM
*
* This function writes a byte to a specified address within the 93LC56B EEPROM
*
* \param[in] slaveAddress Address of the I2C slave (EEPROM)
* \param[in] registerAddress Address of the memory location inside the slave to where the byte
* is to be written
* \param[in] data The byte that is to be written
* \return Returns status code of type FT_STATUS(see D2XX Programmer's Guide)
* \sa Datasheet of 93LC56B http://ww1.microchip.com/downloads/en/DeviceDoc/21794F.pdf
* \note
* \warning
*/
static FT_STATUS read_byte(uint8 slaveAddress, uint8 address, uint16 *data)
{
uint32 sizeToTransfer = 0;
uint32 sizeTransfered;
uint8 writeComplete=0;
uint32 retry=0;
FT_STATUS status;
/* CS_High + Write command + Address */
sizeToTransfer=1;
sizeTransfered=0;
buffer[0] = 0xC0;/* Write command (3bits)*/
buffer[0] = buffer[0] | ( ( address >> 3) & 0x0F );/*5 most significant add bits*/
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
/*Write partial address bits */
sizeToTransfer=4;
sizeTransfered=0;
buffer[0] = ( address & 0x07 ) << 5; /* least significant 3 address bits */
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS);
APP_CHECK_STATUS(status);
/*Read 2 bytes*/
sizeToTransfer=2;
sizeTransfered=0;
status = SPI_Read(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
*data = (uint16)(buffer[1]<<8);
*data = (*data & 0xFF00) | (0x00FF & (uint16)buffer[0]);
return status;
}
/*!
* \brief Reads from EEPROM
*
* This function reads a byte from a specified address within the 93LC56B EEPROM
*
* \param[in] slaveAddress Address of the I2C slave (EEPROM)
* \param[in] registerAddress Address of the memory location inside the slave from where the
* byte is to be read
* \param[in] *data Address to where the byte is to be read
* \return Returns status code of type FT_STATUS(see D2XX Programmer's Guide)
* \sa Datasheet of 93LC56B http://ww1.microchip.com/downloads/en/DeviceDoc/21794F.pdf
* \note
* \warning
*/
static FT_STATUS write_byte(uint8 slaveAddress, uint8 address, uint16 data)
{
uint32 sizeToTransfer = 0;
uint32 sizeTransfered=0;
uint8 writeComplete=0;
uint32 retry=0;
FT_STATUS status;
/* Write command EWEN(with CS_High -> CS_Low) */
sizeToTransfer=11;
sizeTransfered=0;
buffer[0]=0x9F;/* SPI_EWEN -> binary 10011xxxxxx (11bits) */
buffer[1]=0xFF;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
/* CS_High + Write command + Address */
sizeToTransfer=1;
sizeTransfered=0;
buffer[0] = 0xA0;/* Write command (3bits) */
buffer[0] = buffer[0] | ( ( address >> 3) & 0x0F );/*5 most significant add bits*/
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
/*Write 3 least sig address bits */
sizeToTransfer=3;
sizeTransfered=0;
buffer[0] = ( address & 0x07 ) << 5; /* least significant 3 address bits */
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS);
APP_CHECK_STATUS(status);
/* Write 2 byte data + CS_Low */
sizeToTransfer=2;
sizeTransfered=0;
buffer[0] = (uint8)(data & 0xFF);
buffer[1] = (uint8)((data & 0xFF00)>>8);
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
/* Wait until D0 is high */
#if 1
/* Strobe Chip Select */
sizeToTransfer=0;
sizeTransfered=0;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
APP_CHECK_STATUS(status);
#ifndef __linux__
Sleep(10);
#endif
sizeToTransfer=0;
sizeTransfered=0;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
#else
retry=0;
state=FALSE;
SPI_IsBusy(ftHandle,&state);
while((FALSE==state) && (retry<SPI_WRITE_COMPLETION_RETRY))
{
printf("SPI device is busy(%u)\n",(unsigned)retry);
SPI_IsBusy(ftHandle,&state);
retry++;
}
#endif
/* Write command EWEN(with CS_High -> CS_Low) */
sizeToTransfer=11;
sizeTransfered=0;
buffer[0]=0x8F;/* SPI_EWEN -> binary 10011xxxxxx (11bits) */
buffer[1]=0xFF;
status = SPI_Write(ftHandle, buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
APP_CHECK_STATUS(status);
return status;
}
/*!
* \brief Main function / Entry point to the sample application
*
* This function is the entry point to the sample application. It opens the channel, writes to the
* EEPROM and reads back.
*
* \param[in] none
* \return Returns 0 for success
* \sa
* \note
* \warning
*/
int main()
{
uint32 noChannels = 0;
char *channelId[10];
char channelIdArray[10][46] = { { '\0' } };
for (int i = 0; i < sizeof(channelId); i++)
channelId[i] = channelIdArray[i];
comBridge_initialize(&noChannels, channelId);
for (uint32 channel = 0; channel < noChannels; channel++)
{
//cout << "Channel " << channel << ": " << channelId[channel] << endl;
comBridge_setup(channel, 100000, SPI_CONFIG_OPTION_MODE0);
comBridge_release(channel);
}
FT_STATUS status = FT_OK;
FT_DEVICE_LIST_INFO_NODE devList = {0};
ChannelConfig channelConf = {0};
uint8 address = 0;
uint32 channels = 0;
uint16 data = 0;
uint8 i = 0;
uint8 latency = 255;
channelConf.ClockRate = 5000;
channelConf.LatencyTimer = latency;
channelConf.configOptions = SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3;// | SPI_CONFIG_OPTION_CS_ACTIVELOW;
channelConf.Pin = 0x00000000;/*FinalVal-FinalDir-InitVal-InitDir (for dir 0=in, 1=out)*/
/* init library */
#ifdef _MSC_VER
Init_libMPSSE();
#endif
status = SPI_GetNumChannels(&channels);
APP_CHECK_STATUS(status);
printf("Number of available SPI channels = %d\n",(int)channels);
if(channels>0)
{
for(i=0;i<channels;i++)
{
status = SPI_GetChannelInfo(i,&devList);
APP_CHECK_STATUS(status);
printf("Information on channel number %d:\n",i);
/* print the dev info */
printf(" Flags=0x%x\n",devList.Flags);
printf(" Type=0x%x\n",devList.Type);
printf(" ID=0x%x\n",devList.ID);
printf(" LocId=0x%x\n",devList.LocId);
printf(" SerialNumber=%s\n",devList.SerialNumber);
printf(" Description=%s\n",devList.Description);
printf(" ftHandle=0x%x\n",(unsigned int)devList.ftHandle);/*is 0 unless open*/
}
/* Open the first available channel */
status = SPI_OpenChannel(CHANNEL_TO_OPEN,&ftHandle);
APP_CHECK_STATUS(status);
printf("\nhandle=0x%x status=0x%x\n",(unsigned int)ftHandle,status);
status = SPI_InitChannel(ftHandle,&channelConf);
APP_CHECK_STATUS(status);
#if USE_WRITEREAD
{
uint8 k,l;
uint8 inBuffer[100];
uint8 outBuffer[]={0x81,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39};
uint32 sizeToTransfer,sizeTransferred;
for(k=0; k<5; k++)
{
printf("LoopCount = %u ",(unsigned)k);
sizeToTransfer=10;
sizeTransferred=0;
#if 1 // BYTES
status = SPI_ReadWrite(ftHandle, inBuffer, outBuffer+k, sizeToTransfer, &sizeTransferred,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
#else // BITES
status = SPI_ReadWrite(ftHandle, inBuffer, outBuffer+k, sizeToTransfer*8, &sizeTransferred,
SPI_TRANSFER_OPTIONS_SIZE_IN_BITS|
SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE|
SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
#endif
APP_CHECK_STATUS(status);
printf("status=0x%x sizeTransferred=%u\n", status, sizeTransferred);
for(l=0;l<sizeToTransfer;l++)
printf("0x%x\n",(unsigned)inBuffer[l]);
printf("\n");
}
}
#else // USE_WRITEREAD
for(address=START_ADDRESS_EEPROM;address<END_ADDRESS_EEPROM;address++)
{
printf("writing address = %02d data = %d\n",address,address+DATA_OFFSET);
write_byte(SPI_SLAVE_0, address,(uint16)address+DATA_OFFSET);
}
for(address=START_ADDRESS_EEPROM;address<END_ADDRESS_EEPROM;address++)
{
read_byte(SPI_SLAVE_0, address,&data);
printf("reading address = %02d data = %d\n",address,data);
}
#endif // USE_WRITEREAD
status = SPI_CloseChannel(ftHandle);
}
#ifdef _MSC_VER
Cleanup_libMPSSE();
#endif
#ifndef __linux__
system("pause");
#endif
return 0;
}
答案 0 :(得分:1)
FT2232H / win7Pro也有同样的问题。
根本原因是libMPSSE获得了错误的locID并判断该设备不可用,因为D2XX始终将locId = 0返回给libMPSSE。
ftdi_mid.c
case FT_DEVICE_2232H:
if(((devList.LocId & 0xf)==1)|| ((devList.LocId & 0xf)==2))
{
isMPSSEAvailable = MID_MPSSE_AVAILABLE;
}
break;
我修改条件并用mingw64重新编译libMPSSE。就是这样。
答案 1 :(得分:0)
我已就此问题写信给FTDI Chip。支持人员发送了一个有效的更新库。库的版本是0.6(测试版)。
答案 2 :(得分:0)
我在Ubuntu 19.10上有类似的问题。造成这种情况的根本原因是内核模块在连接FTDI之后便与FTDI进行交互,从而阻止了我与之建立连接。
解决方案是卸载该内核模块:
sudo rmmod ftdi_sio
libftd2xx ReadMe
文件中也提到了它:
If the message "FT_Open failed" appears:
Perhaps the kernel automatically loaded another driver for the
FTDI USB device.
sudo lsmod
If "ftdi_sio" is listed:
Unload it (and its helper module, usbserial), as follows.
sudo rmmod ftdi_sio
sudo rmmod usbserial
Otherwise, it's possible that libftd2xx does not recognise your
device's Vendor and Product Identifiers. Call FT_SetVIDPID before
calling FT_Open/FT_OpenEx/FT_ListDevices.