STM32F407-SPI-flash存储-01
flash芯片
芯片大小
本例子使用的flash芯片是W25Q128
它内部可以存储128M bit,即它的存储为16MB
flash与eeprom不一样,写入数据前需要先擦除flash;
擦除操作
4KB为一个扇区;最小擦除空间为一个扇区;
可以按块擦除;一块为64KB
写入操作
写入时按页写入;一页为256字节;
支持的SPI模式
该flash支持的SPI模式为模式0或模式3
使用SPI与flash通讯
例子:获取flash的ID
/*
SPI1_CLK PB3
SPI1_MISO PB4
SPI1_MOSI PB5
SPI_CS PG8
*/
void My_Flash_Init(void)
{
My_GPIO_Config();
My_SPI_Config();
}
static void My_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOG,ENABLE); //使能GPIO 时钟
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1); //配置GPIO的复用功能为SPI1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO引脚,并配置为复用模式
//使用软件控制CS引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
static void My_SPI_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); //使能 SPI 时钟
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ; //SPI工作模式 全双工
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ; // spi的时钟几分频 SPI1 在 APB2时钟上
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //mode 0
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //mode 0
SPI_InitStructure.SPI_CRCPolynomial = 0;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b ; //SPI 为8位
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB ; //高位先出
SPI_InitStructure.SPI_Mode = SPI_Mode_Master ; //主机
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ; //软件片选
SPI_Init(SPI1, &SPI_InitStructure); /* I2C1 初始化 */
SPI_Cmd(SPI1, ENABLE);
}
uint8_t My_Flash_Read_ID(void)
{
uint8_t id;
//控制片选引脚
FLASH_SPI_CS_LOW();
//指令代码
SPI_FLASH_ByteWrite(FLASH_ORDER_ReleasePowerDown);
SPI_FLASH_ByteWrite(DUMMY);
SPI_FLASH_ByteWrite(DUMMY);
SPI_FLASH_ByteWrite(DUMMY);
//接收读取到的内容
id = SPI_FLASH_ByteWrite(DUMMY);
FLASH_SPI_CS_HIGH();
return id;
}
static uint8_t SPI_FLASH_ByteWrite(uint8_t data)
{
uint8_t re_data;
//等待TXE标志
uint16_t SPITimeout = SPIT_FLAG_TIMEOUT;
while(SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET ) //等待发送完成标志立起来
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);
}
SPI_I2S_SendData(SPI1, data); //发送数据
//等待RXNE标志 来确认发送完成,及准备读取数据
SPITimeout = SPIT_FLAG_TIMEOUT;
while(SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == RESET ) //等待接收到数据
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(2);
}
re_data = SPI_I2S_ReceiveData(SPI1); //接收数据
return re_data;
}
static uint8_t SPI_TIMEOUT_UserCallback(uint8_t errno)
{
FLASH_ERROR("timeout !! errno:%d\n",errno);
return errno;
}
#define FLASH_SPI_CS_LOW() GPIO_ResetBits(GPIOG,GPIO_Pin_8)
#define FLASH_SPI_CS_HIGH() GPIO_SetBits(GPIOG,GPIO_Pin_8)
#define SPIT_FLAG_TIMEOUT 0xFFFF
/*SPI 指令*/
#define FLASH_ORDER_ReleasePowerDown 0xAB
#define DUMMY 0xFF
/*信息输出*/
#define FLASH_DEBUG_ON 0
#define FLASH_INFO(fmt,arg...) printf("<<-FLASH-INFO->> "fmt"\n",##arg)
#define FLASH_ERROR(fmt,arg...) printf("<<-FLASH-ERROR->> "fmt"\n",##arg)
#define FLASH_DEBUG(fmt,arg...) do{\
if(FLASH_DEBUG_ON)\
printf("<<-FLASH-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
}while(0)