研究生
最后登录1970-1-1
在线时间 小时
注册时间2023-3-23
|
本帖最后由 微信用户-CP1Las 于 2026-1-23 17:17 编辑
各位老师好,麻烦帮忙审核一下我的代码,谢谢!
09 flash.zip
(8.62 MB, 下载次数: 0)
1. 代码目的:擦除Flash 地址为0的扇区的数据,然后读取出来确认是否已经完全擦除。
2. 遇到的问题:
- 读取到的数不是0xFF,而是0x00
- 单步调试或者在等待函数后面加延时的时候数组的前面几项可以显示0xff,但是绝大部分还是0x00
/*************************************main函数**********************************************/
- #include "stm32f10x.h"
- #include "bsp_spi_flash.h"
- #include "bsp_usart.h"
- #include "delay.h"
- uint8_t buff[4096];
- int main (void)
- {
- uint32_t id;
- uint16_t i;
- SPI_Flash_Init();
- USART_Config();
- id=SPI_Read_ID();
- printf("ID=%d \n",id);
- SPI_ERASE_SECTRO(0);
- SPI_WaitForWriteEnd();
- delay_ms(500);
- SPI_Read_Data(0,buff,4096);
- for(i=0;i<4096;i++)
- {
- printf("0x%x",buff[i]);
- if (i%10==0)
- {
- printf("\r\n");
- }
- }
- while (1)
- {
- }
- }
复制代码 /************************************bsp_spi_flash.c**********************************************/
- #include "bsp_spi_flash.h"
- //注意这个变量只在本文件中存在,但是生命周期是整个程序执行时间
- static __IO uint32_t SPITimeout=SPI_FLAG_TIMEOUT;
- void SPI_Flash_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- SPI_InitTypeDef SPI_InitStructure;
- FLASH_SPI_APBxClock_FUN(FLASH_SPI_CLK, ENABLE);
- FLASH_SPI_CS_APBxClock_FUN(FLASH_SPI_CS_CLK, ENABLE);
- FLASH_SPI_SCK_APBxClock_FUN(FLASH_SPI_SCK_CLK, ENABLE);
- FLASH_SPI_MOSI_APBxClock_FUN(FLASH_SPI_MOSI_CLK, ENABLE);
- FLASH_SPI_MISO_APBxClock_FUN(FLASH_SPI_MISO_CLK, ENABLE);
- // cs,普通io模式
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
- // scl
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);
- // mosi
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);
- // miso
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(FlASH_SPI_MISO_PORT, &GPIO_InitStructure);
- /*停止信号,cs引脚为高电平*/
- FLASH_SPI_CS_HIGH();
- /*spi的模式配置,stm32支持spi模式1和模式3,分别配置CPOL CPHA*/
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; // 波特率分频数
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 初始化空闲状态下的电频为1
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 初始化检测边缘时高电平
- SPI_InitStructure.SPI_CRCPolynomial = 0; // 不使用crc校验值。大部分的spi设备都不支持crc,具体请查看数据手册
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 选择双线全双工
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 配置为msb先行,就是高位先行
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // spi的主从模式选择
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 软件控制spi
- SPI_Init(FLASH_SPIx, &SPI_InitStructure);
- SPI_Cmd(FLASH_SPIx, ENABLE);
- }
- static uint32_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
- {
- FLASH_ERROR("SPI 等待超时! errorCode = %d",errorCode);
- return 0;
- }
- //发送一个字节,注意spi的时序产生的条件。当没有发送数据给spi的时候,是不会产生时序的,等待则无效
- uint8_t SPI_Flash_SendByte(uint8_t date)
- {
- SPITimeout=SPI_FLAG_TIMEOUT;
- while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_TXE) == RESET)
- {
- if (SPITimeout--==0) return SPI_TIMEOUT_UserCallback(0);
- };
- //程序执行到这里时,tx缓冲区已空
- SPI_I2S_SendData(FLASH_SPIx, date);
- SPITimeout=SPI_FLAG_TIMEOUT;
- while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE) == RESET)
- {
- if (SPITimeout--==0) return SPI_TIMEOUT_UserCallback(0);
- };
- //程序到此处,说明数据发送完毕,并接受下一字节
- return SPI_I2S_ReceiveData(FLASH_SPIx);
- }
- uint8_t SPI_Flash_Read_Byte(void)
- {
- return SPI_Flash_SendByte(DUMMY);
- }
- uint32_t SPI_Read_ID(void)
- {
- uint32_t flash_id;
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(READ_JEDEC_ID);
- flash_id=SPI_Flash_SendByte(DUMMY);
- flash_id<<=8;
- flash_id|=SPI_Flash_SendByte(DUMMY);
- flash_id<<=8;
- flash_id|=SPI_Flash_SendByte(DUMMY);
- FLASH_SPI_CS_HIGH();
- return flash_id;
- }
- //等待flash内部时序擦书完成
- void SPI_WaitForWriteEnd(void)
- {
- uint8_t status_arg = 0;
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(READ_STATUS);
- do
- {
- status_arg = SPI_Flash_SendByte(DUMMY);
- } while ((status_arg & 0x01) == SET); // 判断为忙碌
- FLASH_SPI_CS_HIGH();
- }
- //擦除FLASH指定扇区
- void SPI_ERASE_SECTRO(uint32_t addr)
- {
- SPI_Write_Enable();
- SPI_WaitForWriteEnd();
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(ERASE_SECTOR);
- SPI_Flash_SendByte((uint8_t)(addr>>16)&0xff);
- SPI_Flash_SendByte((uint8_t)(addr>>8)&0xff);
- SPI_Flash_SendByte((uint8_t)(addr>>0)&0xff);
- FLASH_SPI_CS_HIGH();
- SPI_WaitForWriteEnd();
- }
- //读取FLASH的内容
- void SPI_Read_Data(uint32_t addr,uint8_t *buff,uint32_t numByteToRead)
- {
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(READ_DATA);
-
- SPI_Flash_SendByte((addr>>16)&0xff);
- SPI_Flash_SendByte((addr>>8)&0xff);
- SPI_Flash_SendByte((addr)&0xff);
- while(numByteToRead--)
- {
- *buff = SPI_Flash_SendByte(DUMMY);
- buff++;
- }
- FLASH_SPI_CS_HIGH();
- }
- //flash写入使能
- void SPI_Write_Enable(void)
- {
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(WRITE_ENABLE);
- FLASH_SPI_CS_HIGH();
- }
- //写入
- void SPI_Write_Data(uint32_t addr,uint8_t *writebuff,uint32_t numByteToWrite)
- {
- SPI_Write_Enable();
- FLASH_SPI_CS_LOW();
- SPI_Flash_SendByte(WRITE_DATA);
-
- SPI_Flash_SendByte((addr>>16)&0xff);
- SPI_Flash_SendByte((addr>>8)&0xff);
- SPI_Flash_SendByte((addr)&0xff);
- while(numByteToWrite--)
- {
- *writebuff = SPI_Flash_SendByte(DUMMY);
- writebuff++;
- }
- FLASH_SPI_CS_HIGH();
- SPI_WaitForWriteEnd();
- }
复制代码 /************************************bsp_spi_flash.h**********************************************/
- #ifndef __BSP_SPI_FLASH_H
- #define __BSP_SPI_FLASH_H
- #include "stm32f10x.h"
- #include <stdio.h>
- #include <string.h>
- #include <stdio.h>
- #define FLASH_SPIx SPI1
- #define FLASH_SPI_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define FLASH_SPI_CLK RCC_APB2Periph_SPI1
- // cs 引脚,普通io口
- #define FLASH_SPI_CS_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define FLASH_SPI_CS_CLK RCC_APB2Periph_GPIOC
- #define FLASH_SPI_CS_PORT GPIOC
- #define FLASH_SPI_CS_PIN GPIO_Pin_0
- // sck引脚
- #define FLASH_SPI_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define FLASH_SPI_SCK_CLK RCC_APB2Periph_GPIOA
- #define FLASH_SPI_SCK_PORT GPIOA
- #define FLASH_SPI_SCK_PIN GPIO_Pin_5
- // mosi引脚
- #define FLASH_SPI_MOSI_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define FLASH_SPI_MOSI_CLK RCC_APB2Periph_GPIOA
- #define FLASH_SPI_MOSI_PORT GPIOA
- #define FLASH_SPI_MOSI_PIN GPIO_Pin_6
- // miso引脚
- #define FLASH_SPI_MISO_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define FLASH_SPI_MISO_CLK RCC_APB2Periph_GPIOA
- #define FlASH_SPI_MISO_PORT GPIOA
- #define FLASH_SPI_MISO_PIN GPIO_Pin_7
- //cs引脚配置
- #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 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-ERROR->> [%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
- #define WRITE_DATA 0x02
- /*************************************************** */
- void SPI_Flash_Init(void);
- uint8_t SPI_Flash_SendByte(uint8_t date);
- uint8_t SPI_Flash_Read_Byte(void);
- uint32_t SPI_Read_ID(void);
- void SPI_ERASE_SECTRO(uint32_t addr);
- void SPI_WaitForWriteEnd(void);
- void SPI_Read_Data(uint32_t addr,uint8_t *buff,uint32_t numByteToRead);
- void SPI_Write_Enable(void);
- void SPI_Write_Data(uint32_t addr,uint8_t *writebuff,uint32_t numByteToWrite);
- #endif // !__BSP_SPI_FLASH_H
复制代码
如果main函数里面在SPI_WaitForWriteEnd()下方加延时或者加断点逐行调试的时候,串口助手上的内容是这样的。如果不加延时函数就是全部为0x00.
bsp_spi_flash.h
===========================================================
[url=]6.png[/url]
[url=] [/url]
[url=][url=]7.png[/url][/url]
[url=][url=] [/url][/url]
[url=][url=][url=]===========================================================
main.c
===========================================================
[url=]9.png[/url]
[url=] [/url]
[/url][/url][/url]
|
|