爲什麼需要四線串行訪問23LC1024?
在“單片機片外RAM,串行的
”中減少了對Microchip公司的SPI接口RAM芯片:23LC1024的讀寫測試。但是在STC8G1K08但潘辰的SPI接口驅動下,訪問對其進行一次字節的讀寫操作,大概需要消耗20微妙的的時間,這使得在高速、高精度採集應用中跟不上數據的採集。
爲了提高對其的訪問速度,可以採用以下的方式:
- 使用其四線串行模式(SQI)的方式進行訪問;
- 儘量使用序列讀寫方式,而不是每次完成完整的命令+地址+數據的腹瀉方式
下面爲了配合AD7606八通道AD採集模塊測試
中數據的採集,首先測試23LC1024在STC8G1K08操作下訪問速度
本文實驗中的工程文件可以在下面資源中下載:
實驗電路設計
AD工程文件目錄:
AD\Test\2020\TestAD7606STC\TestAD7606STC8G.SchDoc
1. 原理圖
電路板設計中採用了STC8G1K08 TSOP20封裝的芯片。核心板上集成了23LC1024串行接口的RAM,對於AD7606的接口是通過ADI10芯接口連接。
▲ 原理圖
2. PCB
設計電路PCB版圖,適宜使用單面PCB板製作實驗電路。
▲ 快速製版後的實驗電路板
3. 硬件調試
軟件開發所在的目錄:
C51\STC\Test\2020\testAD76068G1K\TestAD76068G.uvproj
置STC8G1K08的硬件選項配置如下:
▲ 單片機硬件選項配置
主要性能測試
1. 測試單個字節讀寫的時間
測試標準寫入函數在執行過程中,LC1024的CS的波形:
LC1024ByteWrite(0, 0, 0xff, 0xf)
寫入時間爲2us,CS的波形如下圖所示:
▲ CS波形,時間爲2.03us
讀出的時間也是2.0us,
LC1024ByteRead(0x0, 0x0, 0xff)
下面是在讀的時候,CLK, SO1的波形。
▲ 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();
▲ 連續讀取十個字節所需要的時間
如果僅僅執行讀取起始和結束的語句:
LC1024ReadBegin(0x0, 0x0, 0x0);
LC1024ReadWriteEnd();
所小號的時間爲2us。這說明讀取單個字節的時間大約爲左右。
這個速度與博文“擴展32KRAM的STC8H8K信號採集版
”中,通過並口擴展RAM的一次讀寫時間0.532us的速度基本相當了。
通過這個時間可以說明,使用SQI(串行四線制)在連續讀寫的情況下可以達到與並口擴展RAM相當的速度。
即使是單個讀寫所消耗的2us的時間,也比在博文“單片機片外RAM,串行的
”中讀取單個字節所消耗19.2us將近快了10倍左右。
▲ 通電進行調試
▲ 測量讀寫信號波形
函數程序模塊
相關LC1024讀取的程序模塊如下。
其中致的說明的是,在LC1024的初始化函數中,調用了LC1024Reset命令,就保證了LC1024成功進入SQI模式。
- LC1024訪問函數頭文件:
/*
**==============================================================================
** LC1024L4.H: -- by Dr. ZhuoQing, 2020-05-04
**
** Description:
**
**==============================================================================
*/
#ifndef __LC1024L4__
#define __LC1024L4__
//------------------------------------------------------------------------------
#ifdef LC1024L4_GLOBALS
#define LC1024L4_EXT
#else
#define LC1024L4_EXT extern
#endif // LC1024L4_GLOBALS
//------------------------------------------------------------------------------
//==============================================================================
#define LC1024_CS 1, 5
#define LC1024_CLK 1, 4
#define LC1024_SO0 1, 0
#define LC1024_SO1 1, 1
#define LC1024_SO2 1, 2
#define LC1024_SO3 1, 3
#define LC1024_CLK_PULSE ON(LC1024_CLK),_nop_(),OFF(LC1024_CLK)
#define LC1024_SO_OUT (P1M1 &= 0xf0, P1M0|=0xf)
#define LC1024_SO_IN (P1M1 |= 0xf, P1M0 &= 0xf0)
//------------------------------------------------------------------------------
void LC1024L4Init(void);
//------------------------------------------------------------------------------
#define LC1024_READ 0x03 // Read data from memory areray beginning at selected address
#define LC1024_WRITE 0x02 // Write data to memory array beginning at selected address
#define LC1024_EDIO 0x3B // Enter Dual I/O access(Enter SDI bus mode)
#define LC1024_EQIO 0x38 // Enter Quad I/O access
#define LC1024_RSTIO 0xFF // Reset Dual and Quad I/O access
#define LC1024_RDMR 0x05 // Read Mode register
#define LC1024_WRMR 0x1 // Write Mode register
#define LONG_3(w) ((unsigned char)(w >> 24))
#define LONG_2(w) ((unsigned char)(w >> 16))
#define LONG_1(w) ((unsigned char)(w >> 8))
#define LONG_0(w) ((unsigned char)w)
//------------------------------------------------------------------------------
void LC1024Reset(void);
void LC1024EQIEnter(void);
void LC1024EQIExit(void);
//------------------------------------------------------------------------------
unsigned char LC1024ByteRead(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0);
void LC1024ByteWrite(unsigned char ucAdd2, unsigned char ucAdd1,
unsigned char ucAdd0, unsigned char ucByte);
//------------------------------------------------------------------------------
void LC1024ReadBegin(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0);
void LC1024WriteBegin(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0);
unsigned char LC1024ReadByte(void);
void LC1024WriteByte(unsigned char ucByte);
void LC1024ReadWriteEnd(void);
//------------------------------------------------------------------------------
unsigned char LC1024ReadMode(void);
void LC1024WriteMode(unsigned char ucMode);
//==============================================================================
// END OF THE FILE : LC1024L4.H
//------------------------------------------------------------------------------
#endif // __LC1024L4__
- LC1024的C語言程序。
/*
**==============================================================================
** LC1024L4.C: -- by Dr. ZhuoQing, 2020-05-04
**
**==============================================================================
*/
//------------------------------------------------------------------------------
#define LC1024L4_GLOBALS 1 // Define the global variables
#include "LC1024L4.H"
#include "C51BASIC.H"
#include "STC8G.H"
#include "INTRINS.H"
//------------------------------------------------------------------------------
void LC1024L4Init(void) {
PM_PP(LC1024_CS);
PM_PP(LC1024_CLK);
ON(LC1024_CS);
OFF(LC1024_CLK);
LC1024_SO_IN;
LC1024Reset();
LC1024EQIEnter();
}
//------------------------------------------------------------------------------
void LC1024EQIEnter(void) {
unsigned char i, 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);
else OFF(LC1024_SO0);
ucMask >>= 1;
LC1024_CLK_PULSE;
}
LC1024_SO_IN;
ON(LC1024_CS);
}
void LC1024EQIExit(void) {
LC1024_SO_OUT;
P1 |= 0xf;
OFF(LC1024_CS);
LC1024_CLK_PULSE;
LC1024_CLK_PULSE;
LC1024_SO_IN;
ON(LC1024_CS);
}
//------------------------------------------------------------------------------
unsigned char LC1024ByteRead(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0) {
unsigned char ucRet;
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; // Dummy byte
LC1024_CLK_PULSE;
ON(LC1024_CLK);
ucRet = (P1 << 4);
OFF(LC1024_CLK);
ON(LC1024_CLK);
ucRet |= (P1 & 0xf);
OFF(LC1024_CLK);
ON(LC1024_CS);
return ucRet;
}
//------------------------------------------------------------------------------
void LC1024ByteWrite(unsigned char ucAdd2, unsigned char ucAdd1,
unsigned char ucAdd0, unsigned char ucByte) {
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);
}
//------------------------------------------------------------------------------
unsigned char LC1024ReadMode(void) {
unsigned char ucRet;
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);
return ucRet;
}
//------------------------------------------------------------------------------
void LC1024ReadBegin(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0) {
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; // Dummy byte
LC1024_CLK_PULSE;
}
//------------------------------------------------------------------------------
void LC1024WriteBegin(unsigned char ucAdd2, unsigned char ucAdd1, unsigned char ucAdd0) {
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;
}
unsigned char LC1024ReadByte(void) {
unsigned char ucRet;
ON(LC1024_CLK);
ucRet = (P1 << 4);
OFF(LC1024_CLK);
ON(LC1024_CLK);
ucRet |= (P1 & 0xf);
OFF(LC1024_CLK);
return ucRet;
}
void LC1024WriteByte(unsigned char ucByte) {
P1 &= 0xf0;
P1 |= (ucByte >> 4);
LC1024_CLK_PULSE;
P1 &= 0xf0;
P1 |= (ucByte & 0xf);
LC1024_CLK_PULSE;
}
//------------------------------------------------------------------------------
void LC1024ReadWriteEnd(void) {
LC1024_SO_IN;
ON(LC1024_CS);
}
//------------------------------------------------------------------------------
void LC1024WriteMode(unsigned char ucMode) {
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;
}
//------------------------------------------------------------------------------
void LC1024Reset(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;
}
//==============================================================================
// END OF THE FILE : LC1024L4.C
//------------------------------------------------------------------------------