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 |