W25Q128的SPI 驱动



W25Q128的SPI 驱动,没测试。

别人的链接    STM32 FLASH 链接


自己加了点注释和几个函数。


/*****************************************************************************
** 文件名称:flash.h   (芯片为W25Q128)
** 功    能:
** 修改日志:
******************************************************************************/
#ifndef __FLASH_H
#define __FLASH_H

typedef unsigned char		uint8_t;  /*  8 bits */
typedef unsigned short int	uint16_t; /* 16 bits */
typedef unsigned int	        uint32_t; /* 32 bits */

/******************************************************************************
** SPI_FLASH
********************************************************************************/
typedef enum
{
    RET_SUCCESS = 0,
    RET_FlashRead_ERROR,
    RET_WriteCmd_ERROR,
    RET_WaitBusy_ERROR
}
}SpiRetValueType;
/*****************************************************************************
** 管脚定义
*****************************************************************************/
#define    SPIFlash_Enable_CS      (P8OUT &= 0XFE)  //CS       	CS = 1							  		//打开spiflash片选使能
#define    SPIFlash_Disable_CS     (P8OUT |= 0X01)  //CS     	CS = 0							    	//关闭spiflash片选使能
#define    SPIFlash_Set_SCLK       (P7OUT |= 0X08)  //CLK     //上升沿写入 ,下降沿输出(读)   		        //拉高spiflash时钟线  
#define    SPIFlash_Clr_SCLK       (P7OUT &= 0Xf7)  //CLK      									        //拉低spiflash时钟线
#define    SPIFlash_Set_DO         (P8OUT |= 0X04)  //D0    D0 = 1							   		    //MOSI数据线置1,即输出1高电平
#define    SPIFlash_Clr_DO         (P8OUT &= 0XFB)  //D0    D0 = 0 									    //MOSI数据线清0,即输出0低电平
/*
#define    SPIFlash_Enable_CS       7引脚 = 1       //CS = 1							  		//打开spiflash片选使能
#define    SPIFlash_Disable_CS      7引脚 = 0       //CS     	CS = 0							    	//关闭spiflash片选使能
#define    SPIFlash_Set_SCLK        16引脚 = 1      //CLK     //上升沿写入 ,下降沿输出(读)   		        //拉高spiflash时钟线  
#define    SPIFlash_Clr_SCLK        16引脚 = 0      //CLK      									        //拉低spiflash时钟线
#define    SPIFlash_Set_DO          8引脚 = 1       //D0    D0 = 1							   		    //MOSI数据线置1,即输出1高电平
#define    SPIFlash_Clr_DO          8引脚 = 0       //D0    D0 = 0 									    //MOSI数据线清0,即输出0低电平
*/

#define    SPIFlash_Get_DI         SPIFlash_GPIO_GetBit()

#define    SPIFLASH_CMD_LENGTH        0x03 
#define    SPIFLASH_WRITE_BUSYBIT     0X01 //状态寄存器Busy位(状态寄存器的0位为 BUSY位) 
#define    SPIFlash_ReadData_CMD      0x03 //读数据
#define    SPIFlash_WriteEnable_CMD   0x06  //写使能 会使“状态寄存器”WEL为置位。在执行“擦除”前,需要置位WEL
#define    SPIFlash_WriteDisable_CMD  0x04  //写使能关闭
#define    SPIFlash_PageProgram_CMD   0x02   //页编程指令 (页256字节)
#define    SPIFlash_WriteSR_CMD       0x01   //写状态寄存器
#define    SPIFlash_ReadSR_CMD        0x05 //读状态寄存器 当CS低位,05H送入引脚,在CLK上升沿数据被芯片采集,芯片会把“状态寄存器”的值从DO输出,数据在CLK下降沿输出,高位在前.
#define    SPIFlash_SecErase_CMD      0x20  //扇区擦除指令 (一扇区 4K)
#define    SPIFlash_BlockErase_CMD    0xD8   //块擦除指令  将一块区(64K)全部变成1,即FFH
#define    SPIFlash_ChipeErase_CMD    0xC7   //芯片擦除指令
#define    SPIFLASH_ReadChipId_CMD    0x90   //读芯片ID
#define    SPIFlash_PAGEBYTE_LENGTH   256
#define    SPIFlash_SECBYTE_LENGTH   (1024*4)

/*******************************************************************************
** 函数声明
*******************************************************************************/

