加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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);

? ?? ?? ?? ?? ?? ? }? ?? ?
? ?? ?? ?}
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读