高中生
最后登录1970-1-1
在线时间 小时
注册时间2025-1-4
|
本帖最后由 Rddavid 于 2025-3-4 20:40 编辑
各位老师好,麻烦帮忙审核一下我的代码,谢谢!
1. 代码目的:擦除Flash 地址为0的扇区的数据,然后读取出来确认是否已经完全擦除。
2. 遇到的问题:读取到的数不是0xFF,而是0x2
以下为我的代码截图和代码附件。
----------------------------------------Main函数----------------------------------------
uint32_t buff[4096];
int main(void)
{
uint32_t i=0;
uint32_t id;
LED_GPIO_Config();
USART_Config();
I2C_EE_Init();
SPI_Flash_Init();
LED_G(OFF);
id=SPI_FLASH_Read_ID();
printf("SPI发送后接收到的数据为:0x%x\n",id);
SPI_FLASH_SectorErase(0);
SPI_FLASH_WaitForWriteEnd();
SPI_FLASH_Read(0,buff,4096);
for (i=0;i<4096;i++)
{
printf("0x%x ",buff);
if (i%10==0)
printf("\n");
}
----------------------------------------SPI_Flash.c----------------------------------------
#include "./spi/bsp_spi_flash.h"
static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
static uint32_t SPI_TIMEOUT_UserCallback(uint8_t ErrorCode);
static void SPI_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 打开SPI外设的时钟
FLASH_SPI_APBxClock_FUN (FLASH_SPI_CLK,ENABLE);
// 打开SPI GPIO的时钟
FLASH_SPI_GPIO_APBxClock_FUN (FLASH_SPI_SCL_GPIO_CLK,ENABLE);
// 将SPI SCK配置为复用推挽输出模式
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_SCK_PORT,&GPIO_InitStructure);
// 将SPI MOSI配置为复用推挽输出模式
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_MOSI_PORT,&GPIO_InitStructure);
// 将SPI MISO配置为浮空模式
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_MISO_PORT,&GPIO_InitStructure);
// 将SPI CS配置为推挽输出模式,使用软件控制
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_CS_PORT,&GPIO_InitStructure);
}
static void SPI_MODE_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
/* I2C 配置 */
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //分频因子
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //时钟相位,模式3
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟极性,模式3
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_Mode = SPI_Mode_Master ;//
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//
/* SPI 初始化 */
SPI_Init(FLASH_SPIx, &SPI_InitStructure);
/* I2C 使能 */
SPI_Cmd(FLASH_SPIx, ENABLE);
}
void SPI_Flash_Init(void)
{
SPI_GPIO_Config();
SPI_MODE_Config();
} //封装起来
uint8_t SPI_FLASH_Send_Byte(uint8_t data)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
//发送缓冲区非空就一直等待,直到超时
while(SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_TXE)==RESET)
{
if(SPITimeout--==0)
return SPI_TIMEOUT_UserCallback(0);
}
//发送缓冲区空后,可以往缓冲区写入数据了
SPI_I2S_SendData(FLASH_SPIx, data);
//发送与接收是同步的(注意:时间上其实还是有先后的),接收非空,说明主机的数据已经发送出去了
SPITimeout = SPIT_FLAG_TIMEOUT;
//接收缓冲区为空就一直等待,直到超时
while(SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE)==RESET)
{
if(SPITimeout--==0)
return SPI_TIMEOUT_UserCallback(1);
}
//作为此函数的返回值发送出去
return SPI_I2S_ReceiveData(FLASH_SPIx);
}
uint8_t SPI_FLASH_Read_Byte(void)
{
return SPI_FLASH_Send_Byte(Dummy);
}
uint32_t SPI_FLASH_Read_ID(void)
{
uint32_t Flash_ID;
FLASH_SPI_CS_LOW;
SPI_FLASH_Send_Byte(Read_JEDEC_ID);
Flash_ID=SPI_FLASH_Send_Byte(Dummy);
Flash_ID <<= 8; //左移8位,并且给自己赋值
Flash_ID |=SPI_FLASH_Send_Byte(Dummy);
Flash_ID <<= 8; //左移8位,并且给自己赋值
Flash_ID |=SPI_FLASH_Send_Byte(Dummy);
FLASH_SPI_CS_HIGH;
return Flash_ID;
}
void SPI_FLASH_WriteEnable(void)
{
FLASH_SPI_CS_LOW;
SPI_FLASH_Send_Byte(Write_Enable);
FLASH_SPI_CS_HIGH;
}
//擦除FLASH指定扇区
void SPI_FLASH_SectorErase(uint32_t addr)
{
SPI_FLASH_WriteEnable();
SPI_FLASH_WaitForWriteEnd();
FLASH_SPI_CS_LOW;
SPI_FLASH_Send_Byte(Erase_Sector);
SPI_FLASH_Send_Byte((addr>>16)&0xFF); //先发送高位,右移16位,然后与运算取一个字节。
SPI_FLASH_Send_Byte((addr>>8)&0xFF); //取中间的字节
SPI_FLASH_Send_Byte(addr&0xFF); //取最后一个字节
FLASH_SPI_CS_HIGH;
SPI_FLASH_WaitForWriteEnd();
}
//等待Flash内部操作完成
void SPI_FLASH_WaitForWriteEnd()
{
uint8_t Status_Reg = 0;
FLASH_SPI_CS_LOW;
SPI_FLASH_Send_Byte(Read_Status);
do
{
Status_Reg = SPI_FLASH_Send_Byte(Dummy);
} while ((Status_Reg &0x01) == 1); //取Status_Reg的最低位,如果等于1,说明Flash一直在忙,需要继续循环。
}
//读取FLASH的内容
void SPI_FLASH_Read(uint32_t addr,uint32_t *buffer,uint32_t numByteToRead)
{
FLASH_SPI_CS_LOW;
SPI_FLASH_Send_Byte(Read_Data);
SPI_FLASH_Send_Byte((addr>>16)&0xFF);
SPI_FLASH_Send_Byte((addr>>8)&0xFF);
SPI_FLASH_Send_Byte(addr&0xFF); //分三次发送要读取的地址
while(numByteToRead--)
{
*buffer = SPI_FLASH_Send_Byte(Dummy); //类似读flash的id号,发送dummy数据即可。
buffer++;
}
FLASH_SPI_CS_HIGH;
}
static uint32_t SPI_TIMEOUT_UserCallback(uint8_t ErrorCode)
{
FLASH_ERROR("SPI 等待超时!ErrorCode = %d ", ErrorCode);
return 0;
}
----------------------------------------SPI_Flash.h----------------------------------------
#ifndef __BSP_SPI_FLASH_H
#define __BSP_SPI_FLASH_H
#include "stm32f10x.h"
#include "stdio.h"
//SPI引脚定义
#define FLASH_SPIx SPI1
#define FLASH_SPI_APBxClock_FUN RCC_APB2PeriphClockCmd
#define FLASH_SPI_CLK RCC_APB2Periph_SPI1
//SPI GPIO引脚宏定义
#define FLASH_SPI_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define Use_ZhiNanZhe_PCB 1
#if (Use_ZhiNanZhe_PCB ==1)
#define FLASH_SPI_SCL_GPIO_CLK (RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC)
#define FLASH_SPI_CS_PORT GPIOC
#define FLASH_SPI_CS_PIN GPIO_Pin_0
#else
#define FLASH_SPI_SCL_GPIO_CLK RCC_APB2Periph_GPIOA
#define FLASH_SPI_CS_PORT GPIOA
#define FLASH_SPI_CS_PIN GPIO_Pin_4
#endif
#define FLASH_SPI_SCK_PORT GPIOA
#define FLASH_SPI_SCK_PIN GPIO_Pin_5
#define FLASH_SPI_MOSI_PORT GPIOA
#define FLASH_SPI_MOSI_PIN GPIO_Pin_7
#define FLASH_SPI_MISO_PORT GPIOA
#define FLASH_SPI_MISO_PIN GPIO_Pin_6
#define FLASH_SPI_CS_PORT GPIOC
#define FLASH_SPI_CS_PIN GPIO_Pin_0
#define FLASH_SPI_CS_LOW GPIO_ResetBits(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN);
#define FLASH_SPI_CS_HIGH GPIO_SetBits(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN);
//等待超时时间
#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000)
#define SPIT_LONG_TIMEOUT ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))
#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 0x00
#define Read_JEDEC_ID 0x9F
#define Erase_Sector 0x20
#define Read_Status 0x05
#define Read_Data 0x03
#define Write_Enable 0x06
void SPI_Flash_Init(void);
uint8_t SPI_FLASH_Send_Byte(uint8_t data);
uint8_t SPI_FLASH_Read_Byte(void);
uint32_t SPI_FLASH_Read_ID(void);
void SPI_FLASH_Read(uint32_t addr,uint32_t *buffer,uint32_t numByteToRead);
void SPI_FLASH_SectorErase(uint32_t addr);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WaitForWriteEnd();
#endif /*__BSP_SPI_FLASH_H*/
|
|