void SpiFlash_WriteOneByte(uint8_t DataBuffer);				  //写入Flash一个字节(byte),DataBuffer为要写入的内容
uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
void SpiFlash_Write_Sector_Data(char *pBuffer,uint8_t Block_Num,uint8_t Sector_Num,uint32_t WriteBytesNum);
void SpiFlash_Write_Data(char *pBuffer,uint8_t Block_Num,uint8_t Page_Num,uint32_t WriteBytesNum);

uint8_t SpiFlash_ReadOneByte(void);							  //从Flash读出一个字节(Byte),返回值为 retValue(uint8_t)
uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum);
void SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum);
void SpiFlash_Read_Sector_Data(char *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num,uint32_t ReadBytesNum);

void SPIFlash_Erase_Block(uint8_t BlockNum);
void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number);
void SPIFlash_Erase_Chip(void); //擦除整个芯片

void Spi_Flash_Init(void);
uint16_t SPIFlash_GPIO_GetBit(void);
#endif





/*****************************************************************************
** 文件名称:flash.c
** 功    能:
** 修改日志:
******************************************************************************/
#include "includes.h"

/*****************************************************************************
** 文件名称:uint8_t SpiFlash_ReadOneByte(void)
** 功    能:从Flash读出一个字节(Byte),返回值为 retValue(uint8_t)
** 修改日志:
** 附    录:先把CLK = 1 ,CLK = 0 下降沿 读取
******************************************************************************/

uint8_t SpiFlash_ReadOneByte(void)
{
    uint8_t BitCount = 0;
    uint8_t retValue = 0;
    SPIFlash_Set_SCLK;            //时钟线拉高,恢复时钟线为高电平 cs = 1

    for(BitCount = 0;BitCount < 8; BitCount++)
    {
        retValue <<= 1;
        SPIFlash_Set_SCLK;            //时钟线拉高,恢复时钟线为高电平
        if(SPIFlash_Get_DI)
        {
            retValue |= 0x01;
        }
        else
        {
            retValue &= 0xFE;
        }
        SPIFlash_Clr_SCLK;            //时钟线拉低,产生下降沿读出数据  // cs = 0 产生下降沿 读出数据
    }
    SPIFlash_Set_SCLK;
    return (retValue);
}

/*****************************************************************************
** 文件名称:void SpiFlash_WriteOneByte(uint8_t DataBuffer)
** 功    能:写入Flash一个字节(byte),DataBuffer为要写入的内容
** 修改日志:

** 附    录:先把CS拉低(拉低选中)CS = 0 设备被选中,可以写入和读取
			
******************************************************************************/

void SpiFlash_WriteOneByte(uint8_t DataBuffer)
{
    uint8_t BitCount = 0;
    SPIFlash_Clr_SCLK;          //时钟线拉低,恢复时钟线为低电平
    for(BitCount = 0;BitCount < 8; BitCount++)
    {
        SPIFlash_Clr_SCLK;          //时钟线拉低,恢复时钟线为低电平
        if(DataBuffer & 0x80)
        {
            SPIFlash_Set_DO;          //MOSI数据线置1,即输出1高电平
        }
        else
        {
            SPIFlash_Clr_DO;
        }
        DataBuffer <<= 1;
        SPIFlash_Set_SCLK;            //时钟线拉高,产生上升沿写入数据
    }
    SPIFlash_Clr_SCLK;
    SPIFlash_Set_DO;                //一字节数据传送完毕,MOSI数据线置高表示空闲状态

}

/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_Write_CMD(uint8_t *CMD)
** 功    能:写入 “读数据” 命令          
** 修改日志:
** 附    录:当CS拉低之后,把03H从DI引脚输入到Flash芯片,之后送入24位地址,这些数据在CLK上升沿,数据写入Flash。当芯片接收完24位地址后,会把相应地址的数据,在CLK的下降沿输出,
			 从DO输出。高位在前。当读完这个数据后,地址自动增加,然后通过DO引脚把下一个地址的数据送出,形成一个数据流。因此,只要时钟在工作,通过一条读指令就能把整个芯片的存储器
			 读出来。
			 CS拉高,“读数据”指令结束。		
******************************************************************************/

