spi flash驱动

接口:

//擦除FLASH指定扇区
extern void SPI_Erase_Sector(uint32_t addr);

//擦除FLASH指定Block32
extern void SPI_Erase_Block32(uint32_t addr);

//擦除FLASH指定Block64
extern void SPI_Erase_Block64(uint32_t addr);

//spi_FLash初始化
extern void Spi_Flash_init(void);

//读取FLASH的内容
extern void SPI_Read_Data(uint32_t addr,uint8_t *readBuff,uint32_t numByteToRead);

//连续写入多字节:不用考虑是否达到边界的问题
extern void SPI_Write_Datas(uint32_t WriteAddr ,uint8_t *writeBuff,uint32_t numByteToWrite);

//FLASH进入deep_power_down模式
extern void SPI_EnterDeepPowerDownMode(void);

//FLASH进入deep_power_down模式
extern void SPI_ExitDeepPowerDownMode(void);


extern void spiReadWrtTest(void);

.c


#ifndef LIB_DRIVER_EX_FLASH
#define LIB_DRIVER_EX_FLASH
#include "stm32l1xx_hal.h"
#include "Driver_bord.h"
#include "Driver_exFlash.h"
#include "Driver_configer.h"
#include "string.h"
#endif

#define SPI_MOSI_PIN      			GPIO_PIN_15        	//掉电保持Flash片选引脚号
#define SPI_MISO_PIN      			GPIO_PIN_13        	//掉电保持Flash片选引脚号
#define SPI_SCK_PIN       			GPIO_PIN_14        	//掉电保持Flash片选引脚号
#define SPI_NSS_PIN       			GPIO_PIN_12        	//掉电保持Flash片选引脚号

#define SPI_MOSI_GPIO_PORT          GPIOB   			//
#define SPI_MISO_GPIO_PORT          GPIOB   			//
#define SPI_SCK_GPIO_PORT          	GPIOB   			//
#define SPI_NSS_GPIO_PORT          	GPIOB   			//

#define SOFTWARE_SPI_MOSI_SET()  	HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET)  
#define SOFTWARE_SPI_MOSI_CLR()  	HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET)  
#define SOFTWARE_SPI_SCLK_SET()   	HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET)  
#define SOFTWARE_SPI_SCLK_CLR()   	HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET)  
#define SOFTWARE_SPI_Read()  		HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN) 
#define SPI_NSS_H   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET)  
#define SPI_NSS_L   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET)


//
// Function name  :	Spi_Flash_init
// Function capacity  :	spi_FLash初始化
// Parameter declare  :
// parameter 1: 	 选择的模式,0-低速模式,1-高速模式
//	......
// Return value   : void
// Designed idea  : 
// Author         :	zhangjun
// Creation date: 2016.7.1
//
void Spi_Flash_init(void)   
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
    GPIO_InitStruct.Pin = SPI_NSS_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = SPI_SCK_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStruct);	

    GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);
	
    GPIO_InitStruct.Pin = SPI_MISO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct); 	
}

//
// Function name  :	SPI_2_Rx
// Function capacity  :	SPI2串口接收数据   
// Parameter declare  :   void
//	......
// Return value   : 读取的数据
// Designed idea  : 防止进入死循环,一直等待接收数据
// Author         :	zhangjun
// Creation date: 2016.7.1
//  

void software_spi00_send_dat(unsigned char dat)
{
    unsigned char temp;
	

	temp = dat;

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x80)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x40)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x20)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x10)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x08)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x04)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x02)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
	SOFTWARE_SPI_SCLK_SET();

	SOFTWARE_SPI_SCLK_CLR();
	if(temp&0x01)			SOFTWARE_SPI_MOSI_SET();
	else					SOFTWARE_SPI_MOSI_CLR();
    SOFTWARE_SPI_SCLK_SET();
	
    SOFTWARE_SPI_SCLK_CLR();//end
}

