查看: 1178|回复: 0
打印 上一主题 下一主题

教W25X16的ID读取

[复制链接]
跳转到指定楼层
沙发
发表于 2015-9-18 10:55:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面是W25X16的驱动程序,发现写数据,读数据没有问题,但是在用SPI_FLASH_ReadID读器件ID的时候总是返回0x00,哪里出了问题了?谢谢了



/******************************
*         | PA4-SPI1-NSS  : W25X16-CS  |
*         | PA5-SPI1-SCK  : W25X16-CLK |
*         | PA6-SPI1-MISO : W25X16-DO  |
*         | PA7-SPI1-MOSI : W25X16-DIO |
*          ----------------------------
******************************/

#include "SPI_W25X16.h"

#define     SPI_FLASH_PerWritePageSize    256           //每一页256个字节


#define W25X16_WriteEnable                        0x06
#define W25X16_WriteDisable                        0x04
#define W25X16_ReadStatusReg                    0x05
#define W25X16_WriteStatusReg                    0x01
#define W25X16_ReadData                                0x03
#define W25X16_FastReadData                        0x0B
#define W25X16_FastReadDual                        0x3B
#define W25X16_PageProgram                        0x02
#define W25X16_BlockErase                            0xD8
#define W25X16_SectorErase                        0x20
#define W25X16_ChipErase                            0xC7
#define W25X16_PowerDown                            0xB9
#define W25X16_ReleasePowerDown                0xAB
#define W25X16_DeviceID                                0xAB
#define W25X16_ManufactDeviceID               0x90
#define W25X16_JedecDeviceID                    0x9F

#define WIP_Flag                        0x01
#define Dummy_Byte                      0xff    //随意的字节

void  SPI_FLASH_Init(void)
{
                SPI_InitTypeDef    SPI_InitStructure;
                GPIO_InitTypeDef   GPIO_InitStructure;
                //使能GPIOA SPI时钟
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);

                //四个引脚都设置为了复用推挽输出
                GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_4;
                GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
                GPIO_Init(GPIOA,&GPIO_InitStructure);

                //不选择FLASH
                SPI_FLASH_CS_HIGH();
                //配置SPI
                SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//双向全双工
                SPI_InitStructure.SPI_Mode=SPI_Mode_Master ;
                SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
                SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;
                SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;
                SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
                SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4;
                SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
                SPI_InitStructure.SPI_CRCPolynomial=7;
                SPI_Init(SPI1,&SPI_InitStructure);

                SPI_Cmd(SPI1,ENABLE);
}
//send a byte through the spi interface and return the byte receive from the SPI bus
u8   SPI_FLASH_SendByte(u8 byte)
{
                //等待DR为空
                while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
                SPI_I2S_SendData(SPI1,byte);
                //等待接收数据
                while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);
                return SPI_I2S_ReceiveData(SPI1);
}

//Enable the Write access to the FALSH
void           SPI_FLASH_WriteEnable(void)
{
                SPI_FLASH_CS_LOW();
                //使能 写
                SPI_FLASH_SendByte(W25X16_WriteEnable);               
                SPI_FLASH_CS_HIGH();
}
//wait for write complete
void   SPI_FLASH_WaitForWriteEnd(void)
{
                u8  FLASH_Status=0;
                SPI_FLASH_CS_LOW();
                //读状态寄存器
                SPI_FLASH_SendByte(W25X16_ReadStatusReg);
                do
                {
                                //send a dummy byte to generate the clock needed by the flash
                                //and return the value of the status register
                                FLASH_Status=SPI_FLASH_SendByte(Dummy_Byte);               
                } while((FLASH_Status&WIP_Flag)==SET);
                SPI_FLASH_CS_HIGH();
}


// 扇区擦除4KB SectorAddr为起始地址
void   SPI_FLASH_SectorErase(u32 SectorAddr)
{
                SPI_FLASH_WriteEnable();
                SPI_FLASH_WaitForWriteEnd();        
                //sector erase
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_SectorErase);                        
                //send sectorAddr high address byte
                SPI_FLASH_SendByte((SectorAddr&0xFF0000)>>16);
                SPI_FLASH_SendByte((SectorAddr&0xFF00)>>8);
                SPI_FLASH_SendByte(SectorAddr&0xFF);
                SPI_FLASH_CS_HIGH();
                SPI_FLASH_WaitForWriteEnd();
}
// Erase the entire FLASH
void  SPI_FLASH_BulkErase(void)
{
                SPI_FLASH_WriteEnable();
                SPI_FLASH_WaitForWriteEnd();
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_ChipErase);               
                SPI_FLASH_CS_HIGH();
                SPI_FLASH_WaitForWriteEnd();
}
//Writes more than one bytes to the flash, the number of the byte can not
// exceed the FLASH page size (256)
//此函数只能写入小于等于256个字节