static uint8_t SpiFlash_Write_CMD(uint8_t *CMD)
{
    uint32_t i = 0;
    for(i = 0;i < SPIFLASH_CMD_LENGTH; i++)
    {
        SpiFlash_WriteOneByte(CMD[i]);  //打开SD卡的片选信号并写入命令数据
    }

    return RET_SUCCESS;
}

/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_ReadSR(void)
** 功    能:“读状态寄存器”命令,retValue为读到的数值
** 修改日志:
** 附    录:当CS拉低之后,把05H从DI引脚输入到Flash芯片,CLK上升沿,数据写入Flash,当Flash收到05H后,会把“状态寄存器”的值,从D0引脚输出,CLK下降沿输出。  
******************************************************************************/

static uint8_t SpiFlash_ReadSR(void)
{
    uint8_t retValue = 0;
    SPIFlash_Enable_CS; //CS使能
    SpiFlash_WriteOneByte(SPIFlash_ReadSR_CMD);
    retValue = SpiFlash_ReadOneByte();
    SPIFlash_Disable_CS;//CS关闭
    return retValue;
}


/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_Wait_Busy(void)
** 功    能:判断Flash是否busy。
** 修改日志:
:SPIFLASH_WRITE_BUSYBIT 写状态寄存器 
******************************************************************************/

static uint8_t SpiFlash_Wait_Busy(void)
{
    sDelayT.cDelay_Count=0;
    while((SpiFlash_ReadSR()&SPIFLASH_WRITE_BUSYBIT) == 0X01)  //状态寄存器0位为Busy位
    {  
       if(sDelayT.cDelay_Count==100)
          break;     
    }
    return RET_SUCCESS;
}

/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum)
** 功    能:读Flash的某地址ReadAddr,读多大ReadByteNum,的数值。
** 修改日志:
******************************************************************************/

uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum)
{
    uint32_t i = 0;
    uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
    uint8_t ret = 0;

    SPIFlash_Enable_CS;              //打开CS spiflash片选

    SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);

    pcmd[0] = (uint8_t)((ReadAddr&0x00ff0000)>>16);
    pcmd[1] = (uint8_t)((ReadAddr&0x0000ff00)>>8);
    pcmd[2] = (uint8_t)ReadAddr;
	/*
	        // send cmd
        BSP_SpiWriteByte(FLASH_CMD_CARLF);
        BSP_SpiWriteByte((FlashAdr>>16) & 0xFF);
        BSP_SpiWriteByte((FlashAdr>>8) & 0xFF);
        BSP_SpiWriteByte(FlashAdr & 0xFF);
	*/
    ret = SpiFlash_Write_CMD(pcmd);
    if(ret != RET_SUCCESS)
    {
        return RET_WriteCmd_ERROR;
    }

    for(i = 0;i < ReadBytesNum; i++)
    {
       pBuffer[i] = SpiFlash_ReadOneByte();  //读取SPIflash中指定bytes字节数据

    }
    SPIFlash_Disable_CS;       //关闭CS spiflash片选
    return RET_SUCCESS;
}

/*****************************************************************************
** 文件名称:static void SpiFlash_Write_Enable(void)
** 功    能:
** 修改日志:
            SPIFlash_WriteEnable_CMD 写使能 会使“状态寄存器”WEL为置位。在执行“擦除”前,需要置位WEL。
******************************************************************************/

static void SpiFlash_Write_Enable(void)
{
    SPIFlash_Enable_CS;
    SpiFlash_WriteOneByte(SPIFlash_WriteEnable_CMD);
    SPIFlash_Disable_CS;
}

/*****************************************************************************
** 文件名称: void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number)
** 功    能: 擦除扇区 擦除某块Block,某扇区Sector
** 修改日志:
** 附    录: SPIFlash_SecErase_CMD 扇区擦除指令,将一个扇区(4k)擦除。擦除后都为1,扇区字节都为FFH。在执行“扇区擦除”前,需执行“写指令”
              SpiFlash_Write_Enable(),然后拉低CS,写入擦除命令,然后把24位扇区地址写入芯片。然后拉高CS。在执行命令期间,BUSY位为1。执行完,
			  BUSY位为0,WEL为0。
			  
******************************************************************************/

void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number)
{
    uint8_t pcmd[3] = {0};
    SpiFlash_Write_Enable();
    SPIFlash_Enable_CS;
    SpiFlash_WriteOneByte(SPIFlash_SecErase_CMD);

    pcmd[0] = Block_Num;
    pcmd[1] = Sector_Number<<4;
    pcmd[2] = 0;
    SpiFlash_Write_CMD(pcmd);
    SPIFlash_Disable_CS;
    SpiFlash_Wait_Busy();    //每次擦除数据都要延时等待写入结束

    return ;
}