void software_spi00_send_buf(unsigned char *dat,unsigned int len)
{
    unsigned int i;
    unsigned char temp;
	
    for (i=0; i<len; i++)
    {
        temp = dat[i];

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x80)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x40)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x20)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x10)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x08)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x04)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x02)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();

        SOFTWARE_SPI_SCLK_CLR();
        if(temp&0x01)			SOFTWARE_SPI_MOSI_SET();
        else					SOFTWARE_SPI_MOSI_CLR();
        SOFTWARE_SPI_SCLK_SET();
    }
	
    SOFTWARE_SPI_SCLK_CLR();//end
}

unsigned char software_spi00_receiver_dat(void)
{
    unsigned char dat=0;

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x80;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x40;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x20;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x10;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x08;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x04;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x02;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_SET();
    if(SOFTWARE_SPI_Read())		dat|=0x01;
    SOFTWARE_SPI_SCLK_CLR();

    SOFTWARE_SPI_SCLK_CLR();//end
    return dat;
}

void  software_spi00_receiver_buf(uint8_t *buf,uint32_t len)
{
    uint32_t i;
    for (i=0; i<len; i++)
    {
        buf[i] = software_spi00_receiver_dat();
    }

}

//读取ID号
uint32_t SPI_Read_ID(void)
{
    uint32_t flash_id;

    //片选使能
    SPI_NSS_L;
	
    software_spi00_send_dat(READ_JEDEC_ID);

    flash_id = software_spi00_receiver_dat();
    flash_id <<= 8;
    flash_id |= software_spi00_receiver_dat(); 
    flash_id <<= 8;
    flash_id |= software_spi00_receiver_dat(); 

    SPI_NSS_H;

    return flash_id;
}

//FLASH写入使能
void SPI_Write_Enable(void)
{
        //片选使能
    SPI_NSS_L;
	
    software_spi00_send_dat(WRITE_ENABLE);   
	
    SPI_NSS_H;  
}



//擦除FLASH指定扇区
void SPI_Erase_Sector(uint32_t addr)
{   
	SPI_Write_Enable();	//片选使能
	
	SPI_NSS_L;
	
	software_spi00_send_dat(ERASE_SECTOR);
	software_spi00_send_dat((addr>>16)&0xff);
	software_spi00_send_dat((addr>>8)&0xff); 
	software_spi00_send_dat(addr&0xff); 

	SPI_NSS_H;  
	
	SPI_WaitForWriteEnd();	

}

//擦除FLASH指定Block32
void SPI_Erase_Block32(uint32_t addr)
{   
	SPI_Write_Enable();
		//片选使能
	SPI_NSS_L;
	
	software_spi00_send_dat(ERASE_BLOCK_32);
	software_spi00_send_dat((addr>>16)&0xff);
	software_spi00_send_dat((addr>>8)&0xff); 
	software_spi00_send_dat(addr&0xff); 

	SPI_NSS_H;  
	
	SPI_WaitForWriteEnd();		

}

//擦除FLASH指定Block64
void SPI_Erase_Block64(uint32_t addr)
{   
	SPI_Write_Enable();
		//片选使能
	SPI_NSS_L;
	
	software_spi00_send_dat(ERASE_BLOCK_64);
	software_spi00_send_dat((addr>>16)&0xff);
	software_spi00_send_dat((addr>>8)&0xff); 
	software_spi00_send_dat(addr&0xff); 

	SPI_NSS_H;  
	
	SPI_WaitForWriteEnd();	
}



//读取FLASH的内容
void SPI_Read_Data(uint32_t addr,uint8_t *readBuff,uint32_t numByteToRead)
{
	SPI_Write_Enable();
	
	SPI_NSS_L;
	
	software_spi00_send_dat(READ_DATA);
	software_spi00_send_dat((addr>>16)&0xff);
	software_spi00_send_dat((addr>>8)&0xff); 
	software_spi00_send_dat(addr&0xff); 
	
	software_spi00_receiver_buf(readBuff,numByteToRead);

	SPI_NSS_H;  
	
	SPI_WaitForWriteEnd();	
}





