打印
[资料分享与下载]

SPI读写W25Q32

[复制链接]
3064|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
大苏牙|  楼主 | 2015-7-30 16:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本次所做实验为SPI读写开发板上的spiflash器件(W25Q32),可以实现SPI主机的简单应用,更复杂的论坛里面已经有大神发过了。

本次实验实现功能为:
1.通过SPI擦除W25Q32上的数据。程序只实现的简单的擦出,还有许多擦除指令不一一再试,有兴趣的可以调试一下;
2.通过SPI向W25Q32写入一个数组的数据,即从00地址开始的20给数据。
3.通过SPI读取W25Q32中从00地址开始的20给数据
4.读写的数据会通过串口显示,并且在成功读写后会使LED点亮。

程序如下:

主程序:


int  main (void)
{

     INT8U spiid,i = 0;

     SystemCoreClockUpdate();                                            /* 时钟配置                     */
     uart0Init(9600,0,0,8,1);
     printf("SPI Test Star...\r\n");
     gpioInit();                                                                   /* 管脚初始化                   */

     spiInit(SPI0_BASE_PTR , Master);                                    /* SPI0主机模式初始化           */

    spiid = flash_read_id();                                            //读ID
     printf("ID=0x%x08\r\n",spiid);

     printf("Start to erase sector 0...\r\n");
    flash_sector_erase (0x000000);                            //擦除W25Q32



     myDelay(300);                                                                   /* 延时                         */
     ledSet(0);
     printf("Start to write sector 0...\r\n");
     flash_write_sector(0x000000, SNDBUFPT, 20);                          /* 以0x0为起始地址,将WrBuf 写入 */
     myDelay(30);

     printf("Start to read sector 0...\r\n");                                                                    /* 数组里的20个数据写入芯片     */
     flash_read_data(0x000000,  RCVBUFPT,20);                            /* 以0x0为起始地址,读20个   */

     for (i = 0;i < 19;i++) {
         if (GucRdBuf != GucWrBuf ) {                              /* 若SPI读写不正确则程序D3常亮 */
            ledSet(1);
            printf("SPI ERR...\r\n");
             while (1);
         }
     }
     ledSet(2);                                                         /*  若SPI读写正确,D4常亮 */
     printf("Verify ok...\r");
     while(1) {
     };
}

SPI初始化:

void spiInit (SPI_MemMapPtr SPI,BOOLEAN bMode)
{
     SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK;                                   /* 开启SPI0                     */
                                                                         /* CPOL = 0, SCK 为低有效       */
                                                                         /* MSTR = 1, SPI 处于主模式     */
                                                                         /* LSBF = 0, MSB (位7)在先      */
                                                                         /* SPIE = 0, SPI 中断被禁止     */
                                                                         /* CPHA = 0, SCK第一个时钟沿采样*/
    SPI->C1 |= SPI_C1_SPE_MASK ;                                        /* SPI使能                      */
     SPI->C1 &= ~(1 << SPI_C1_CPHA_SHIFT);
     if(bMode == Master) {                                               /* 主模式                       */
         SPI->C1 |= SPI_C1_MSTR_MASK;
     } else {                                                            /* 从模式                       */
         SPI->C1 &= ~(1 << SPI_C1_MSTR_SHIFT);
     }
     SPI->BR |= SPI_BR_SPPR(0) ;                                         /* 时钟分频                     */
}


SPI发送一字节数据:

