我用的是野火的F429-V1的单片机
**.h相关宏定义**
#ifndef __BSP_SPI_FLASH_H
#define __BSP_SPI_FLASH_H
#include "stm32f4xx.h"
#include <stdio.h>
#define FLASH_SPI SPI5
#define FLASH_SPI_CLK RCC_APB2Periph_SPI5
#define RCC_APB_CLOCK_FUN RCC_APB2PeriphClockCmd
#define FLASH_SPI_CS_GPIO_PORT GPIOF
#define FLASH_SPI_CS_GPIO_CLK RCC_AHB1Periph_GPIOF
#define FLASH_SPI_CS__PIN GPIO_Pin_6
//#define FLASH_SPI_CS__AF GPIO_AF_SPI5
//#define FLASH_SPI_CS__SOURCE GPIO_PinSource6
#define FLASH_SPI_SCK_GPIO_PORT GPIOF
#define FLASH_SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOF
#define FLASH_SPI_SCK__PIN GPIO_Pin_7
#define FLASH_SPI_SCK__AF GPIO_AF_SPI5
#define FLASH_SPI_SCK__SOURCE GPIO_PinSource7
#define FLASH_SPI_MISO_GPIO_PORT GPIOF
#define FLASH_SPI_MISO_GPIO_CLK RCC_AHB1Periph_GPIOF
#define FLASH_SPI_MISO__PIN GPIO_Pin_8
#define FLASH_SPI_MISO__AF GPIO_AF_SPI5
#define FLASH_SPI_MISO__SOURCE GPIO_PinSource8
#define FLASH_SPI_MOSI_GPIO_PORT GPIOF
#define FLASH_SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOF
#define FLASH_SPI_MOSI__PIN GPIO_Pin_9
#define FLASH_SPI_MOSI__AF GPIO_AF_SPI5
#define FLASH_SPI_MOSI__SOURCE GPIO_PinSource9
//拉高片选宏定义,控制CS(NSS)引脚输出高电平
#define SPI_FLASH_CS_HIGH() {FLASH_SPI_CS_GPIO_PORT->BSRRL=FLASH_SPI_CS__PIN;}
//拉低片选宏定义,控制CS(NSS)引脚输出低电平
#define SPI_FLASH_CS_LOW() {FLASH_SPI_CS_GPIO_PORT->BSRRH=FLASH_SPI_CS__PIN;}
/*等待超时时间*/
#define SPI_FLAG_TIMEOUT ((uint32_t)0x1000)
#define SPI_LONG_TIMEOUT ((uint32_t)(10 * SPI_FLAG_TIMEOUT))
/*信息输出*/
#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)
//命令定义
#define DUMMY 0xFF
#define JEDEC_ID 0X9F
#define ERACE 0x20
#define READ_DATA 0x03
#define READ_STATUS 0x05
#define WRITE_ENABLE 0x06
#define PAGE_PROGRAM 0x02
void FLASH_SPI_Config(void);
uint32_t Read_Device_ID(void);
void erace_setor(uint32_t addr);
void Read_buffer(uint8_t *pdata,uint32_t addr,uint32_t numByteTorRead);
void Write_buffer(uint8_t *pdata,uint32_t addr,uint32_t numByteTorWrite);
#endif /* __BSP_SPI_FLASH_H */
/**.c文件详情/**
#include "bsp_spi_flash.h"
#include "stm32f4xx_gpio.h"
static uint8_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
static void Wait_for_Ready(void);
uint32_t time_out = SPI_LONG_TIMEOUT;
/**
* @brief 初始化FALSH的SPI的引脚
* @param 无
* @retval 无
*/
void FLASH_SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
//1.初始化GPIO
RCC_AHB1PeriphClockCmd(FLASH_SPI_CS_GPIO_CLK|FLASH_SPI_SCK_GPIO_CLK|FLASH_SPI_MISO_GPIO_CLK|FLASH_SPI_MOSI_GPIO_CLK,ENABLE);
/* 连接 引脚源*/
GPIO_PinAFConfig(FLASH_SPI_SCK_GPIO_PORT,FLASH_SPI_SCK__SOURCE,FLASH_SPI_SCK__AF);
/* 连接 */
GPIO_PinAFConfig(FLASH_SPI_MISO_GPIO_PORT,FLASH_SPI_MISO__SOURCE,FLASH_SPI_MISO__AF);
GPIO_PinAFConfig(FLASH_SPI_MOSI_GPIO_PORT,FLASH_SPI_MOSI__SOURCE,FLASH_SPI_MOSI__AF);
/* 使能 SPI 时钟 */
RCC_APB_CLOCK_FUN(FLASH_SPI_CLK, ENABLE);
/* GPIO初始化 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
/* 配置SCK引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK__PIN ;
GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
/* 配置MISO引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO__PIN;
GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
/* 配置MOSI引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI__PIN;
GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* CS引脚 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
/* 配置CS引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS__PIN ;
GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
//2.配置SPI工作模式
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge ;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High ;
SPI_InitStructure.SPI_CRCPolynomial = 0 ; //不需要CRC校验
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b ;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB ;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master ;
SPI_Init(FLASH_SPI,&SPI_InitStructure);
SPI_Cmd(FLASH_SPI,ENABLE);
SPI_FLASH_CS_HIGH();
}
//3.接收及发送数据
uint8_t Read_Write_Byte(uint8_t data)
{
time_out = SPI_FLAG_TIMEOUT;
while(SPI_GetFlagStatus(FLASH_SPI,SPI_FLAG_TXE) == RESET)
{
if((time_out --)==0) return SPI_TIMEOUT_UserCallback(0);
}
//发送缓冲区为空
SPI_I2S_SendData(FLASH_SPI,data);
time_out = SPI_FLAG_TIMEOUT;
//接收缓冲区为空,死循环
while(SPI_GetFlagStatus(FLASH_SPI,SPI_FLAG_RXNE) == RESET)
{
if((time_out --)==0) return SPI_TIMEOUT_UserCallback(1);
//....循环
}
return SPI_I2S_ReceiveData(FLASH_SPI);
}
//4.获取FLASH ID
uint32_t Read_Device_ID(void)
{
uint8_t temp[3];
//拉低片选
SPI_FLASH_CS_LOW();
Read_Write_Byte(JEDEC_ID);
temp[0] = Read_Write_Byte(DUMMY);
temp[1] = Read_Write_Byte(DUMMY);
temp[2] = Read_Write_Byte(DUMMY);
//拉高片选
SPI_FLASH_CS_HIGH();
return temp[0]<<16|temp[1]<<8|temp[2];
}
//5.Write_Enable
void Write_Enable(void)
{
//拉低片选
SPI_FLASH_CS_LOW();
Read_Write_Byte(WRITE_ENABLE);
//拉高片选
SPI_FLASH_CS_HIGH();
}
//5.擦除FLASH
void erace_setor(uint32_t addr)
{
Write_Enable();
Wait_for_Ready();
//拉低片选
SPI_FLASH_CS_LOW();
Read_Write_Byte(ERACE);
Read_Write_Byte((addr>>16)&0xFF);
Read_Write_Byte((addr>>8)&0xFF);
Read_Write_Byte(addr&0xFF);
//拉高片选
SPI_FLASH_CS_HIGH();
//等待内部时序(等待擦除完成)
}
//5.读取数据
void Read_buffer(uint8_t *pdata,uint32_t addr,uint32_t numByteTorRead)
{
Wait_for_Ready();
//拉低片选
SPI_FLASH_CS_LOW();
Read_Write_Byte(READ_DATA);
Read_Write_Byte((addr>>16)&0xFF);
Read_Write_Byte((addr>>8)&0xFF);
Read_Write_Byte(addr&0xFF);
while(numByteTorRead--)
{
*pdata = Read_Write_Byte(DUMMY);
pdata++;
}
//拉高片选
SPI_FLASH_CS_HIGH();
}
//6.获取寄存器状态
void Wait_for_Ready(void)
{
uint8_t reg_status = 0x01;
while(reg_status & 0x01)
{
//拉低片选
SPI_FLASH_CS_LOW();
//读状态寄存器
Read_Write_Byte(READ_STATUS);
reg_status = Read_Write_Byte(DUMMY);
//拉高片选
SPI_FLASH_CS_HIGH();
}
}
//5.读取数据 最多写256个数据
void Write_buffer(uint8_t *pdata,uint32_t addr,uint32_t numByteTorWrite)
{
Write_Enable();
Wait_for_Ready();
//拉低片选
SPI_FLASH_CS_LOW();
Read_Write_Byte(PAGE_PROGRAM);
Read_Write_Byte((addr>>16)&0xFF);
Read_Write_Byte((addr>>8)&0xFF);
Read_Write_Byte(addr&0xFF);
//拉高片选
SPI_FLASH_CS_HIGH();
while(numByteTorWrite--)
{
Read_Write_Byte(*pdata);
pdata++;
}
}
/**
* @brief Basic management of the timeout situation.
* @param errorCode:错误代码,可以用来定位是哪个环节出错.
* @retval 返回0,表示IIC读取失败.
*/
static uint8_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
/* Block communication and all processes */
FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);
return 0xFF;
}
/**主函数main.c/**
#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include "bsp_spi_flash.h"
uint8_t readBuff[4096] = {0x0};
uint8_t writeBuff[4096] = {0x0};
//拉高片选宏定义
#define CS_HIGH_DISABLE() GPIO_SetBites(FLASH_SPI_CS_GPIO_PORT,FLASH_SPI_CS__PIN)
//拉低片选宏定义
#define CS_LOW_ENABLE() GPIO_ResetBites(FLASH_SPI_CS_GPIO_PORT,FLASH_SPI_CS__PIN)
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
uint32_t device_id = 0;
uint32_t i=0;
/*初始化USART 配置模式为 115200 8-N-1,中断接收*/
Debug_USART_Config();
FLASH_SPI_Config();
/* 发送一个字符串 */
Usart_SendString( DEBUG_USART,"\n这是一个FLASH实验\n");
printf("\n这是一个FLASH实验\n");
device_id = Read_Device_ID();
printf("devcie_id = 0x%x",device_id);
erace_setor(0x00);
//读出擦除后的数据
Read_buffer(readBuff,0x00,4096);
printf("\n**************读出擦除后的数据***************\n");
for(i=0;i<4096;i++)
printf(" 0x%x ",readBuff[i]);
for(i=0;i<256;i++)
writeBuff[i] = i;
Write_buffer(writeBuff,0x00,256);
//读出擦除后的数据
Read_buffer(readBuff,0x00,256);
printf("\n**************读出写入后的数据***************\n");
for(i=0;i<256;i++)
printf(" 0x%x ",readBuff[i]);
while(1)
{
}
}
/遇到的问题/
擦除后的数据和写入的数据都是0xff,没搞明白是怎么一个问题(初学者)