//向FLASH写入内容
void SPI_Write_Data(uint32_t addr,uint8_t *writeBuff,uint32_t numByteToWrite)
{
	SPI_Write_Enable();
	
	SPI_NSS_L;
	
	software_spi00_send_dat(WRITE_DATA);
	software_spi00_send_dat((addr>>16)&0xff);
	software_spi00_send_dat((addr>>8)&0xff); 
	software_spi00_send_dat(addr&0xff); 
	
	software_spi00_send_buf(writeBuff,numByteToWrite);

	SPI_NSS_H;  
	
	SPI_WaitForWriteEnd();	
}


//连续写入多字节:不用考虑是否达到边界的问题,写入字节数也没有限制(当然要小于FLASH容量)
void SPI_Write_Datas(uint32_t WriteAddr ,uint8_t *writeBuff,uint32_t numByteToWrite)
{
	unsigned char NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
	
    SPI_Write_Enable();

    SPI_NSS_L;        //片选使能		
	
	Addr = WriteAddr  % FLASH_PAGE_MAX;
	count = FLASH_PAGE_MAX - Addr;					//差多少可以对齐数据页地址
	
	NumOfPage = numByteToWrite / FLASH_PAGE_MAX;	/*计算出要写多少整数页*/
	
	NumOfSingle = numByteToWrite % FLASH_PAGE_MAX;	/*mod 运算求余,计算出剩余不满一页的字节数*/
	
	if (Addr == 0)		/* Addr=0,则 WriteAddr 刚好按页对齐 aligned */
	{
		if(NumOfPage == 0)
		{
			SPI_Write_Data( WriteAddr,writeBuff,numByteToWrite);
		}
		else
		{
			while(NumOfPage--)										/*先把整数页都写了*/
			{
				SPI_Write_Data( WriteAddr,writeBuff,FLASH_PAGE_MAX); 
				writeBuff = writeBuff + FLASH_PAGE_MAX; 
				WriteAddr = WriteAddr + FLASH_PAGE_MAX; 		
			}
			SPI_Write_Data( WriteAddr,writeBuff,NumOfSingle);		/*若有多余的不满一页的数据,把它写完*/
		}
	}
	else		/* 若地址与 SPI_FLASH_PageSize 不对齐 */
	{
		if(NumOfPage == 0)
		{
			if(NumOfSingle > count)				/*当前页剩余的 count 个位置比 NumOfSingle 小,一页写不完*/
			{
				temp = NumOfSingle - count;
				SPI_Write_Data( WriteAddr,writeBuff,count);				/*先写满当前页*/
				WriteAddr += count;
				writeBuff += count;
				
				SPI_Write_Data( WriteAddr,writeBuff,temp);			
			}
			else								/*当前页剩余的 count 个位置能写完 NumOfSingle 个数据*/
			{
				SPI_Write_Data( WriteAddr,writeBuff,numByteToWrite);
			}
		}
		else									/* numByteToWrite > FLASH_PAGE_MAX */
		{
			numByteToWrite = numByteToWrite - count;			
			NumOfPage = numByteToWrite / FLASH_PAGE_MAX;	/*计算出要写多少整数页*/			
			NumOfSingle = numByteToWrite % FLASH_PAGE_MAX;	/*mod 运算求余,计算出剩余不满一页的字节数*/			
			
			SPI_Write_Data( WriteAddr,writeBuff,count);
			WriteAddr += count;
			writeBuff += count;			
					
			while(NumOfPage--)										/*先把整数页都写了*/
			{
				SPI_Write_Data( WriteAddr,writeBuff,FLASH_PAGE_MAX); 
				writeBuff = writeBuff + FLASH_PAGE_MAX; 
				WriteAddr = WriteAddr + FLASH_PAGE_MAX; 		
			}
			if(NumOfSingle != 0)
			{
				SPI_Write_Data( WriteAddr,writeBuff,NumOfSingle);		/*若有多余的不满一页的数据,把它写完*/
			}
		}		
	}
	
    SPI_NSS_H;	
	
}


//等待FLASH内部时序操作完成
void SPI_WaitForWriteEnd(void)
{
    uint8_t status_reg = 0;

    //片选使能
    SPI_NSS_L;

    software_spi00_send_dat(READ_STATUS);

    do
    {   
		status_reg = software_spi00_receiver_dat();
    }
    while((status_reg & 0x01) == 1);

    SPI_NSS_H;  
}