INT8U Send_Byte (INT8U ucdata)
{
     INT8U ucTemp;
     while((SPI0_S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK);             /* 发送前要先判断寄存器         */
     SPI0_DL = ucdata;

    while((SPI0_S & SPI_S_SPRF_MASK) != SPI_S_SPRF_MASK);               /* 接收数据有效                 */
     ucTemp = SPI0_DL;                                                    /* 清空接收标记寄存器           */
     ucTemp = ucTemp;
         return ucTemp;
}


读W25Q32状态:

uint8_t flash_read_status ( void )
{
         uint8_t status;

         SPI_FLASH_CS_LOW();                                                                                                     /* 选中SPI Flash                */
         Send_Byte(0x05);                                               
         status = Send_Byte(0xff);                                       
         SPI_FLASH_CS_HIGH();                                                                                        /* P0.2--1,CS = 1 释放SPI Flash */
         return status;                                                                                            /* Return Reg 1's Content                */
}


读W25Q32地址:

INT16U flash_read_id (void)
{
         INT16U IDcode;

         SPI_FLASH_CS_LOW();                                                                                                             /* P0.2--0,CS = 0 选中SPI Flash */
         Send_Byte(0x4b);
         Send_Byte(0x00);
         Send_Byte(0x00);
         Send_Byte(0x00);
         Send_Byte(0x00);
         IDcode = Send_Byte(0xff);
         SPI_FLASH_CS_HIGH();                                                                                                            /* P0.2--1,CS = 1 释放SPI Flash */

         return IDcode;                                                                                                   
}


读W25Q32数据:

uint8_t flash_read_data (uint32_t RAddr, uint8_t *buf, uint32_t RLength)
{
         uint8_t Temp;
         uint32_t i;

         if (RLength == 0)
         {
                 return 0;
         }

         /*
          *        Check the state register. If it's busy , wait until it's free
          */
         while(1)                                                                                                               
         {                                                                                                               
                 Temp = flash_read_status( );                                                               
                 Temp &= 0x01;                                                                                       
                 if(Temp == 0x00)                                                                        
                         break;                                                                        
                 for(i=0; i<10; i++);                                                
         }

         SPI_FLASH_CS_LOW();                                                                                                             /* P0.2--0,CS = 0 选中SPI Flash */
         Send_Byte(0x03);
         Send_Byte((RAddr & 0xFF0000) >> 16);
         Send_Byte((RAddr & 0x00FF00) >> 8);
         Send_Byte((RAddr & 0x0000FF));
         for (i=0; i<RLength; i++)
         {
                 buf = Send_Byte(0xff);
                 printf("Read Data = %d\r\n",buf);
         }
         SPI_FLASH_CS_HIGH();                                                                                                            /* P0.2--1,CS = 1 释放SPI Flash */

         return 1;
}


W25Q32区域擦除:

uint8_t flash_sector_erase (uint32_t addr)
{
         flash_write_enable();                                                                                                    /* Write enable                 */
         
         SPI_FLASH_CS_LOW();                                                                                                             /* P0.2--0,CS = 0 选中SPI Flash */
         Send_Byte(0x20);
         Send_Byte((addr & 0xFF0000) >> 16);
         Send_Byte((addr & 0x00FF00) >> 8);
         Send_Byte(addr & 0x0000FF);
          SPI_FLASH_CS_HIGH();                                                                                                            /* P0.2--1,CS = 1 释放SPI Flash */

         while (flash_read_status() & 0x01 != 0x00);                                                        /* Wait for the flash free      */

         return 1;
}


W25Q32区域写:

uint8_t flash_write_sector (uint32_t WAddr, uint8_t *buf, uint32_t WLength)
{
         uint32_t i;

         if (WLength == 0)
         {
                 return 0;
         }

         flash_write_enable();                                                                                                    /* Write enable                 */


         SPI_FLASH_CS_LOW();                                                                                                             /* P0.2--0,CS = 0 选中SPI Flash */
         Send_Byte(0x02);
         Send_Byte((WAddr & 0xFF0000) >> 16);
         Send_Byte((WAddr & 0x00FF00) >> 8);
         Send_Byte((WAddr & 0x0000FF));
         for (i=0; i<WLength; i++)
         {
                 Send_Byte(buf);        
                 printf("Send Data = %d\r\n",buf);
         }
         SPI_FLASH_CS_HIGH();                                                                                                            /* P0.2--1,CS = 1 释放SPI Flash */

         while ((flash_read_status() & 0x01) != 0x00);

         return 1;
}


主程序就不多说了,很好理解,就是将要实现的功能整合到一起。还是惯例红色的部分比较重要。

在这里重点说一下SPI写程序:


起初从主函数按照一步步调试观察的时候,发现程序只用到了SPI的写操作(程序上的说明是写操作),而没有用到读操作(同左),非常费解。

后来发现其实它的写操作里面是包含读操作的。

当需要写数据时就将数据给SPI,函数返回值不去理会,将标志位清零即可。
当需要读数据时就发送一帧0xff,然后将函数返回值读出来。

在这里需要说明为什么要发送0xff,我个人的认为是由于W25Q32器件的指令问题

相关下载

相关帖子

沙发
IversonCar| | 2015-7-30 16:48 | 只看该作者
谢谢楼主的热心分享,注释的很清楚

使用特权

评论回复
板凳
舒斯特尔| | 2015-7-30 20:49 | 只看该作者
SPI Flash的代码,很实用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

278

帖子

4

粉丝