/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
** 功    能:从pBuffer内,向某页上的一地址的写入数据
** 修改日志:

** 附    加:一页大小 256 bytes(a page)
******************************************************************************/
uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
    uint32_t i = 0;
    uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
    uint8_t ret = 0;

    SpiFlash_Write_Enable();
    SPIFlash_Enable_CS;
    SpiFlash_WriteOneByte(SPIFlash_PageProgram_CMD);
    pcmd[0] = (uint8_t)((WriteAddr&0x00ff0000)>>16);
    pcmd[1] = (uint8_t)((WriteAddr&0x0000ff00)>>8);
    pcmd[2] = (uint8_t)WriteAddr;
    ret = SpiFlash_Write_CMD(pcmd);

    if(ret != RET_SUCCESS)
    {
        return RET_WriteCmd_ERROR;
    }

    for(i = 0;i < WriteBytesNum; i++)
    {

        SpiFlash_WriteOneByte(pBuffer[i]);  //向SPIflash中写入最大一页256bytes字节数据
    }
    SPIFlash_Disable_CS;
    ret = SpiFlash_Wait_Busy();                   //每次写入一定数量的数据都要延时等待写入结束
    if(ret != RET_SUCCESS)
        return RET_WaitBusy_ERROR;

    return RET_SUCCESS;
}


/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
** 功    能:pBuffer数据存储器,WriteAddr开始写入的地址(24bit),要写入的字节数WriteBytesNum(最大65536)
** 修改日志:
******************************************************************************/
uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{

    uint16_t PageByteRemain = 0;
    PageByteRemain = SPIFlash_PAGEBYTE_LENGTH - WriteAddr%SPIFlash_PAGEBYTE_LENGTH;//单页剩余的字节数
    if(WriteBytesNum <= PageByteRemain)//不大于256个字节
    {
        PageByteRemain = WriteBytesNum; 
    }
    while(1)
    {
        SpiFlash_Write_Page(pBuffer,WriteAddr,PageByteRemain);
        if(WriteBytesNum == PageByteRemain) //写入结束
        {
            break;
        }
        else
        {
            pBuffer += PageByteRemain;
            WriteAddr += PageByteRemain;
            WriteBytesNum -= PageByteRemain;              //减去已经写入的字节数
            if(WriteBytesNum > SPIFlash_PAGEBYTE_LENGTH)  //一次可以写入256个字节
            {
                PageByteRemain = SPIFlash_PAGEBYTE_LENGTH;
            }
            else										  //不够256个字节
            {
                PageByteRemain = WriteBytesNum;
            }
        }
    }
    return RET_SUCCESS;
}

