为什么需要四线串行访问23LC1024?

在“ 单片机片外RAM,串行的[1]”中减少了对Microchip公司的SPI接口RAM芯片:23LC1024的读写测试。但是在STC8G1K08但潘辰的SPI接口驱动下,访问对其进行一次字节的读写操作,大概需要消耗20微妙的的时间,这使得在高速、高精度采集应用中跟不上数据的采集。

为了提高对其的访问速度,可以采用以下的方式:

下面为了配合 AD7606八通道AD采集模块测试[2]中数据的采集,首先测试23LC1024在STC8G1K08操作下访问速度

本文实验中的工程文件可以在下面资源中下载:

  1. 23LC1024串行四线访问工程[3]

实验电路设计

AD工程文件目录:

AD\Test\2020\TestAD7606STC\TestAD7606STC8G.SchDoc

1. 原理图

电路板设计中采用了STC8G1K08 TSOP20封装的芯片。核心板上集成了23LC1024串行接口的RAM,对于AD7606的接口是通过ADI10芯接口连接。

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(1)

▲ 原理图

2. PCB

设计电路PCB版图,适宜使用单面PCB板制作实验电路。

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(2)

▲ 快速制版后的实验电路板

3. 硬件调试

软件开发所在的目录:

C51\STC\Test\2020\testAD76068G1K\TestAD76068G.uvproj

置STC8G1K08的硬件选项配置如下:

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(3)

▲ 单片机硬件选项配置

主要性能测试

1. 测试单个字节读写的时间

测试标准写入函数在执行过程中,LC1024的CS的波形:

LC1024ByteWrite(0, 0, 0xff, 0xf)

写入时间为2us,CS的波形如下图所示:

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(4)

▲ CS波形,时间为2.03us

读出的时间也是2.0us,

LC1024ByteRead(0x0, 0x0, 0xff)

下面是在读的时候,CLK, SO1的波形。

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(5)

▲ CLK,SD1的波形

2. 连续字节读写

使用连续字节读写的方式读取多组字节。下面是读取连续10个字节。所需要的时间为8.57us。

