[综合信息]

【华大测评】HC32F460测试QSPI通讯测试

[复制链接]
10294|51
手机看帖
扫描二维码
随时随地手机跟帖
binoo7|  楼主 | 2021-2-8 15:25 | 显示全部楼层 |阅读模式
本帖最后由 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控制功能
而且,相关的寄存器也比较丰富
364276020e402b999c.png
几乎是除了直接通讯指令寄存器以外的,他都可以设置了
ROM映射的好处是,读取数据是硬件自己完成的,不需要额外的在写读取的函数,这样直接访问响应的地址,就可以读取到片外的存储的数据了
如下图所示
781086020e4862bf77.png
看到红色方框内的内容了吧,这就是关键的地方,内存映射的起始地址是固定的,也就是可以访问这么多的内存空间,
在应用中这样就可以直接读取到地址中的数据了
412536020e4f574371.png
看到图片中绿色的部分了吗?读取数据真的挺方便的
写入数据不可以直接对该地址进行赋值,需要通过特定的函数进行写入的操作。
是不是感觉很神奇呢,和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 [in] 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 [in] 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 [in] 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 [in] 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 [in] 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 [in] u32Addr                     Valid flash address
**
** \param [in] pData                       Pointer to send data buffer
**
** \param [in] 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]);
           u16Index++;
        }
        QSPI_ExitDirectCommMode();
        /* Wait for flash idle */
        enRet = QspiFlash_WaitForWriteEnd();
    }

    return enRet;
}

/**
*******************************************************************************
** \brief QSPI flash erase 4Kb sector function
**
** \param [in] 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 [in] 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 [in] 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 [in] 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);
}

/**
*******************************************************************************
** \brief  main function for QSPI four wire i/o fast read function
**
** \param [in] 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[0], 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如果点亮了,通过多次按键不会看出来有什么区别,因为都是同一个灯在点亮,所以我把程序作了一点修改,通过按键来翻转灯的亮灭,这样的话就可以判断出来是什么问题,而且显示的效果也比常亮好
下面是实验的图片
980966020e6bc4ac66.png
这个是上电后的状态,一直在等待按键按下,所以没有灯点亮
802576020e6e89c0a7.png
这是按键按下后,判断读取到的数据和写入的数据是一样的,点亮了这个灯,如果再次按下的话这个灯会熄灭
好了,今天就到这里,以后看有什么新的实验,我再发上来和大家一起分享,关于代码中如果有哪里不清楚的可以在本帖下方留言,我看到后会及时回复大家



使用特权

评论回复
wangshujun| | 2021-2-8 15:52 | 显示全部楼层
如果连接spiram的话是否可以用于xip的自动写入

使用特权

评论回复
binoo7|  楼主 | 2021-2-8 16:38 | 显示全部楼层
wangshujun 发表于 2021-2-8 15:52
如果连接spiram的话是否可以用于xip的自动写入

没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的

使用特权

评论回复
wangshujun| | 2021-2-18 10:31 | 显示全部楼层
binoo7 发表于 2021-2-8 16:38
没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的 ...

没有深入了解底层的实现,不过esp32对于挂在到qspi的ram做了处理,可以在应用中直接当作堆来用,这个体验非常好,我猜测是在编译器底层做的处理,而不是芯片自身功能,底层的程序拦截对spi区域的写访问,处理成qspi指令,读取就直接用xip来实现了

使用特权

评论回复
zhuotuzi| | 2021-2-22 23:43 | 显示全部楼层
还没了解过这个接口呢。看看。

使用特权

评论回复
幸福小强| | 2021-2-23 22:40 | 显示全部楼层
只用过SPI

使用特权

评论回复
幸福小强| | 2021-2-23 22:41 | 显示全部楼层
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的简写。

使用特权

评论回复
天灵灵地灵灵| | 2021-2-23 22:50 | 显示全部楼层
是不是速度比较快。

使用特权

评论回复
两只袜子| | 2021-2-24 09:15 | 显示全部楼层
•  支持多种读取方式
a.标准读/快速读
b.二线式输出快速读取/二线式输入输出快速读取
c.四线式输出快速读取/四线式输入输出快速读取

使用特权

评论回复
勇敢的大白菜| | 2021-2-24 09:36 | 显示全部楼层
什么叫Qspi

使用特权

评论回复
一直没有搞明白什么叫QSPI

使用特权

评论回复
binoo7|  楼主 | 2021-2-24 13:00 | 显示全部楼层

QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。

使用特权

评论回复
binoo7|  楼主 | 2021-2-24 13:01 | 显示全部楼层
勇者无惧你和我 发表于 2021-2-24 09:44
一直没有搞明白什么叫QSPI

QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。

使用特权

评论回复
starforeye| | 2021-3-27 11:20 | 显示全部楼层
怎么读取数据?直接操作地址吗?怎么发送地址?

使用特权

评论回复
pzljun| | 2021-4-1 11:26 | 显示全部楼层
这个例程接了W25Q128,根本不能用,惧入惧入

使用特权

评论回复
单片小菜| | 2021-4-1 16:10 | 显示全部楼层
感谢楼主分享,不错的一次体验。

使用特权

评论回复
里面有晴雨| | 2021-4-1 17:31 | 显示全部楼层
感谢楼主的分享,不错的一次体验活动,棒棒的。

使用特权

评论回复
binoo7|  楼主 | 2021-4-2 13:24 | 显示全部楼层
pzljun 发表于 2021-4-1 11:26
这个例程接了W25Q128,根本不能用,惧入惧入

128需要改配置文件,没事儿的

使用特权

评论回复
评论
pzljun 2021-4-2 16:02 回复TA
改哪里?改出来看看呀 
pzljun| | 2021-4-2 16:04 | 显示全部楼层
这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正确的数

使用特权

评论回复
binoo7|  楼主 | 2021-4-2 16:30 | 显示全部楼层
pzljun 发表于 2021-4-2 16:04
这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正 ...

哈哈,这个就是后期需要改进的地方了,能做到这样也挺不容易了

使用特权

评论回复
评论
pzljun 2021-4-2 16:59 回复TA
谁改进?厂家还是用户? 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

454

帖子

8

粉丝