//
///*****************************************************************************
//** 文件名称:uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
//** 功    能:pBuffer数据存储器,WriteAddr开始写入的地址(24bit),要写入的字节数WriteBytesNum(最大65536).以扇区为单位写入。
//** 修改日志:
//******************************************************************************/
//uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
//{
//    uint32_t Secpos = 0;
//    uint16_t Secoff = 0;
//    uint16_t Secremain = 0;
//    uint32_t i = 0;
//    uint8_t  SPIBufferTemp[SPIFlash_SECBYTE_LENGTH] = {0}; //SPIFlash_SECBYTE_LENGTH 4096
//    Secpos = WriteAddr/SPIFlash_SECBYTE_LENGTH;//扇区地址
//    Secoff = WriteAddr%SPIFlash_SECBYTE_LENGTH; //扇区内偏移量
//    Secremain = SPIFlash_SECBYTE_LENGTH - Secoff;//扇区剩余空间
//    if(WriteBytesNum <= Secremain)
//    {
//        Secremain = WriteBytesNum;
//    }
//
//    while(1)
//    {
//        if(SpiFlash_Read(SPIBufferTemp,Secpos*SPIFlash_SECBYTE_LENGTH,SPIFlash_SECBYTE_LENGTH) != RET_SUCCESS) //读出整个扇区内容
//        {
//             return RET_FlashRead_ERROR;
//        }
//        for(i = 0;i < Secremain;i++) //检验数据
//        {
//            if(SPIBufferTemp[Secoff+i] != 0xFF)
//                break;                  //需要擦除一个扇区
//        }
//        if(i < Secremain)               //需要擦除一个扇区
//        {
//            SPIFlash_Erase_Sector(Secpos);      //擦除这个扇区
//            for(i = 0;i < Secremain;i++)     //复制
//            {
//                SPIBufferTemp[i+Secoff] = pBuffer[i];
//            }
//            SpiFlash_Write_MorePage(SPIBufferTemp,Secpos*SPIFlash_SECBYTE_LENGTH,SPIFlash_SECBYTE_LENGTH); //写入整个扇区
//        }
//        else
//        {
//            SpiFlash_Write_MorePage(pBuffer,WriteAddr,Secremain);//写已经擦除的了的,直接写入扇区剩余的空间
//        }
//
//        if(WriteBytesNum == Secremain) //写入结束
//        {
//            break;
//        }
//        else
//        {
//            Secpos++;//扇区地址增1
//            Secoff = 0;//偏移位置为0
//            pBuffer += Secremain;//指针偏移
//            WriteAddr += Secremain;//便宜位置为0
//            WriteBytesNum -=Secremain;//字节数递减
//            if(WriteBytesNum > SPIFlash_SECBYTE_LENGTH) //下一个扇区还没写完
//            {
//                Secremain = SPIFlash_SECBYTE_LENGTH;
//            }
//            else//下一个扇区写完
//            {
//                Secremain = WriteBytesNum;
//            }
//        }
//    }
//    return RET_SUCCESS;
//}
//

/*****************************************************************************
** 文件名称:uint16_t SPIFlash_GPIO_GetBit(void)
** 功    能:
** 修改日志:
******************************************************************************/
uint16_t SPIFlash_GPIO_GetBit(void)
{
  uint16_t retValue = 0;
  uint16_t valueTemp = 0;
  valueTemp = P8IN;
  retValue = (valueTemp &= BIT1)>>0x01;            //BIT1即是0x02
  return retValue;
}


/*****************************************************************************
** 文件名称:void SPIFlash_Erase_Block(uint8_t BlockNum)
** 功    能:擦除BLOCK
** 修改日志:
******************************************************************************/

void SPIFlash_Erase_Block(uint8_t BlockNum)
{
    uint8_t pcmd[3] = {0};

    SpiFlash_Write_Enable();   //写使能
    SPIFlash_Enable_CS;        //片选拉低
    SpiFlash_WriteOneByte(SPIFlash_BlockErase_CMD);  //传输Block擦除指令
    pcmd[0] =BlockNum ;        //传24位地址 因为单片机为16位 所以分两次传
    SpiFlash_Write_CMD(pcmd);
    SPIFlash_Disable_CS;
    SpiFlash_Wait_Busy();                   //每次擦除数据都要延时等待写入结束

    return ;
}

/*****************************************************************************
** 文件名称:void SPIFlash_Erase_Chip(void)
** 功    能:擦除整个芯片
** 修改日志:
******************************************************************************/
void SPIFlash_Erase_Chip(void)
{
	SpiFlash_Write_Enable();   //写使能
	SpiFlash_Wait_Busy(); 
	SPIFlash_Enable_CS;        //片选拉低
	SpiFlash_WriteOneByte(SPIFlash_ChipeErase_CMD);  //传输Block擦除指令
	SPIFlash_Disable_CS;
	SpiFlash_Wait_Busy();  
	
}

