【华大测评】HC32F460测试QSPI通讯测试
本帖最后由 binoo7 于 2021-2-8 15:39 编辑@小跑堂
第一期测评用了GPIO,这次我们来说说QSPI。其实前几天写过一篇原创的**就是关于QSPI的,那篇**是对华大HC32F460的简介及配置的一个说明。
今天是来做一个QSPI的实验,在做实验之前,再说一下关于华大QSPI的通讯,
首先,与其他的芯片的QSPI类似,华大的QSPI支持的通讯方式有两种,按照手册的说法,
一种叫做直接通讯,
一种叫做ROM映射,
这两个通讯方式有什么区别呢?
首先说ROM映射,这方面的**我找到的资料比较少,只能根据自己的实验过程理解和大家做一个分享,还望大家海涵。
ROM映射是把片外的flash映射到内存中,可以和读取内存类似的访问片外的flash,
在访问的时候有多种的访问方式:
•支持多种读取方式
a.标准读/快速读
b.二线式输出快速读取/二线式输入输出快速读取
c.四线式输出快速读取/四线式输入输出快速读取
•自由设置指令
•数量可调的虚拟周期
•16字节的预读取功能
•状态查询功能
•SPI总线周期延长功能
•XIP控制功能
而且,相关的寄存器也比较丰富
几乎是除了直接通讯指令寄存器以外的,他都可以设置了
ROM映射的好处是,读取数据是硬件自己完成的,不需要额外的在写读取的函数,这样直接访问响应的地址,就可以读取到片外的存储的数据了
如下图所示
看到红色方框内的内容了吧,这就是关键的地方,内存映射的起始地址是固定的,也就是可以访问这么多的内存空间,
在应用中这样就可以直接读取到地址中的数据了
看到图片中绿色的部分了吗?读取数据真的挺方便的
写入数据不可以直接对该地址进行赋值,需要通过特定的函数进行写入的操作。
是不是感觉很神奇呢,和SPI一比是不是有很大的优势啊
写入和读取都可以通过4根数据线同时进行,这样读写的速度会大大提高说完了ROM映射的功能,下面说说直接通讯的方式。
QSPI 可以通过自动将 MCU 的外部 ROM 读取总线周期转换为 QSPI 总线周期来对串行闪存进行读取。
但串行闪存还有很多不同的追加功能,诸如 ID 信息读取,擦除,写入及状态信息读取等。
这些功能并没有一套标准的指令来进行设置,并且随着串行闪存新功能的迅速增加,硬件层面上的对应变得愈发的困难。
针对这种情况,QSPI 提供了直接通信模式,用户可通过软件直接对串行闪存进行控制。
由此模式软件可以产生任意所需的 QSPI 总线周期。
将 QSCR 寄存器的 DCOME 位设成 1 可以进入直接通信模式。一旦进入直接通信模式,将无法进行通常的闪存读取操作,
如果要进行常规的闪存读取,需要将 DCOME位清零退出直接通信模式。
注意:
- 如果处于 XIP 模式,则需要先退出 XIP 模式再启动直接通信模式。
- 在直接通信模式下是无法对 QSCR 和 QSDCOM 以外的寄存器进行写操作的。对其他寄存器
的写操作将会退出直接通信模式。
下面看一下实验的代码,方式通过的是直接内存映射的方式来做的实验
#include "hc32_ddl.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* LED0 Port/Pin definition */
#define LED0_PORT (PortE)
#define LED0_PIN (Pin06)
#define LED0_ON() (PORT_SetBits(LED0_PORT, LED0_PIN))
#define LED0_OFF() (PORT_ResetBits(LED0_PORT, LED0_PIN))
#define LED0_TOGGLE() (PORT_Toggle(LED0_PORT, LED0_PIN))
/* LED1 Port/Pin definition */
#define LED1_PORT (PortA)
#define LED1_PIN (Pin07)
#define LED1_ON() (PORT_SetBits(LED1_PORT, LED1_PIN))
#define LED1_OFF() (PORT_ResetBits(LED1_PORT, LED1_PIN))
#define LED1_TOGGLE() (PORT_Toggle(LED1_PORT, LED1_PIN))
/* KEY0 Port/Pin definition */
#define KEY0_PORT (PortD)
#define KEY0_PIN (Pin03)
/* QSPCK Port/Pin definition */
#define QSPCK_PORT (PortC)
#define QSPCK_PIN (Pin06)
/* QSNSS Port/Pin definition */
#define QSNSS_PORT (PortC)
#define QSNSS_PIN (Pin07)
/* QSIO0 Port/Pin definition */
#define QSIO0_PORT (PortD)
#define QSIO0_PIN (Pin08)
/* QSIO1 Port/Pin definition */
#define QSIO1_PORT (PortD)
#define QSIO1_PIN (Pin09)
/* QSIO2 Port/Pin definition */
#define QSIO2_PORT (PortD)
#define QSIO2_PIN (Pin10)
/* QSIO3 Port/Pin definition */
#define QSIO3_PORT (PortD)
#define QSIO3_PIN (Pin11)
/* QSPI memory bus address definition */
#define QSPI_BUS_ADDRESS (0x98000000ul)
/* FLASH parameters definition */
#define FLASH_PAGE_SIZE (0x100u)
#define FLASH_SECTOR_SIZE (0x1000u)
#define FLASH_MAX_ADDR (0x800000ul)
#define FLASH_DUMMY_BYTE_VALUE (0xffu)
#define FLASH_BUSY_BIT_MASK (0x01u)
/* FLASH instruction definition */
#define FLASH_INSTR_WRITE_ENABLE (0x06u)
#define FLASH_INSTR_PAGE_PROGRAM (0x02u)
#define FLASH_INSTR_ERASE_4KB_SECTOR (0x20u)
#define FLASH_INSTR_ERASE_CHIP (0xC7u)
#define FLASH_INSTR_READ_SR1 (0x05u)
#define FLASH_INSTR_READ_SR2 (0x35u)
#define FLASH_INSTR_READ_SR3 (0x15u)
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
static uint8_t u8ExIntFlag = 0u;
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
*******************************************************************************
** \brief ExtInt3 callback function
**
** \param None
**
** \retval None
**
******************************************************************************/
void ExtInt03_Callback(void)
{
if (Set == EXINT_Irq**Get(ExtiCh03))
{
u8ExIntFlag = 1u;
EXINT_Irq**Clr(ExtiCh03);
}
}
/**
*******************************************************************************
** \brief KEY0(SW2) init function
**
** \param None
**
** \retval None
**
******************************************************************************/
void Sw2_Init(void)
{
stc_port_init_t stcPortInit;
stc_exint_config_t stcExtiConfig;
stc_irq_regi_conf_t stcIrqRegiConf;
/* configure structure initialization */
MEM_ZERO_STRUCT(stcPortInit);
MEM_ZERO_STRUCT(stcExtiConfig);
MEM_ZERO_STRUCT(stcIrqRegiConf);
/* Set PD03 as External Int Ch.3 input */
stcPortInit.enExInt = Enable;
PORT_Init(KEY0_PORT, KEY0_PIN, &stcPortInit);
stcExtiConfig.enExitCh = ExtiCh03;
/* Filter setting */
stcExtiConfig.enFilterEn = Enable;
stcExtiConfig.enFltClk = Pclk3Div8;
/* Both edge */
stcExtiConfig.enExtiLvl = ExIntFallingEdge;
EXINT_Init(&stcExtiConfig);
/* Select External Int Ch.3 */
stcIrqRegiConf.enIntSrc = INT_PORT_EIRQ3;
/* Register External Int to Vect.No.007 */
stcIrqRegiConf.enIRQn = Int007_IRQn;
/* Callback function */
stcIrqRegiConf.pfnCallback = &ExtInt03_Callback;
/* Registration IRQ */
enIrqRegistration(&stcIrqRegiConf);
/* Clear pending */
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
/* Set priority */
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);
/* Enable NVIC */
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}
/**
*******************************************************************************
** \brief QSPI flash init function
**
** \param None
**
** \retval None
**
******************************************************************************/
void QspiFlash_Init(void)
{
stc_qspi_init_t stcQspiInit;
/* configuration structure initialization */
MEM_ZERO_STRUCT(stcQspiInit);
/* Configuration peripheral clock */
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_QSPI, Enable);
/* Configuration QSPI pin */
PORT_SetFunc(QSPCK_PORT, QSPCK_PIN, Func_Qspi, Disable);
PORT_SetFunc(QSNSS_PORT, QSNSS_PIN, Func_Qspi, Disable);
PORT_SetFunc(QSIO0_PORT, QSIO0_PIN, Func_Qspi, Disable);
PORT_SetFunc(QSIO1_PORT, QSIO1_PIN, Func_Qspi, Disable);
PORT_SetFunc(QSIO2_PORT, QSIO2_PIN, Func_Qspi, Disable);
PORT_SetFunc(QSIO3_PORT, QSIO3_PIN, Func_Qspi, Disable);
/* Configuration QSPI structure */
stcQspiInit.enClkDiv = QspiHclkDiv3;
stcQspiInit.enSpiMode = QspiSpiMode3;
stcQspiInit.enBusCommMode = QspiBusModeRomAccess;
stcQspiInit.enPrefetchMode = QspiPrefetchStopComplete;
stcQspiInit.enPrefetchFuncEn = Disable;
stcQspiInit.enQssnValidExtendTime = QspiQssnValidExtendSck32;
stcQspiInit.enQssnIntervalTime = QspiQssnIntervalQsck8;
stcQspiInit.enQsckDutyCorr = QspiQsckDutyCorrHalfHclk;
stcQspiInit.enVirtualPeriod = QspiVirtualPeriodQsck6;
stcQspiInit.enWpPinLevel = QspiWpPinOutputHigh;
stcQspiInit.enQssnSetupDelayTime = QspiQssnSetupDelay1Dot5Qsck;
stcQspiInit.enQssnHoldDelayTime = QspiQssnHoldDelay1Dot5Qsck;
stcQspiInit.enFourByteAddrReadEn = Disable;
stcQspiInit.enAddrWidth = QspiAddressByteThree;
stcQspiInit.stcCommProtocol.enReadMode = QspiReadModeFourWiresIO;
stcQspiInit.stcCommProtocol.enTransInstrProtocol = QspiProtocolExtendSpi;
stcQspiInit.stcCommProtocol.enTransAddrProtocol = QspiProtocolExtendSpi;
stcQspiInit.stcCommProtocol.enReceProtocol = QspiProtocolExtendSpi;
stcQspiInit.u8RomAccessInstr = QSPI_3BINSTR_FOUR_WIRES_IO_READ;
QSPI_Init(&stcQspiInit);
}
/**
*******************************************************************************
** \brief QSPI flash write enable function
**
** \param None
**
** \retval None
**
******************************************************************************/
void QspiFlash_WriteEnable(void)
{
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(FLASH_INSTR_WRITE_ENABLE);
QSPI_ExitDirectCommMode();
}
/**
*******************************************************************************
** \brief QSPI flash wait for write operation end function
**
** \param None
**
** \retval Ok Flash internal operation finish
** \retval ErrorTimeout Flash internal operation timeout
**
******************************************************************************/
en_result_t QspiFlash_WaitForWriteEnd(void)
{
en_result_t enRet = Ok;
uint8_t u8Status = 0u;
uint32_t u32Timeout;
stc_clk_freq_t stcClkFreq;
CLK_GetClockFreq(&stcClkFreq);
u32Timeout = stcClkFreq.sysclkFreq / 1000u;
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(FLASH_INSTR_READ_SR1);
do
{
u8Status = QSPI_ReadDirectCommValue();
u32Timeout--;
} while ((u32Timeout != 0u) &&
((u8Status & FLASH_BUSY_BIT_MASK) == FLASH_BUSY_BIT_MASK));
if (FLASH_BUSY_BIT_MASK == u8Status)
{
enRet = ErrorTimeout;
}
QSPI_ExitDirectCommMode();
return enRet;
}
/**
*******************************************************************************
** \brief QSPI flash page write program function
**
** \param u32Addr Valid flash address
**
** \param pData Pointer to send data buffer
**
** \param len Send data length
**
** \retval Error Page write program failed
** \retval Ok Page write program success
**
******************************************************************************/
en_result_t QspiFlash_WritePage(uint32_t u32Addr, const uint8_t pData[], uint16_t len)
{
en_result_t enRet = Ok;
uint16_t u16Index = 0u;
if ((u32Addr > FLASH_MAX_ADDR) || (NULL == pData) || (len > FLASH_PAGE_SIZE))
{
enRet = Error;
}
else
{
QspiFlash_WriteEnable();
/* Send data to flash */
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(FLASH_INSTR_PAGE_PROGRAM);
QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF0000ul) >> 16));
QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF00u) >> 8));
QSPI_WriteDirectCommValue((uint8_t)(u32Addr & 0xFFu));
while (len--)
{
QSPI_WriteDirectCommValue(pData);
u16Index++;
}
QSPI_ExitDirectCommMode();
/* Wait for flash idle */
enRet = QspiFlash_WaitForWriteEnd();
}
return enRet;
}
/**
*******************************************************************************
** \brief QSPI flash erase 4Kb sector function
**
** \param u32Addr Valid flash address
**
** \retval Error Sector erase failed
** \retval Ok Sector erase success
**
******************************************************************************/
en_result_t QspiFlash_Erase4KbSector(uint32_t u32Addr)
{
en_result_t enRet = Ok;
if (u32Addr >= FLASH_MAX_ADDR)
{
enRet = Error;
}
else
{
QspiFlash_WriteEnable();
/* Send instruction to flash */
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(FLASH_INSTR_ERASE_4KB_SECTOR);
QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF0000ul) >> 16));
QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF00u) >> 8));
QSPI_WriteDirectCommValue((uint8_t)(u32Addr & 0xFFu));
QSPI_ExitDirectCommMode();
/* Wait for flash idle */
enRet = QspiFlash_WaitForWriteEnd();
}
return enRet;
}
/**
*******************************************************************************
** \brief QSPI flash erase chip function
**
** \param None
**
** \retval None
**
******************************************************************************/
void QspiFlash_EraseChip(void)
{
QspiFlash_WriteEnable();
/* Send instruction to flash */
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(FLASH_INSTR_ERASE_CHIP);
QSPI_ExitDirectCommMode();
/* Wait for flash idle */
QspiFlash_WaitForWriteEnd();
}
/**
*******************************************************************************
** \brief QSPI flash read status register function
**
** \param u8Reg Need to get status register
** \arg FLASH_INSTR_READ_SR1 Status register 1
** \arg FLASH_INSTR_READ_SR2 Status register 2
** \arg FLASH_INSTR_READ_SR3 Status register 3
**
** \retval uint8_t Current register value
**
******************************************************************************/
uint8_t QspiFlash_ReadStatusRegister(uint8_t u8Reg)
{
uint8_t regSta = 0u;
QSPI_EnterDirectCommMode();
QSPI_WriteDirectCommValue(u8Reg);
regSta = QSPI_ReadDirectCommValue();
QSPI_ExitDirectCommMode();
return regSta;
}
/**
*******************************************************************************
** \brief System clock init function
**
** \param None
**
** \retval None
**
******************************************************************************/
void SystemClk_Init(void)
{
stc_clk_sysclk_cfg_t stcSysClkCfg;
stc_clk_xtal_cfg_t stcXtalCfg;
stc_clk_mpll_cfg_t stcMpllCfg;
MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcXtalCfg);
MEM_ZERO_STRUCT(stcMpllCfg);
/* Set bus clk div. */
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1; // 168MHz
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;// 84MHz
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;// 168MHz
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;// 84MHz
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;// 42MHz
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;// 42MHz
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;// 84MHz
CLK_SysClkConfig(&stcSysClkCfg);
/* Switch system clock source to MPLL. */
/* Use Xtal as MPLL source. */
stcXtalCfg.enMode = ClkXtalModeOsc;
stcXtalCfg.enDrv = ClkXtalLowDrv;
stcXtalCfg.enFastStartup = Enable;
CLK_XtalConfig(&stcXtalCfg);
CLK_XtalCmd(Enable);
/* MPLL config. */
stcMpllCfg.pllmDiv = 1u;
stcMpllCfg.plln = 42u;
stcMpllCfg.PllpDiv = 2u;
stcMpllCfg.PllqDiv = 2u;
stcMpllCfg.PllrDiv = 2u;
CLK_SetPllSource(ClkPllSrcXTAL);
CLK_MpllConfig(&stcMpllCfg);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_4);
EFM_Lock();
/* Enable MPLL. */
CLK_MpllCmd(Enable);
/* Wait MPLL ready. */
while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{
}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);
}
/**
*******************************************************************************
** \briefmain function for QSPI four wire i/o fast read function
**
** \param None
**
** \retval int32_t Return value, if needed
**
******************************************************************************/
int32_t main(void)
{
uint32_t flashAddr = 0u;
uint8_t *pFlashReadAddr;
uint16_t bufferLen = 0u;
char txBuffer[] = "QSPI read and write flash example: Welcome to use HDSC micro chip";
stc_port_init_t stcPortInit;
stc_qspi_comm_protocol_t stcQspiCommProtocol;
/* configure structure initialization */
MEM_ZERO_STRUCT(stcPortInit);
MEM_ZERO_STRUCT(stcQspiCommProtocol);
/* Configure system clock frequency */
SystemClk_Init();
/* LED0 Port/Pin initialization */
LED0_OFF();
stcPortInit.enPinMode = Pin_Mode_Out;
PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);
/* LED1 Port/Pin initialization */
LED1_OFF();
stcPortInit.enPinMode = Pin_Mode_Out;
PORT_Init(LED1_PORT, LED1_PIN, &stcPortInit);
/* Key0 Port/Pin initialization */
Sw2_Init();
/* Flash initialization */
QspiFlash_Init();
/* Get tx buffer length */
bufferLen = (uint16_t)sizeof(txBuffer);
while (1)
{
if (1u == u8ExIntFlag)
{
u8ExIntFlag = 0u;
// LED0_OFF();
// LED1_OFF();
/* Switch to standard read mode */
stcQspiCommProtocol.enReadMode = QspiReadModeStandard;
QSPI_CommProtocolConfig(&stcQspiCommProtocol);
/* Erase sector */
QspiFlash_Erase4KbSector(flashAddr);
/* Write data to flash */
QspiFlash_WritePage(flashAddr, (uint8_t*)&txBuffer, sizeof(txBuffer));
/* Switch to four wire i/o fast read mode */
stcQspiCommProtocol.enReadMode = QspiReadModeFourWiresIO;
QSPI_CommProtocolConfig(&stcQspiCommProtocol);
/* Pointer to flash address map */
pFlashReadAddr = (uint8_t *)((uint32_t)QSPI_BUS_ADDRESS + flashAddr);
/* Compare txBuffer and flash */
if (memcmp(txBuffer, pFlashReadAddr, (uint32_t)bufferLen) != 0)
{
LED0_TOGGLE();
}
else
{
LED1_TOGGLE();
}
/* Flash address offset */
flashAddr += FLASH_SECTOR_SIZE;
if (flashAddr >= FLASH_MAX_ADDR)
{
flashAddr = 0u;
}
}
}
}
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
在给的例程中是判断读取到的数据和写入的数据是否一样来点亮LED0或者LED1,这样的话应用起来效果不明显,因为LED1如果点亮了,通过多次按键不会看出来有什么区别,因为都是同一个灯在点亮,所以我把程序作了一点修改,通过按键来翻转灯的亮灭,这样的话就可以判断出来是什么问题,而且显示的效果也比常亮好
下面是实验的图片
这个是上电后的状态,一直在等待按键按下,所以没有灯点亮
这是按键按下后,判断读取到的数据和写入的数据是一样的,点亮了这个灯,如果再次按下的话这个灯会熄灭
好了,今天就到这里,以后看有什么新的实验,我再发上来和大家一起分享,关于代码中如果有哪里不清楚的可以在本帖下方留言,我看到后会及时回复大家
如果连接spiram的话是否可以用于xip的自动写入 wangshujun 发表于 2021-2-8 15:52
如果连接spiram的话是否可以用于xip的自动写入
没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的 binoo7 发表于 2021-2-8 16:38
没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的 ...
没有深入了解底层的实现,不过esp32对于挂在到qspi的ram做了处理,可以在应用中直接当作堆来用,这个体验非常好,我猜测是在编译器底层做的处理,而不是芯片自身功能,底层的程序拦截对spi区域的写访问,处理成qspi指令,读取就直接用xip来实现了 还没了解过这个接口呢。看看。 只用过SPI QSPI是什么?
SPI协议其实是包括:Standard SPI、Dual SPI和Queued SPI三种协议接口,分别对应3-wire, 4-wire, 6-wire。
(1)通常我们说的SPI就是Standard SPI,有4根信号线,分别为CLK、CS、MOSI和MISO。数据线工作在全双工。
(2)Dual SPI,它只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。
(3)类似的,还可以扩展,与也是针对SPI Flash,Qual SPI Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit
而QSPI就是Queued SPI的简写。 是不是速度比较快。 •支持多种读取方式
a.标准读/快速读
b.二线式输出快速读取/二线式输入输出快速读取
c.四线式输出快速读取/四线式输入输出快速读取 什么叫Qspi 一直没有搞明白什么叫QSPI 勇敢的大白菜 发表于 2021-2-24 09:36
什么叫Qspi
QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。 勇者无惧你和我 发表于 2021-2-24 09:44
一直没有搞明白什么叫QSPI
QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。{:lol:} 怎么读取数据?直接操作地址吗?怎么发送地址? 这个例程接了W25Q128,根本不能用,惧入惧入 感谢楼主分享,不错的一次体验。 感谢楼主的分享,不错的一次体验活动,棒棒的。
pzljun 发表于 2021-4-1 11:26
这个例程接了W25Q128,根本不能用,惧入惧入
128需要改配置文件,没事儿的 这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正确的数 pzljun 发表于 2021-4-2 16:04
这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正 ...
哈哈,这个就是后期需要改进的地方了,能做到这样也挺不容易了