当前位置:   article > 正文

SPI读写Flash的时序_flash存储器读写时序

flash存储器读写时序

在使用nordic52832的SPI外设对外部Flash进行读写操作时,发现读出来的数据与写进去的数据不一致。

先看一下读写一个字节的错误示范:

  1. static uint8_t spi_tx[256],spi_rx[256],;
  2. static bool gSpiDone = false;//spi传输完成标志
  3. /**
  4. @brief SPI传输完成时的回调函数
  5. */
  6. static void spiCallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg)
  7. {
  8. gSpiDone = true;
  9. }
  10. static uint8_t SpiReadStatusReg(void)
  11. {
  12. spi_tx[0] =0x05;//状态寄存器地址
  13. gSpiDone=false;
  14. //注意这个错误示范中发送和接受的都是1个字节
  15. nrf_drv_spi_transfer(&spi_flash, spi_tx, 1, spi_rx, 1);
  16. while(!gSpiDone);//等待传输完成
  17. return spi_rx[0];
  18. }

通过上面的函数读出来的值总是零,实际上是SPI的时序搞错了,我们来重新补习SPI时序相关的知识。

下面是通过逻辑分析仪捕获的读取外部flash器件ID的正常时序图:

先拉低片选信号CS,再发送命令0XAB,再发送三个字节的dummy。读取第四个字节数据,数据就是device ID。最后拉高CS,结束一次操作。注意时钟信号总共有5个字节周期!由于SPI是全双工工作,主机发送数据的同时,也会收到从机的数据,但因为主机没有发送完成,收到的从机数据都是无效的。因此上面的SpiWriteReadByte函数需要改成如下:

  1. static uint8_t SpiReadStatusReg(void)
  2. {
  3. spi_tx[0] =0x05;//状态寄存器地址
  4. spi_tx[1] =0xFF;//发送的第二个字节是无效数据,目的是提供时序以接受从机的数据
  5. gSpiDone=false;
  6. //注意这个正确示范中发送和接受的都是2个字节
  7. nrf_drv_spi_transfer(&spi_flash, spi_tx, 2, spi_rx, 2);
  8. while(!gSpiDone);//等待传输完成
  9. return spi_rx[1];//返回的第一个字节是无效数据,第二个字节才是有效数据
  10. }

改完之后读写正常,问题解决。

另外,针对52832的SPI库函数,需要注意的是52832的nrf_drv_spi_transfer函数限制了每次读写不能超过251字节(因为nrf_drv_spi_transfer传输数据长度的类型是uint8,1字节命令+3字节地址+251字节数据=255),所以要特殊处理一下。读可以任意地址读,写不能跨页写,正常一页256字节每次都需要分成251+5两次写。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号