FT4222H的SPI主模式支持SPI,DSPI,QSPI三种模式,并且可以支持连接4组SPI设备。
【初始化为SPI(主)接口】
当FT4222H打开后可以得到一个handle值,将该值赋值给变量spiMHandle。
对应的API函数是FT4222_SPIMaster_Init。
[DllImport("LibFT4222.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern eFT4222Status FT4222_SPIMaster_Init(IntPtr ftHandle, eSPIMode ioLine, eSPIClock clock, eSPICPOL cpol, eSPICPHA cpha, Byte ssoMap);
参数ioLine表示用的是几线IO,这里初始化建议只选择SPI_IO_SINGLE(很多设备都是默认Single,等切换为其他模式后在设置,有另一个API函数设置)。
public enum eSPIMode
{
SPI_IO_NONE = 0,
SPI_IO_SINGLE = 1,
SPI_IO_DUAL = 2,
SPI_IO_QUAD = 4,
};
参数clock表示SPI的速率,基于FT4222H的系统频率分频得到。
public enum eSPIClock
{
CLK_NONE = 0,
CLK_DIV_2, // 1/2 System Clock
CLK_DIV_4, // 1/4 System Clock
CLK_DIV_8, // 1/8 System Clock
CLK_DIV_16, // 1/16 System Clock
CLK_DIV_32, // 1/32 System Clock
CLK_DIV_64, // 1/64 System Clock
CLK_DIV_128, // 1/128 System Clock
CLK_DIV_256, // 1/256 System Clock
CLK_DIV_512, // 1/512 System Clock
};
参数cpol和cpha对应SPI的四种模式。
case "Mode 0":
spiCPOL = FT4222H.eSPICPOL.CLK_IDLE_LOW;
spiCPHL = FT4222H.eSPICPHA.CLK_LEADING;
break;
case "Mode 1":
spiCPOL = FT4222H.eSPICPOL.CLK_IDLE_LOW;
spiCPHL = FT4222H.eSPICPHA.CLK_TRAILING;
break;
case "Mode 2":
spiCPOL = FT4222H.eSPICPOL.CLK_IDLE_HIGH;
spiCPHL = FT4222H.eSPICPHA.CLK_LEADING;
break;
case "Mode 3":
spiCPOL = FT4222H.eSPICPOL.CLK_IDLE_HIGH;
spiCPHL = FT4222H.eSPICPHA.CLK_TRAILING;
break;
参数表示选择第几个SPI CS口,
【设置IO口模式】
单独设置SPI、DSPI、QSPI
[DllImport("LibFT4222.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern eFT4222Status FT4222_SPIMaster_SetLines(IntPtr ftHandle, eSPIMode spiMode);
【SPI接口写数据】
FT4222H的读写API函数分Single和Multi两类,当FT4222_SPIMaster_SetLines设置为SPI_IO_SINGLE时,对应的写函数是FT4222_SPIMaster_SingleWrite。
[DllImport("LibFT4222.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern eFT4222Status FT4222_SPIMaster_SingleWrite(IntPtr ftHandle,
byte[] buffer, ushort bytesToWrite, ref ushort sizeTransferred, bool isEndTransaction);
参数buffer是写入的数据;参数bytesToWrite是写入数据的长度,即最大64KB;参数sizeTransferred是返回的数据表示实际写入的数据;参数isEndTransaction是表示是否需要在写完数据后将CS拉高。
【SPI接口读数据】
[DllImport("LibFT4222.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern eFT4222Status FT4222_SPIMaster_SingleRead(IntPtr ftHandle,
byte[] buffer, ushort bytesToRead, ref ushort sizeTransferred, bool isEndTransaction);
参数含义与写函数相同。
【DSPI、QSPI读写数据】
当选择DSPI、QSPI时,只有一个读写函数FT4222_SPIMaster_MultiReadWrite。
[DllImport("LibFT4222.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern eFT4222Status FT4222_SPIMaster_MultiReadWrite(
IntPtr ftHandle,
byte[] readBuffer,
byte[] writeBuffer,
byte singleWriteBytes,
ushort multiWriteBytes,
ushort multiReadBytes,
ref UInt32 sizeOfRead);
参数readBuffer,writeBuffer是读写数据buffer;参数singleWriteBytes表示writeBuffer中前面多少个字节是用SPI的方式传输,注意最大256字节;参数multiWriteBytes表示writeBuffer中从singleWriteBytes个字节开始采用DSPI或QSPI传输的数据个数,最大64KB;参数multiReadBytes表示DSPI或QSPI读的数据;参数sizeOfRead是返回实际读到的数据。
以读SPI NOR FLASH的ID为例说明SPI读写调用过程
private const byte CMD_READ_ID = 0x9F;
UInt32 id = 0;
byte[] cmdBuf = new byte[1] { CMD_READ_ID };
byte[] rdBuf = new byte[3] { 0xff, 0xff, 0xff };
FT4222H.eFT4222Status ftStatus = 0;
ushort sizeTransferred = 0;
ftStatus = FT4222H.FT4222_SPIMaster_SingleWrite(ftHandle, cmdBuf, (ushort)cmdBuf.Length, ref sizeTransferred, false);
if (ftStatus != FT4222H.eFT4222Status.FT4222_OK || sizeTransferred != cmdBuf.Length)
{
Console.WriteLine("sflash read Jedec ID fail:" + ftStatus + ", wr size:" + sizeTransferred);
return 0;
}
ftStatus = FT4222H.FT4222_SPIMaster_SingleRead(ftHandle, rdBuf, (ushort)rdBuf.Length, ref sizeTransferred, true);
if (ftStatus != FT4222H.eFT4222Status.FT4222_OK || sizeTransferred != rdBuf.Length)
{
Console.WriteLine("sflash read Jedec ID fail:" + ftStatus + ", rd size:" + sizeTransferred);
return 0;
}
id = ((UInt32)rdBuf[0] << 16) | (UInt32)(rdBuf[1] << 8) | (UInt32)(rdBuf[2]);
SPI速度测试结果,其中BT816可以当作一个1MB的SPI接口的SRAM。
Platform: FT4222H + Winbond W25Q64 | ||||
Clock(MHz) | Div | IO | RD | WR |
80 | 1/2 | Quad | 4.76MB | 150KB |
80 | 1/2 | Single | 2.96MB | 103KB |
80 | 1/4 | Quad | 4.99MB | 159KB |
80 | 1/4 | Single | 1.82MB | 103KB |
60 | 1/2 | Quad | 4.56MB | 142KB |
60 | 1/2 | Single | 2.50MB | 111KB |
60 | 1/4 | Quad | 3.88MB | 156KB |
60 | 1/4 | Single | 1.50MB | 112KB |
48 | 1/2 | Quad | 3.50MB | 130KB |
48 | 1/2 | Single | 2.10MB | 124KB |
24 | 1/2 | Quad | 1.91MB | 106KB |
24 | 1/2 | Single | 806KB | 107KB |
24 | 1/512 | Single | 5.84KB | 5.40KB |
Platform: FT4222H + VM816C50A-D | ||||
Clock(MHz) | Div | IO | RD | WR |
80 | 1/2 | Dual | 5.47MB | 4.92MB |
80 | 1/2 | Single | 2.58MB | 3.27MB |
80 | 1/4 | Quad | 4.49MB | 4.92MB |
80 | 1/4 | Single | 1.64MB | 1.77MB |
60 | 1/2 | Quad | 4.74MB | 5.15MB |
60 | 1/2 | Single | 1.84MB | 2.19MB |
60 | 1/4 | Quad | 4.13MB | 3.80MB |
60 | 1/4 | Single | 1.27MB | 1.24MB |
48 | 1/2 | Quad | 3.54MB | 4.13MB |
48 | 1/2 | Single | 1.68MB | 1.70MB |
24 | 1/2 | Quad | 1.96MB | 2.05MB |
24 | 1/2 | Single | 949KB | 967KB |
24 | 1/512 | Single | 5.85KB | 5.85KB |
Note: 80 1/2 Dual test Fail, and BT816 can't support 80M 1/2 Quad |