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