FLASH进入deep_power_down模式
//void SPI_EnterDeepPowerDownMode(void)
//{
//	SPI_Write_Enable();
//	
//    //片选使能
//    SPI_NSS_L;

//    software_spi00_send_dat(DEEP_POWER_DOWN);

//    SPI_NSS_H; 
//}

FLASH进入deep_power_down模式
//void SPI_ExitDeepPowerDownMode(void)
//{
//	SPI_Write_Enable();
//	
//    //片选使能
//    SPI_NSS_L;

//    software_spi00_send_dat(EXIT_DEEP_POWER_DOWN);

//    SPI_NSS_H; 

//	SPI_WaitForWriteEnd();		
//}


//#define SPI_flash_Test 1

//#ifdef SPI_flash_Test
//unsigned char spiTestBuf[1500];

//void spiReadWrtTest(void)
//{
//	unsigned short i;
//	
//	SPI_Read_Data(1024,spiTestBuf,sizeof(spiTestBuf));	
//	
//	for(i=0;i<1;i++)
//	{
//		SPI_Erase_Block32(0 + i*64*1024);
//	}
//	
//	memset(spiTestBuf,0x55,sizeof(spiTestBuf));
//	
//	SPI_Write_Datas(1024,spiTestBuf,sizeof(spiTestBuf));
//	memset(spiTestBuf,0,sizeof(spiTestBuf));
//	SPI_Read_Data(1024,spiTestBuf,sizeof(spiTestBuf));
//	
//	SPI_Write_Datas(2000,spiTestBuf,sizeof(spiTestBuf));\
//	memset(spiTestBuf,0,sizeof(spiTestBuf));
//	SPI_Read_Data(2000,spiTestBuf,sizeof(spiTestBuf));	
//	
//	for(i=0;i<1;i++)
//	{
//		SPI_Erase_Block32(0 + i*64*1024);
//	}

//	memset(spiTestBuf,0xaa,sizeof(spiTestBuf));
//	SPI_Write_Datas(1024,spiTestBuf,sizeof(spiTestBuf));
//	SPI_Read_Data(1024,spiTestBuf,sizeof(spiTestBuf));	
//	
//	SPI_Write_Datas(2000,spiTestBuf,sizeof(spiTestBuf));
//	SPI_Read_Data(2000,spiTestBuf,sizeof(spiTestBuf));	
//}
//#endif


.h
···
#ifndef DRIVER_EX_FLASH_H
#define DRIVER_EX_FLASH_H

#endif

#include “stdint.h”

#define DUMMY 0x00
#define READ_JEDEC_ID 0x9f
#define ERASE_SECTOR 0x20
#define ERASE_BLOCK_32 0x52
#define ERASE_BLOCK_64 0xd8
#define READ_STATUS 0x05
#define READ_DATA 0x03
#define WRITE_ENABLE 0x06
#define WRITE_DATA 0x02

#define DEEP_POWER_DOWN 0xB9
#define EXIT_DEEP_POWER_DOWN 0xAB

#define FLASH_PAGE_MAX 256

#ifdef LIB_DRIVER_EX_FLASH

void SPI_WaitForWriteEnd(void);

#else

//擦除FLASH指定扇区
extern void SPI_Erase_Sector(uint32_t addr);

//擦除FLASH指定Block32
extern void SPI_Erase_Block32(uint32_t addr);

//擦除FLASH指定Block64
extern void SPI_Erase_Block64(uint32_t addr);

//spi_FLash初始化
extern void Spi_Flash_init(void);

//读取FLASH的内容
extern void SPI_Read_Data(uint32_t addr,uint8_t *readBuff,uint32_t numByteToRead);

//连续写入多字节:不用考虑是否达到边界的问题
extern void SPI_Write_Datas(uint32_t WriteAddr ,uint8_t *writeBuff,uint32_t numByteToWrite);

//FLASH进入deep_power_down模式
extern void SPI_EnterDeepPowerDownMode(void);

//FLASH进入deep_power_down模式
extern void SPI_ExitDeepPowerDownMode(void);

extern void spiReadWrtTest(void);

#endif

···

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值