LC1024ReadBegin(0x0,0x0,0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024WriteByte(0x0); LC1024ReadWriteEnd();

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(6)

▲ 连续读取十个字节所需要的时间

如果仅仅执行读取起始和结束的语句:

LC1024ReadBegin(0x0,0x0,0x0); LC1024ReadWriteEnd();

所小号的时间为2us。这说明读取单个字节的时间大约为左右。

这个速度与博文“ 扩展32KRAM的STC8H8K信号采集版[4]”中,通过并口扩展RAM的一次读写时间0.532us的速度基本相当了。

通过这个时间可以说明,使用SQI(串行四线制)在连续读写的情况下可以达到与并口扩展RAM相当的速度。

即使是单个读写所消耗的2us的时间,也比在博文“ 单片机片外RAM,串行的[5]”中读取单个字节所消耗19.2us将近快了10倍左右。

ram芯片的最小数目(串行RAM23LC1024四线访问数据)(7)

函数程序模块

相关LC1024读取的程序模块如下。

其中致的说明的是,在LC1024的初始化函数中,调用了LC1024Reset命令,就保证了LC1024成功进入SQI模式。

  1. LC1024访问函数头文件:

/* ***************************************** **LC1024L4.H:--byDr.ZhuoQing,2020-05-04 ** **Description: ** ***************************************** */ #ifndef__LC1024L4__ #define__LC1024L4__ //------------------------------------------------------------------------------ #ifdefLC1024L4_GLOBALS #defineLC1024L4_EXT #else #defineLC1024L4_EXTextern #endif//LC1024L4_GLOBALS //------------------------------------------------------------------------------ //*************************************** #defineLC1024_CS1,5 #defineLC1024_CLK1,4 #defineLC1024_SO01,0 #defineLC1024_SO11,1 #defineLC1024_SO21,2 #defineLC1024_SO31,3 #defineLC1024_CLK_PULSEON(LC1024_CLK),_nop_(),OFF(LC1024_CLK) #defineLC1024_SO_OUT(P1M1&=0xf0,P1M0|=0xf) #defineLC1024_SO_IN(P1M1|=0xf,P1M0&=0xf0) //------------------------------------------------------------------------------ voidLC1024L4Init(void); //------------------------------------------------------------------------------ #defineLC1024_READ0x03//Readdatafrommemoryareraybeginningatselectedaddress #defineLC1024_WRITE0x02//Writedatatomemoryarraybeginningatselectedaddress #defineLC1024_EDIO0x3B//EnterDualI/Oaccess(EnterSDIbusmode) #defineLC1024_EQIO0x38//EnterQuadI/Oaccess #defineLC1024_RSTIO0xFF//ResetDualandQuadI/Oaccess #defineLC1024_RDMR0x05//ReadModeregister #defineLC1024_WRMR0x1//WriteModeregister #defineLONG_3(w)((unsignedchar)(w>>24)) #defineLONG_2(w)((unsignedchar)(w>>16)) #defineLONG_1(w)((unsignedchar)(w>>8)) #defineLONG_0(w)((unsignedchar)w) //------------------------------------------------------------------------------ voidLC1024Reset(void); voidLC1024EQIEnter(void); voidLC1024EQIExit(void); //------------------------------------------------------------------------------ unsignedcharLC1024ByteRead(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0); voidLC1024ByteWrite(unsignedcharucAdd2,unsignedcharucAdd1, unsignedcharucAdd0,unsignedcharucByte); //------------------------------------------------------------------------------ voidLC1024ReadBegin(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0); voidLC1024WriteBegin(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0); unsignedcharLC1024ReadByte(void); voidLC1024WriteByte(unsignedcharucByte); voidLC1024ReadWriteEnd(void); //------------------------------------------------------------------------------ unsignedcharLC1024ReadMode(void); voidLC1024WriteMode(unsignedcharucMode); //*************************************** //ENDOFTHEFILE:LC1024L4.H //------------------------------------------------------------------------------ #endif//__LC1024L4__

  1. LC1024的C语言程序。

/* ***************************************** **LC1024L4.C:--byDr.ZhuoQing,2020-05-04 ** ***************************************** */ //------------------------------------------------------------------------------ #defineLC1024L4_GLOBALS1//Definetheglobalvariables #include"LC1024L4.H" #include"C51BASIC.H" #include"STC8G.H" #include"INTRINS.H" //------------------------------------------------------------------------------ voidLC1024L4Init(void){ PM_PP(LC1024_CS); PM_PP(LC1024_CLK); ON(LC1024_CS); OFF(LC1024_CLK); LC1024_SO_IN; LC1024Reset(); LC1024EQIEnter(); } //------------------------------------------------------------------------------ voidLC1024EQIEnter(void){ unsignedchari,ucMask,ucByte; ucByte=LC1024_EQIO; ucMask=0x80; LC1024_SO_IN; PM_PP(LC1024_SO0); OFF(LC1024_CS); for(i=0;i<8;i ){ if(ucByte&ucMask)ON(LC1024_SO0); elseOFF(LC1024_SO0); ucMask>>=1; LC1024_CLK_PULSE; } LC1024_SO_IN; ON(LC1024_CS); } voidLC1024EQIExit(void){ LC1024_SO_OUT; P1|=0xf; OFF(LC1024_CS); LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_SO_IN; ON(LC1024_CS); } //------------------------------------------------------------------------------ unsignedcharLC1024ByteRead(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0){ unsignedcharucRet; LC1024_SO_OUT; OFF(LC1024_CS); P1&=0xf0; LC1024_CLK_PULSE; P1|=0x3; LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0&0xf); LC1024_CLK_PULSE; LC1024_SO_IN; LC1024_CLK_PULSE;//Dummybyte LC1024_CLK_PULSE; ON(LC1024_CLK); ucRet=(P1<<4); OFF(LC1024_CLK); ON(LC1024_CLK); ucRet|=(P1&0xf); OFF(LC1024_CLK); ON(LC1024_CS); returnucRet; } //------------------------------------------------------------------------------ voidLC1024ByteWrite(unsignedcharucAdd2,unsignedcharucAdd1, unsignedcharucAdd0,unsignedcharucByte){ LC1024_SO_OUT; OFF(LC1024_CS); P1&=0xf0; LC1024_CLK_PULSE; P1|=0x2; LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucByte>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucByte&0xf); LC1024_CLK_PULSE; LC1024_SO_IN; ON(LC1024_CS); } //------------------------------------------------------------------------------ unsignedcharLC1024ReadMode(void){ unsignedcharucRet; OFF(LC1024_CS); LC1024_SO_OUT; P1&=0xf0; LC1024_CLK_PULSE; P1|=0x5; LC1024_CLK_PULSE; LC1024_SO_IN; ON(LC1024_CLK); ucRet=(P1<<4); OFF(LC1024_CLK); ON(LC1024_CLK); ucRet|=(P1&0xf); OFF(LC1024_CLK); ON(LC1024_CS); returnucRet; } //------------------------------------------------------------------------------ voidLC1024ReadBegin(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0){ LC1024_SO_OUT; OFF(LC1024_CS); P1&=0xf0; LC1024_CLK_PULSE; P1|=0x3; LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0&0xf); LC1024_CLK_PULSE; LC1024_SO_IN; LC1024_CLK_PULSE;//Dummybyte LC1024_CLK_PULSE; } //------------------------------------------------------------------------------ voidLC1024WriteBegin(unsignedcharucAdd2,unsignedcharucAdd1,unsignedcharucAdd0){ LC1024_SO_OUT; OFF(LC1024_CS); P1&=0xf0; LC1024_CLK_PULSE; P1|=0x2; LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd2&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd1&0xf); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucAdd0&0xf); LC1024_CLK_PULSE; } unsignedcharLC1024ReadByte(void){ unsignedcharucRet; ON(LC1024_CLK); ucRet=(P1<<4); OFF(LC1024_CLK); ON(LC1024_CLK); ucRet|=(P1&0xf); OFF(LC1024_CLK); returnucRet; } voidLC1024WriteByte(unsignedcharucByte){ P1&=0xf0; P1|=(ucByte>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucByte&0xf); LC1024_CLK_PULSE; } //------------------------------------------------------------------------------ voidLC1024ReadWriteEnd(void){ LC1024_SO_IN; ON(LC1024_CS); } //------------------------------------------------------------------------------ voidLC1024WriteMode(unsignedcharucMode){ LC1024_SO_OUT; OFF(LC1024_CS); P1&=0xf0; LC1024_CLK_PULSE; P1|=0x5; LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucMode>>4); LC1024_CLK_PULSE; P1&=0xf0; P1|=(ucMode&0xf); LC1024_CLK_PULSE; ON(LC1024_CS); LC1024_SO_IN; } //------------------------------------------------------------------------------ voidLC1024Reset(void){ LC1024_SO_OUT; P1|=0xf; OFF(LC1024_CS); LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; LC1024_CLK_PULSE; ON(LC1024_CS); LC1024_SO_IN; } //*************************************** //ENDOFTHEFILE:LC1024L4.C //------------------------------------------------------------------------------

结论

参考资料

[1] 单片机片外RAM,串行的: https://zhuoqing.blog.csdn.net/article/details/105891541

[2] AD7606八通道AD采集模块测试: https://zhuoqing.blog.csdn.net/article/details/105908384

[3] 23LC1024串行四线访问工程: https://download.csdn.net/download/zhuoqingjoking97298/12388449

[4] 扩展32KRAM的STC8H8K信号采集版: https://zhuoqing.blog.csdn.net/article/details/105798094

,