接口:
//擦除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
···