/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_Data(uint8_t *pBuffer,uint8_t Block_Num,int8_t Page_Num,uint32_t WriteBytesNum)
** 功    能:写哪个块中哪一页的数据
** 修改日志:
******************************************************************************/
void SpiFlash_Write_Data(char *pBuffer,uint8_t Block_Num,uint8_t Page_Num,uint32_t WriteBytesNum)
{
    
    uint8_t pcmd[3] = {0};
    
    SpiFlash_Write_Enable();
    SPIFlash_Enable_CS;
    SpiFlash_WriteOneByte(SPIFlash_PageProgram_CMD);
    pcmd[0] = Block_Num;
    pcmd[1] = Page_Num;
    pcmd[2] = 0;
    SpiFlash_Write_CMD(pcmd);

    for(uint32_t i = 0;i < WriteBytesNum; i++)
    {
        SpiFlash_WriteOneByte(pBuffer[i]);  //向SPIflash中写入最大一页256bytes字节数据
    }
    SPIFlash_Disable_CS;
    SpiFlash_Wait_Busy();                   //每次写入一定数量的数据都要延时等待写入结束
    return ;
}
/*****************************************************************************
** 文件名称:void SpiFlash_Write_Sector_Data(uint8_t *pBuffer,uint8_t Block_Num,int8_t Sector_Num,uint32_t WriteBytesNum)
** 功    能:写扇区数据
** 修改日志:
******************************************************************************/
void SpiFlash_Write_Sector_Data(char *pBuffer,uint8_t Block_Num,uint8_t Sector_Num,uint32_t WriteBytesNum)
{
   uint8_t Write_Page_Num=0;

   Write_Page_Num = WriteBytesNum/256;
   if((WriteBytesNum%256)!=0) Write_Page_Num+=1;
   for(uint8_t i=0;i<Write_Page_Num;i++)
   {    
     SpiFlash_Write_Data(pBuffer,Block_Num,i+(Sector_Num<<4),256);
     pBuffer=pBuffer+256;   
   }
   return ;
}

/*****************************************************************************
** 文件名称:void SpiFlash_Read_Sector_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num ,uint32_t ReadBytesNum)
** 功    能:读扇区数据
** 修改日志:
******************************************************************************/

void SpiFlash_Read_Sector_Data(char *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num,uint32_t ReadBytesNum)
{
    uint32_t i = 0;
    uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};

    SPIFlash_Enable_CS;              //打开spiflash片选
    SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);
    pcmd[0] =Block_Num ;
    pcmd[1] =Sector_Num<<4;
    pcmd[2] = 0;
    SpiFlash_Write_CMD(pcmd);

    for(i = 0;i < ReadBytesNum; i++)
    {
       pBuffer[i] = SpiFlash_ReadOneByte();  //读取SPIflash中指定bytes字节数据

    }
    SPIFlash_Disable_CS;
    
    return ;
}

/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
** 功    能:
** 修改日志:
******************************************************************************/

void SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
{
    
    uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};

    SPIFlash_Enable_CS;              //打开spiflash片选
    SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);
    pcmd[0] =Block_Num ;
    pcmd[1] =Page_Num ;
    pcmd[2] = 0;
    SpiFlash_Write_CMD(pcmd);

    for(uint32_t i = 0 ;i < ReadBytesNum; i++)
    {
       pBuffer[i] = SpiFlash_ReadOneByte();  //读取SPIflash中指定bytes字节数据

    }
    SPIFlash_Disable_CS;
    return ;
}

/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
** 功    能:
** 修改日志:
******************************************************************************/
SPIFLASH_ReadChipId_CMD
uint16_t SpiFlash_ReadChipId(void)
{
	uint16_t Temp = 0;
	SPIFlash_Enable_CS; //cs = 0
	SpiFlash_WriteOneByte(SPIFLASH_ReadChipId_CMD);
	SpiFlash_WriteOneByte(0x00);
	SpiFlash_WriteOneByte(0x00);
	SpiFlash_WriteOneByte(0x00);
	Temp |= SpiFlash_ReadOneByte(0xFF)<<8;
	Temp |= SpiFlash_ReadOneByte(0xFF);
	SPIFlash_Disable_CS;
	
	return Temp;
	
}


/*******************************************************************************
** 函数名称:void Spi_Flash_init(void)
** 功    能:
** 修改日志:
*******************************************************************************/
void Spi_Flash_Init(void)
{
    P7DIR &= 0XF7;       //设置P7.3为IO模式

    P7DIR |= 0x08;       //设置CLK引脚为强输出模式

    P8SEL &= 0XF8;       //设置P8.0,P8.1,P8.2为IO模式

    P8DIR &= 0XFD;       //设置MCU端的DI为输入模式

    P8DIR |= 0X05;       //设置MCU端的CS#,DO为强输出模式

    P8REN &= 0XFD;       //设为不用上拉电阻和下拉电阻的普通输入模式
    
    P8OUT |=BIT0;        //根据芯片数据手册 cs脚需上拉(因硬件上没有所以这用软件)
}

#if 0
void Spi_Flash_Init(void)
{
	SPIFlash_Disable_CS;

}

#endif


                                                                                                


你可能感兴趣的:(W25Q128的SPI 驱动)