加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入

【LPC845月餅板】+ W25Qxx SPIFLASH驅(qū)動(dòng)起來(lái),存數(shù)據(jù)就不怕了

05/16 10:30
2576
服務(wù)支持:
技術(shù)交流群

完成交易后在“購(gòu)買成功”頁(yè)面掃碼入群,即可與技術(shù)大咖們分享疑惑和經(jīng)驗(yàn)、收獲成長(zhǎng)和認(rèn)同、領(lǐng)取優(yōu)惠和紅包等。

虛擬商品不可退

當(dāng)前內(nèi)容為數(shù)字版權(quán)作品,購(gòu)買后不支持退換且無(wú)法轉(zhuǎn)移使用。

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論
放大
電路板圖(3)
相關(guān)方案
  • 方案介紹
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

本來(lái)準(zhǔn)備移植ARM2D圖形的,例子還沒準(zhǔn)備好,下次再說(shuō)。今天就說(shuō)說(shuō)如何驅(qū)動(dòng)SPI flash吧。 LPC845月餅板上有一塊spi flash,主要是為了存儲(chǔ)一些資源數(shù)據(jù)等等。LPC845本身flash不夠多,到時(shí)想做一些lcd顯示圖片字體的話,資源會(huì)不足。后面還會(huì)說(shuō)說(shuō)如何編寫flash的下載算法。下載算法已經(jīng)基本調(diào)好了,可以直接下載數(shù)據(jù)到flash上了。

進(jìn)入正題,下面說(shuō)一下如何驅(qū)動(dòng)spi flash。

要驅(qū)動(dòng)spiflash,首先看看原理圖,找到IO管腳,然后初始化管腳,初始化SPI。電路圖部分如下:

這里要說(shuō)明一下,LPC845只有2個(gè)SPI外設(shè)。lcd屏幕用了一個(gè)SPI0,上期WS2812燈用了一個(gè)SPI1.所以這個(gè)SPIFLASH只能和他們共用一個(gè)SPI外設(shè)了。我這里是WS2812和SPIFLASH共用SPI1在,分時(shí)復(fù)用。

下面是spi初始化部分:

