SPI FLASH 驱动
发布时间:2020-12-15 17:53:57 所属栏目:百科 来源:网络整理
导读:void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) ? SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 ? ?? ?? ?SST25V_DBSY(); SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 ? ?? ?? ?SST25V_DBSY(); 实验目的:将数
void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)?
SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 ? ?? ?? ?SST25V_DBSY(); SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 ? ?? ?? ?SST25V_DBSY(); 实验目的:将数据写入外部FLASH中,然后再读出来显示在LCD上 实验平台:基于STM32F103C8T6的彩屏开发板 FLASH: SST25VF 016B flash_SST.c #include "flash_SST.h" #include "spi.h" #include "delay.h" //4Kbytes为一个Sector //16个扇区为1个Block //SST25VF016B //容量为2M字节,共有32个Block(块),512个Sector(扇区) //初始化SPI FLASH的IO口 //修改状态寄存器,允许芯片存储器被写 void SPI_Flash_Init(void) { RCC->APB2ENR|=1<<2;? ?? ???//PORTA时钟使能? ?? ??? GPIOA->CRH&=0XFFFFFF0F; GPIOA->CRH|=0X00000030;? ? //PA9 推挽? ?? ?? ? GPIOA->ODR|=1<<9;? ?? ?? ? //PA9上拉 SPIx_Init();? ?? ?? ?? ?? ?//初始化SPI SPI_FLASH_Write_SR(0x02);??//使能状态寄存器中的写存储器 SST25V_DBSY(); }? //读取SPI_FLASH的状态寄存器 //BIT7??6? ?5? ?4? ?3? ?2? ?1? ?0 //SPR? ?RV??TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 u8 SPI_Flash_ReadSR(void)?? {? u8 byte=0;?? SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ? //使能器件?? SPIx_ReadWriteByte(SST25_ReadStatusReg);? ? //发送读取状态寄存器命令? ? byte=SPIx_ReadWriteByte(0Xff);? ?? ?? ?? ? //读取一个字节? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//取消片选? ?? return byte;?? } //写SPI_FLASH状态寄存器 //只有SPR,TB,BP0(bit 7,5,4,3,2)可以写!!! void SPI_FLASH_Write_SR(u8 sr)?? {?? SPI_FLASH_CS=0;? ? //片选 SPIx_ReadWriteByte(SST25_EnableWriteStatusReg);??//使能写状态寄存器命令?? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //取消片选 SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//片选? ?? ?? ?? ?? ?? ?? ?? ? SPIx_ReadWriteByte(SST25_WriteStatusReg);? ?//发送写取状态寄存器命令? ? SPIx_ReadWriteByte(sr);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//写入一个字节? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //取消片选? ?? ?? ?? ?? ??? }? //SPI_FLASH写使能 //将WEL置位?? void SPI_FLASH_Write_Enable(void)?? { SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ? //使能器件?? SPIx_ReadWriteByte(SST25_WriteEnable);? ?? ?//发送写使能? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ? //取消片选? ?? ?? ?? ?? ? } //SPI_FLASH写禁止 //将WEL清零? void SPI_FLASH_Write_Disable(void)?? {? SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//使能器件?? SPIx_ReadWriteByte(SST25_WriteDisable);? ???//发送写禁止指令? ? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//取消片选? ?? ?? ?? ?? ? }? ?? ?? ?? ?? ?? ?? ?? ?? ??? //读取芯片ID SST25VF016的是 0XBF41 u16 SPI_Flash_ReadID(void) { u16 Temp = 0;? ?? ? SPI_FLASH_CS=0;? ? ? //发送读取ID命令? ?? ?? ?? ?? ?? ?? ?? ?? ? SPIx_ReadWriteByte(0x90); //发送24位的地址? ?? ??? SPIx_ReadWriteByte(0x00);? ?? ?? ?? ?? SPIx_ReadWriteByte(0x00);? ?? ?? ?? ?? SPIx_ReadWriteByte(0x00); //读取返回的16位值? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? Temp=SPIx_ReadWriteByte(0xFF)<<8;??//高8位数据 Temp+=SPIx_ReadWriteByte(0xFF);? ?? ?//底八位数据 SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??? return Temp; } //读取SPI FLASH? //在指定地址开始读取指定长度的数据 //pBuffer:数据存储区 //ReadAddr:开始读取的地址(24bit) //NumByteToRead:要读取的字节数(最大65535即64k) void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)?? { u16 i;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//使能器件?? SPIx_ReadWriteByte(SST25_ReadData);? ?? ?? ?//发送读取命令 //发送24bit地址? ? SPIx_ReadWriteByte((u8)((ReadAddr)>>16));? ? SPIx_ReadWriteByte((u8)((ReadAddr)>>8));?? SPIx_ReadWriteByte((u8)ReadAddr); for(i=0;i<NumByteToRead;i++) { ??pBuffer=SPIx_ReadWriteByte(0XFF);? ?//循环读数? } SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ? //取消片选? ?? ?? ?? ?? ? }? //地址自动增加的写数据A void AutoAddressIncrement_WordProgramA(u8 Byte1,u8 Byte2,u32 Addr) { SPI_FLASH_Write_Enable(); SPI_FLASH_CS=0; SPIx_ReadWriteByte(SST25_AAI_WordProgram); //输入所要写数据的起始地址 SPIx_ReadWriteByte((Addr & 0xFF0000) >> 16); SPIx_ReadWriteByte((Addr & 0xFF00) >> 8); SPIx_ReadWriteByte(Addr & 0xFF);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //发送最初的两个数据 SPIx_ReadWriteByte(Byte1); SPIx_ReadWriteByte(Byte2); SPI_FLASH_CS=1; SPI_Flash_Wait_Busy(); } //地址自动增加的写数据B void AutoAddressIncrement_WordProgramB(u8 state,u8 Byte1,u8 Byte2) { SPI_FLASH_Write_Enable(); SPI_FLASH_CS=0; SPIx_ReadWriteByte(SST25_AAI_WordProgram); SPIx_ReadWriteByte(Byte1); SPIx_ReadWriteByte(Byte2); SPI_FLASH_CS=1; SPI_Flash_Wait_Busy(); if(state==1) { ??SPI_FLASH_Write_Disable(); } SPI_Flash_Wait_Busy(); } //结合AB构成的地址自动增加的连续数据的写入 //具有先擦除待写区域的功能 //pBuffer:为待写数据组 //WriteAddr:所写数据的起始地址 //NumByteToWrite:所要写的数据的长度 void SPI_Flash_Write(u8* pBuffer,u16 NumByteToWrite) { u16 i,temp; u32 secpos; u16 secoff; u16 secremain;? ??? //以下代码为擦除待写区域的代码 secpos=WriteAddr/4096;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //扇区(4K)地址0~511 for? ???SST25VF016 secoff=WriteAddr@96;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //在扇区内的偏移 secremain=4096-secoff;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//扇区剩余空间大小 if(NumByteToWrite<secremain)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//剩余空间大于所存数据 { ??temp=1; } else? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//剩余空间小于所存数据 { ??i=NumByteToWrite-secremain;? ?? ?? ?? ?? ?? ?? ?? ?? ?//判断还占了几个扇区 if(i%96==0) ? ?? ? temp=i/4096+1; else ? ?? ? temp=i/4096+2; } for(i=0;i<temp;i++) { ??SPI_Flash_Erase_Sector((secpos+i)*4096);? ?? ?? ?? ?? ?? ? //擦除将要写入数据的扇区? ? } ??//以下代码为将数据写入指定地址的代码 if(NumByteToWrite%2==0) { ??temp=NumByteToWrite/2-1; } else { ??temp=NumByteToWrite/2; } AutoAddressIncrement_WordProgramA(pBuffer[0],pBuffer[1],WriteAddr );? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //开始写数据 for(i=1;i<temp;i++) { ??AutoAddressIncrement_WordProgramB(0,pBuffer[2*i],pBuffer[2*i+1]); } if(NumByteToWrite%2==0) { ??AutoAddressIncrement_WordProgramB(1,pBuffer[NumByteToWrite-2],pBuffer[NumByteToWrite-1]);? ?//结束写数据 } else { ??AutoAddressIncrement_WordProgramB(1,pBuffer[NumByteToWrite-1],0);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//结束写数据 } //写入1Byte数据 //pBuffer:待写的数据 //WriteAddr:待写数据的地址 void Flash_WriteByte(u8* pBuffer,u32 WriteAddr) { u32 secpos; secpos=WriteAddr/4096;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//扇区地址 0~511 for w25x16??4096=4k SPI_Flash_Erase_Sector(secpos);? ?? ?? ?? ?? ?? ?? ?? ?//擦除这个扇区 SPI_FLASH_Write_Enable();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//SET WEL SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//使能器件?? SPIx_ReadWriteByte(SST25_ByteProgram );? ?? ? //发送写页命令 //发送24bit地址? ? SPIx_ReadWriteByte((u8)((WriteAddr)>>16));?? SPIx_ReadWriteByte((u8)((WriteAddr)>>8));?? SPIx_ReadWriteByte((u8)WriteAddr);? ?? ?? ?? ?? ?? ?//发送待写的数据 SPIx_ReadWriteByte(pBuffer[0]); SPI_FLASH_CS=1;? SPI_Flash_Wait_Busy();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //等待写完成 } //擦除整个芯片 //整片擦除时间: //W25X16:25s //W25X32:40s //W25X64:40s //等待时间超长... void SPI_Flash_Erase_Chip(void)?? {? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??? SPI_FLASH_Write_Enable();? ?? ?? ?? ?? ?? ?? ?? ???//SET WEL SPI_Flash_Wait_Busy();?? SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//使能器件?? SPIx_ReadWriteByte(SST25_ChipErase);? ?? ? //发送片擦除命令? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //取消片选? ?? ?? ?? ?? ? SPI_Flash_Wait_Busy();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待芯片擦除结束 } //擦除一个扇区 //Dst_Addr:扇区地址 0~511 for w25x16 //擦除一个山区的最少时间:150ms void SPI_Flash_Erase_Sector(u32 Dst_Addr)?? {?? SPI_FLASH_Write_Enable();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//SET WEL? ?? ?? ??? SPI_Flash_Wait_Busy();?? SPI_FLASH_CS=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//使能器件?? SPIx_ReadWriteByte(SST25_4KByte_BlockERASE);? ?? ?//发送扇区擦除指令 SPIx_ReadWriteByte((u8)((Dst_Addr)>>16));? ?? ?? ?? ?//发送24bit地址? ? SPIx_ReadWriteByte((u8)((Dst_Addr)>>8));?? SPIx_ReadWriteByte((u8)Dst_Addr);? SPI_FLASH_CS=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//取消片选? ?? ?? ?? ?? ? SPI_Flash_Wait_Busy();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待擦除完成 }? //等待空闲 void SPI_Flash_Wait_Busy(void)?? {?? while ((SPI_Flash_ReadSR()&0x01)==0x01);? ?? ? // 等待BUSY位清空 } void SST25V_EBSY(void) { SPI_FLASH_CS=0; SPIx_ReadWriteByte( SST25_EBSY); SPI_FLASH_CS=1;? ? } void SST25V_DBSY(void) { SPI_FLASH_CS=0; SPIx_ReadWriteByte( SST25_DBSY); SPI_FLASH_CS=1;? ? } Flash.h #ifndef __FLASH_SST_H #define __FLASH_SST_H? ?? ?? ?? ?? ?? ?? ?? ? #include "sys.h"? #define? ?? ?SPI_FLASH_CS PAout(9)? ?? ?//选中FLASH? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? #define FLASH_ID 0XBF41? ?? ?? ?? ?? ?? ???//SST25VF016读写 //指令表 #define SST25_ReadData? ?? ?? ?? ?? ?? ?? ?? ?? ?0x03 #define SST25_FastReadData? ?? ?? ?? ?? ?? ?? ? 0x0B #define SST25_4KByte_BlockERASE? ?? ?? ?? ? 0x20 #define SST25_32KByte_BlockErase? ?? ?? ?? ? 0x52 #define SST25_64KByte_BlockErase? ?? ?? ?? ? 0xD8 #define SST25_ChipErase? ?? ?? ?? ?? ?? ?? ?? ?? ?0xC7 #define SST25_ByteProgram? ?? ?? ?? ?? ?? ?? ? 0x02 #define SST25_AAI_WordProgram? ?? ?? ?? ???0xAD #define SST25_ReadStatusReg? ?? ?? ?? ?? ?? ? 0x05 #define SST25_EnableWriteStatusReg? ?? ?? ?0x50 #define SST25_WriteStatusReg? ?? ?? ?? ?? ?? ?0x01 #define SST25_WriteEnable? ?? ?? ?? ?? ?? ?? ???0x06 #define SST25_WriteDisable? ?? ?? ?? ?? ?? ?? ? 0x04 #define SST25_ManufactDeviceID? ?? ?? ?? ???0x90 #define SST25_JedecDeviceID? ?? ?? ?? ?? ?? ? 0x9F #define SST25_EBSY? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???0x70 #define SST25_DBSY? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???0x80? void SPI_Flash_Init(void); u16??SPI_Flash_ReadID(void);? ?? ?? ?? ?? ? //读取FLASH ID u8? ???SPI_Flash_ReadSR(void);? ?? ?? ?? ???//读取状态寄存器 void SPI_FLASH_Write_SR(u8 sr);? ?? ?? ? //写状态寄存器 void SPI_FLASH_Write_Enable(void);? ???//写使能 void SPI_FLASH_Write_Disable(void);? ???//写保护 void SPI_Flash_Read(u8* pBuffer,u16 NumByteToRead);? ?//读取flash void SPI_Flash_Erase_Chip(void);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//整片擦除 void SPI_Flash_Erase_Sector(u32 Dst_Addr);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //扇区擦除 void SPI_Flash_Wait_Busy(void);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待空闲 void SST25V_EBSY(void); void SST25V_DBSY(void); void Flash_WriteByte(u8* pBuffer,u32 WriteAddr);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//写入1Byte数据 void AutoAddressIncrement_WordProgramA(u8 Byte1,u32 Addr);??//地址自动增加的写数据A void AutoAddressIncrement_WordProgramB(u8 state,u8 Byte2);? ???//地址自动增加的写数据B void SPI_Flash_Write(u8 pBuffer[],u16 NumByteToWrite);? ?? ? //结合AB构成的地址自动增加的连续数据的写入 #endif main.c 主函数: #include<stm32f10x_lib.h> #include"common.h" #include"TFTLCD.h" #include"spi.h" #include"key.h" #include"flash.h" const u8 TEXT_Buffer[]={"Chen An SST25VF"};? ?? ? //待写入flash的数据 #define SIZE sizeof(TEXT_Buffer)? ?? ?? ?? ?? ?? ?? ?? ?? ?//计算待写入数据的长度 int main(void) { ? ?? ?? ?u8 key; ? ?? ?? ?u8 datatemp[SIZE];? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//开辟空间用于存放从flash读回的数据 ? ?? ?? ?Stm32_Clock_Init(9);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//系统时钟初始化 ? ?? ?? ?delay_init(72);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//延时函数的初始化 ? ?? ?? ?LCD_Init();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//LCD初始化 ? ?? ?? ?KEY_Init();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//按键初始化 ? ?? ?? ?SPI_Flash_Init();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//SPI关于flash的硬件接口初始化 ? ?? ?? ?POINT_COLOR=RED;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//设置字体颜色 ? ?? ?? ?while(SPI_Flash_ReadID()!=FLASH_ID)? ?? ???//检验flash是否存在 ? ?? ?? ?{ ? ?? ?? ?? ?? ?? ? LCD_ShowString(60,130,"SST25VF Check Failed!"); ? ?? ?? ?? ?? ?? ? delay_ms(500); ? ?? ?? ?} ? ?? ?? ?LCD_ShowString(60,"SST25VF Ready!"); ? ?? ?? ?LCD_ShowString(60,150,"KEY1:Write KEY2:Read"); ? ?? ?? ?POINT_COLOR=BLUE; ? ?? ?? ?while(1) ? ?? ?? ?{ ? ?? ?? ?? ?? ?? ? key=KEY_Scan();? ?? ?? ?? ?? ?? ?? ?//按键扫描 ? ?? ?? ?? ?? ?? ? if(key==1)? ?? ?? ?? ?? ?? ???//按键1按下,开始写数据到flash ? ?? ?? ?? ?? ?? ? { ? ?? ?? ?? ?? ?? ?? ?? ?? ? LCD_Fill(0,170,239,319,WHITE); ? ?? ?? ?? ?? ?? ?? ?? ?? ? LCD_ShowString(60,"Start Write SST25V"); ? ?? ?? ?? ?? ?? ?? ?? ?? ? SPI_Flash_Write((u8*)TEXT_Buffer,1000,SIZE);? ?? ?? ?? ?? ???//写数据 ? ?? ?? ?? ?? ?? ? LCD_ShowString(60,"SST25V Write Finished"); ? ?? ?? ?? ?? ?? ? } ? ?? ?? ?? ?? ?? ? if(key==2)? ?? ?? ?? ?? ?? ?? ?? ?? ? //按键2按下,开始从flash读回数据 ? ?? ?? ?? ?? ?? ? { ? ?? ?? ?? ?? ?? ?? ?? ?? ? LCD_ShowString(60,"Start Read SST25V"); ? ?? ?? ?? ?? ?? ?? ?? ?? ? SPI_Flash_Read(datatemp,SIZE);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//读数据? ? ?? ?? ?? ?? ?? ?? ?? ?? ? LCD_ShowString(60,"The Data Is"); ? ?? ?? ?? ?? ?? ?? ?? ?? ? LCD_ShowString(60,190,datatemp); ? ?? ?? ?? ?? ?? ? }? ?? ? ? ?? ?? ?} } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |