在线时间3068 小时
UID3327992
注册时间2018-4-5
NXP金币11402
TA的每日心情 | 擦汗 15 分钟前 |
---|
签到天数: 2406 天 连续签到: 115 天 [LV.Master]伴坛终老
版主
  
- 积分
- 22340
- 最后登录
- 2025-8-24
|
本来准备移植ARM2D图形的,例子还没准备好,下次再说。今天就说说如何驱动SPI flash吧。 LPC845月饼板上有一块spi flash,主要是为了存储一些资源数据等等。LPC845本身flash不够多,到时想做一些lcd显示图片字体的话,资源会不足。后面还会说说如何编写flash的下载算法。下载算法已经基本调好了,可以直接下载数据到flash上了。
进入正题,下面说一下如何驱动spi flash。
要驱动spiflash,首先看看原理图,找到IO管脚,然后初始化管脚,初始化SPI。电路图部分如下:
这里要说明一下,LPC845只有2个SPI外设。lcd屏幕用了一个SPI0,上期WS2812灯用了一个SPI1.所以这个SPIFLASH只能和他们共用一个SPI外设了。我这里是WS2812和SPIFLASH共用SPI1在,分时复用。
下面是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的驱动是以前写好的,直接拿来用,主要实现了SPI读写接口就行。
下面对W25QXX flash读写测试一下。
主要测试代码:
- for (int i = 0; i < BUFFER_SIZE; i++)
- {
- txBuffer[i] = i % 256;
- rxBuffer[i] = 0U;
- }
- DbgConsole_Printf("W25QXX Erase Chip.\r\n");
- W25QXX_EraseChip();
- DbgConsole_Printf("W25QXX Read Data.\r\n");
- W25QXX_Read(0,rxBuffer,64);
- for (int i = 0; i < BUFFER_SIZE; i++)
- {
- DbgConsole_Printf("%02X ",rxBuffer[i]);
- }
- DbgConsole_Printf("W25QXX Write Data.\r\n");
- W25QXX_Write_NoCheck(0,txBuffer,BUFFER_SIZE);
- DbgConsole_Printf("W25QXX Read Data to Check.\r\n");
- 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");
- }
复制代码
通过串口观察数据,写入和读出一致。
好了,本次到此结束。
下一期会讲如何写spi flash下载算法。
|
评分
-
查看全部评分
|