void drv_spi_gpio_init(void)
{
    CLOCK_EnableClock(kCLOCK_Iocon);
    CLOCK_EnableClock(kCLOCK_Gpio0);
    CLOCK_EnableClock(kCLOCK_Gpio1);
    
    CLOCK_EnableClock(kCLOCK_Spi0);
    CLOCK_EnableClock(kCLOCK_Spi1);
    
    CLOCK_Select(kSPI0_Clk_From_MainClk);
    CLOCK_Select(kSPI1_Clk_From_MainClk);
    
    RESET_PeripheralReset(kSPI0_RST_N_SHIFT_RSTn);
    RESET_PeripheralReset(kSPI1_RST_N_SHIFT_RSTn);

    gpio_pin_config_t SPILCD_IN_config = {
        .pinDirection = kGPIO_DigitalInput,
        .outputLogic = 1U,
    };
    gpio_pin_config_t SPILCD_IOH_config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = 1U,
    };
    gpio_pin_config_t SPILCD_IOL_config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = 0U,
    };
    /* Initialize GPIO functionality on pin */
    GPIO_PinInit(GPIO, 0, 7, &SPILCD_IOL_config);//LCD_BLK
    GPIO_PinInit(GPIO, 1, 6, &SPILCD_IOH_config);//LCD_DC
    GPIO_PinInit(GPIO, 1, 7, &SPILCD_IOH_config);//LCD_RST
    GPIO_PinInit(GPIO, 1,18, &SPILCD_IOH_config);//LCD_CS
    GPIO_PinInit(GPIO, 1,19, &SPILCD_IOH_config);//LCD_CLK
    GPIO_PinInit(GPIO, 0, 6, &SPILCD_IOH_config);//LCD_MOSI
    
    GPIO_PinInit(GPIO, 1,13, &SPILCD_IOH_config);//RGB_MOSI
    
    GPIO_PinInit(GPIO, 1,8, &SPILCD_IOH_config); //FLASH_CS
    GPIO_PinInit(GPIO, 1,9, &SPILCD_IN_config); //FLASH_MISO
    GPIO_PinInit(GPIO, 0,12, &SPILCD_IOH_config);//FLASH_CLK
    GPIO_PinInit(GPIO, 0,13, &SPILCD_IOH_config);//FLASH_MOSI
    
    const uint32_t spilcd_ioc = (/* Selects pull-up function */
                              IOCON_PIO_MODE_PULLUP |
                              /* Enable hysteresis */
                              IOCON_PIO_HYS_EN |
                              /* Input not invert */
                              IOCON_PIO_INV_DI |
                              /* Disables Open-drain function */
                              IOCON_PIO_OD_DI |
                              /* Bypass input filter */
                              IOCON_PIO_SMODE_BYPASS |
                              /* IOCONCLKDIV0 */
                              IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_7,  spilcd_ioc);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_6,  spilcd_ioc);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_7,  spilcd_ioc);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_18, spilcd_ioc);    
    
    /* Enables clock for switch matrix.: enable */
    const uint32_t SPI_LCD_CLK = (/* Selects pull-up function */
                                    IOCON_PIO_MODE_PULLUP |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_19, SPI_LCD_CLK);

    const uint32_t SPI_LCD_MOSI = (/* Selects pull-up function */
                                    IOCON_PIO_MODE_PULLUP |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_6, SPI_LCD_MOSI);
    
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_13, SPI_LCD_MOSI);  //RGB_IO=MOSI
    
    const uint32_t SPI_MISO = (/* Selects pull-up function */
                                    0 |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_9, SPI_MISO);   //f_miso

    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_8,   spilcd_ioc);    //f_cs
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_12,  spilcd_ioc);   //f_clk
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_13,  spilcd_ioc);   //f_mosi
    
    CLOCK_EnableClock(kCLOCK_Swm);
    
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI0_SCK,   kSWM_PortPin_P1_19);
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI0_MOSI,  kSWM_PortPin_P0_6);
    
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI,  kSWM_PortPin_P1_13);
    
    /* Disable clock for switch matrix. */
    CLOCK_DisableClock(kCLOCK_Swm);
    
    spi_master_config_t userConfig = {0};
    uint32_t srcFreq               = 0U;
    /* Note: The slave board using interrupt way, slave will spend more time to write data
     *       to TX register, to prevent TX data missing in slave, we will add some delay between
     *       frames and capture data at the second edge, this operation will make the slave
     *       has more time to prapare the data.
     */
    
    SPI_MasterGetDefaultConfig(&userConfig);
    userConfig.baudRate_Bps           = 30000000;
    userConfig.sselNumber             = kSPI_Ssel0Assert;
    userConfig.clockPolarity          = kSPI_ClockPolarityActiveHigh;
    userConfig.clockPhase             = kSPI_ClockPhaseFirstEdge;
    userConfig.direction              = kSPI_MsbFirst;
    userConfig.delayConfig.preDelay   = 0x0U;
    userConfig.delayConfig.postDelay  = 0x0U;
    userConfig.delayConfig.frameDelay = 0x0U;
    userConfig.delayConfig.transferDelay = 0x0U;
    srcFreq                           = CLOCK_GetFreq(kCLOCK_MainClk);
    SPI_MasterInit(SPI0, &userConfig, srcFreq);
    
    userConfig.baudRate_Bps           = 6000000;
    SPI_MasterInit(SPI1, &userConfig, srcFreq);

}




SPI_Type * spi_table[2]=
{
    SPI0,
    SPI1,
};

void spi_pre_h(void)
{
    CLOCK_EnableClock(kCLOCK_Swm);
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MISO,  kSWM_PortPin_P1_9);  //F_MISO
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI,  kSWM_PortPin_P0_13); //F_MOSI
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_SCK ,  kSWM_PortPin_P0_12); //F_CLK
    CLOCK_DisableClock(kCLOCK_Swm);
    SPI_MasterSetBaudRate(SPI1,30000000, CLOCK_GetFreq(kCLOCK_MainClk));
}