void  SPI_FLASH_PageWrite(u8 *pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
                SPI_FLASH_WriteEnable();
                SPI_FLASH_WaitForWriteEnd();
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_PageProgram);
                SPI_FLASH_SendByte((WriteAddr&0xFF0000)>>16);               
                SPI_FLASH_SendByte((WriteAddr&0xFF00)>>8);
                SPI_FLASH_SendByte(WriteAddr&0xFF);
                if(NumByteToWrite>SPI_FLASH_PerWritePageSize)
                {
                                NumByteToWrite=SPI_FLASH_PerWritePageSize;

                }
                while(NumByteToWrite--)
                {
                                SPI_FLASH_SendByte(*pBuffer);
                                pBuffer++;
                }
                SPI_FLASH_CS_HIGH();
                SPI_FLASH_WaitForWriteEnd();
}
//将缓冲区的数据写入flash中,字节数不要大于整个芯片的字节数
void  SPI_FLASH_BufferWrite(u8 *pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
                u8 NumOfPage=0,NumOfSingle=0,Addr=0,count=0,temp=0;
                Addr=WriteAddr%SPI_FLASH_PerWritePageSize;  
                count=SPI_FLASH_PerWritePageSize-Addr;  
                NumOfPage=NumByteToWrite/SPI_FLASH_PerWritePageSize;
                NumOfSingle=NumByteToWrite%SPI_FLASH_PerWritePageSize;
                if(Addr==0) //起始地址是256的整数倍
                {
                                if(NumOfPage==0)        //小于256个字节
                                {
                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumByteToWrite);               
                                }               
                                else         //多于256个字节
                                {
                                                while(NumOfPage--)  
                                                {
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,SPI_FLASH_PerWritePageSize);
                                                                WriteAddr+=SPI_FLASH_PerWritePageSize;
                                                                pBuffer+=SPI_FLASH_PerWritePageSize;
                                                }
                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumOfSingle);  
                                }
                }

                else   
                {
                                if(NumOfPage==0)  //
                                {
                                                if(NumOfSingle>count)  
                                                {
                                                                temp=NumOfSingle-count;  
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,count);
                                                                WriteAddr+=count;
                                                                pBuffer+=count;
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,temp);
                                                }
                                                else        
                                                {
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumByteToWrite);                                
                                                }               
                                }
                                else    //多于256个字节
                                {
                                                NumByteToWrite-=count;  
                                                NumOfPage=NumByteToWrite/SPI_FLASH_PerWritePageSize;  
                                                NumOfSingle=NumByteToWrite%SPI_FLASH_PerWritePageSize;

                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,count);
                                                WriteAddr+=count;
                                                pBuffer+=count;
                                                while(NumOfPage--)
                                                {
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,SPI_FLASH_PerWritePageSize);                        
                                                                WriteAddr+=SPI_FLASH_PerWritePageSize;
                                                                pBuffer+=SPI_FLASH_PerWritePageSize;
                                                }
                                                if(NumOfSingle!=0)                                
                                                {
                                                                SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumOfSingle);
                                                }
                                }
                }
}
// read a block of data from the FLASH
void  SPI_FLASH_BufferRead(u8 *pBuffer,u32 ReadAddr,u16 NumByteToRead)
{
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_ReadData);
                SPI_FLASH_SendByte((ReadAddr&0xFF0000)>>16);               
                SPI_FLASH_SendByte((ReadAddr&0xFF00)>>8);
                SPI_FLASH_SendByte(ReadAddr&0xFF);
                while(NumByteToRead--)
                {
                                *pBuffer=SPI_FLASH_SendByte(Dummy_Byte);               
                                pBuffer++;
                }
                SPI_FLASH_CS_HIGH();
}
// Read FLASH identification
u32   SPI_FLASH_ReadID(void)
{
                u32 temp=0,temp0=0,temp1=0,temp2=0;
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_JedecDeviceID);
                temp0=SPI_FLASH_SendByte(Dummy_Byte);
                temp1=SPI_FLASH_SendByte(Dummy_Byte);
                temp2=SPI_FLASH_SendByte(Dummy_Byte);
                SPI_FLASH_CS_HIGH();
                temp=(temp0<<16)|(temp1<<8)|temp2;
                return temp;

}
/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
u32 SPI_FLASH_ReadDeviceID(void)
{
                u32 Temp = 0;

                  /* Select the FLASH: Chip Select low */
                  SPI_FLASH_CS_LOW();

                  /* Send "RDID " instruction */
                  SPI_FLASH_SendByte(W25X16_DeviceID);
                  SPI_FLASH_SendByte(Dummy_Byte);
                  SPI_FLASH_SendByte(Dummy_Byte);
                  SPI_FLASH_SendByte(Dummy_Byte);

                  /* Read a byte from the FLASH */
                  Temp = SPI_FLASH_SendByte(Dummy_Byte);

                  /* Deselect the FLASH: Chip Select high */
                  SPI_FLASH_CS_HIGH();

                  return Temp;
}



//进入掉电模式
void  SPI_FLASH_PowerDown(void)
{
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_PowerDown);
                SPI_FLASH_CS_HIGH();
}
//唤醒
void  SPI_FLASH_WAKEUP(void)
{
                SPI_FLASH_CS_LOW();
                SPI_FLASH_SendByte(W25X16_ReleasePowerDown);
                SPI_FLASH_CS_HIGH();
}
转载
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表