void spi_pre_l(void)
{
    CLOCK_EnableClock(kCLOCK_Swm);
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI,  kSWM_PortPin_P1_13); //RGB_IO
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MISO,  0XFF);  //
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_SCK ,  0XFF);  //
    CLOCK_DisableClock(kCLOCK_Swm);
    SPI_MasterSetBaudRate(SPI1,6000000, CLOCK_GetFreq(kCLOCK_MainClk));
}

void spi_writebyte(uint8_t index,uint8_t TxData)
{
    spi_table[index]->TXDATCTL = TxData | 0X077E0000;
    while ((spi_table[index]->STAT & SPI_STAT_TXRDY_MASK) == 0U){;}
}

uint8_t spi_readbyte(uint8_t index)
{
    uint8_t re;
    spi_table[index]->TXDATCTL = 0xff | 0X073E0000;
    while ((spi_table[index]->STAT & SPI_STAT_RXRDY_MASK) == 0U){;}
    re = spi_table[index]->RXDAT & 0XFF;
    return re;
}


uint8_t spi_writebuff(uint8_t index,uint8_t *buff,uint32_t len)
{
    volatile uint32_t i;
    for(i=0; i<len; i++)
    {
        spi_writebyte(index,buff[i]);
    }    
    return 0;
}

uint8_t spi_readbuff(uint8_t index,uint8_t *buff,uint32_t len)
{
    volatile uint32_t i;
    for(i=0; i<len; i++)
    {
        buff[i] = spi_readbyte(index);
    }   
    return 0;
}

void spi_write_read(uint8_t index,uint8_t * wbuf,uint32_t wl,uint8_t * rbuf,uint32_t rl)
{
    if((wbuf != NULL) && (wl != 0))
    {
        while(wl--)
        {
            spi_writebyte(index,*wbuf++);
        }
    }

    if((rbuf != NULL) && (rl != 0))
    {
        while(rl--)
        {
            *rbuf++ = spi_readbyte(index);
        }
    }
}

W25QXX的驅(qū)動(dòng)是以前寫好的,直接拿來(lái)用,主要實(shí)現(xiàn)了SPI讀寫接口就行。

下面對(duì)W25QXX flash讀寫測(cè)試一下。

主要測(cè)試代碼:

    for (int i = 0; i < BUFFER_SIZE; i++)
    {
        txBuffer[i] = i % 256;
        rxBuffer[i] = 0U;
    }
    DbgConsole_Printf("W25QXX Erase Chip.rn");
    W25QXX_EraseChip();
    DbgConsole_Printf("W25QXX Read Data.rn");
    W25QXX_Read(0,rxBuffer,64);
    for (int i = 0; i < BUFFER_SIZE; i++)
    {
        DbgConsole_Printf("%02X ",rxBuffer[i]);
    } 
    DbgConsole_Printf("W25QXX Write Data.rn");
    W25QXX_Write_NoCheck(0,txBuffer,BUFFER_SIZE);
    DbgConsole_Printf("W25QXX Read Data to Check.rn");
    for (int j = 0; j < BUFFER_SIZE; j++)
    {
        W25QXX_Read(0 + j*BUFFER_SIZE,rxBuffer,64);
        for (int i = 0; i < BUFFER_SIZE; i++)
        {
            DbgConsole_Printf("%02X ",rxBuffer[i]);
        }
        DbgConsole_Printf("n");
    }

通過(guò)串口觀察數(shù)據(jù),寫入和讀出一致。

好了,本次到此結(jié)束。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
CM200C32.768KDZF-UT 1 Citizen Finedevice Co Ltd Parallel - Fundamental Quartz Crystal, 0.032768MHz Nom, ROHS COMPLIANT, PLASTIC, SMD, 4 PIN
$1.17 查看
R38-32.768-12.5 1 Raltron Electronics Corporation Parallel - Fundamental Quartz Crystal, 0.032768MHz Nom, HALOGEN FREE, ROHS AND REACH COMPLIANT PACKAGE-2
$0.06 查看
FM25CL64B-GTR 1 Cypress Semiconductor Memory Circuit, 8KX8, CMOS, PDSO8, SOIC-8

ECAD模型

下載ECAD模型
$4.24 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