野火电子论坛

 找回密码
 注册

扫一扫,访问微社区

查看: 162|回复: 1

[其它] Spi_Flash存储器读取问题

[复制链接]
发表于 2019-8-13 14:58:07 | 显示全部楼层 |阅读模式
5火花
遇到一个很奇怪的问题,在读取Flash存储器SST26VF064的时候,读取到的数据如图1所示,原理图如图2所示,引脚引出去直接接的stm32f103vct6引脚。
头文件如下
[C] 纯文本查看 复制代码
#ifndef _SPI_FLASH_H_
#define _SPI_FLASH_H_
#include "stm32f10x.h"
#define     SST_GPIO_RCC_CONFIG       RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC       //flash芯片时钟

#define     SST_HOLD_GPIOx      GPIOA               //HOLD引脚
#define     SST_HOLD_PIN        GPIO_Pin_7

#define     SST_WP_GPIOx        GPIOA            //WP引脚
#define     SST_WP_PIN          GPIO_Pin_4

#define     SST_CE_GPIOx        GPIOA              //片选引脚
#define     SST_CE_PIN          GPIO_Pin_6

#define     SST_SCLK_GPIOx      GPIOC               //时钟
#define     SST_SCLK_PIN        GPIO_Pin_4

#define     SST_MOSI_GPIOx      GPIOC                 //MOSI
#define     SST_MOSI_PIN        GPIO_Pin_5

#define     SST_MISO_GPIOx      GPIOA					//配置成输入模式 MISO   
#define     SST_MISO_PIN        GPIO_Pin_5

/* 指令表 */
#define SFLASH_WRITE_ENABLE       0x06                     //写使能
#define SFLASH_WRITE_DISABLE      0x04                     //写失能
#define SFLASH_READ_STATUS_REG    0x05                     //读状态寄存器
#define SFLASH_WRITE_STATUS_REG   0x01                     //写状态寄存器

#define SFLASH_READ_DATA          0x03                     //读数据
#define SFLASH_FAST_READ          0x0B                     //快读数据
#define SFLASH_FAST_READ_DUAL     0x3B                     //快读数据(双数据线输出)
#define SFLASH_WRITE_PAGE         0x02                     //页编程
#define SFLASH_ERASE_BLOCK        0xD8                     //擦除块
#define SFLASH_ERASE_SECTOR       0x20                     //擦除扇区
#define SFLASH_ERASE_CHIP         0xC7                     //擦除芯片
#define SFLASH_POWER_DOWN         0xB9                     //掉电
#define SFLASH_RELEASE_POWER_DOWN 0xAB                     //释放掉电
#define SFLASH_DEVICE_ID          0x90                     //设备ID
#define SFLASH_JEDEC_ID           0x9F                     //Jedec ID

void SPI_FLASH_config(void);    //spi的GPIO引脚初始化
void SPI_Initconfig(void);   //SPI初始化
uint32_t SFLASH_ReadJEDEC_ID(void);     //读取JEDEC-ID
void SPI_WriteByte(uint8_t txdata);
uint8_t SPI_ReadByte(void);
uint8_t SFLASH_ReadSR(void);     //读取SFLASH状态寄存器
void SFLASH_WriteSR(uint8_t SR);    //写SFLASH状态寄存器

/****从ReadAddr地址开始连续读取SFLASH的nByte*********************************/
void SFLASH_ReadNByte(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t nByte);

/*****从ReadAddr地址开始连续快速读取SFLASH的nByte
******最多读取65535B***************************/
void SFLASH_FastReadNByte(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t nByte);

void SFLASH_WaitForNoBusy(void);    // 等待不忙 

/*****在SFLASH内写入少于1页(256个字节)的数据************************************/
void SFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte);

/*********无检验写SFLASH
*必须确保所写的地址范围内的数据全部为0xFF,否则在非0xFF处写入的数据将失败!
*具有自动换页功能**********/
void SFLASH_WriteNoCheck(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte);

void SFLASH_EraseBlock(uint32_t BlockAddr);   //擦除块
void SFLASH_EraseSector(uint32_t SectorAddr);  //擦除扇区
void SFLASH_EraseChip(void);  //擦除整个芯片(整片擦除时间较长)

/**从ReadAddr地址开始连续写入nByte到SFLASH中
***pBuffer ----- 写入数据区首地址
*** WriteAddr --- 要写入Flash的地址
**** nByte ------- 要写入的字节数(最大65535B = 64K 块)**********************/
void SFLASH_WriteNByte(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte);

uint32_t SFLASH_ReadDevice_ID(void);   //读取设备ID
void SFLASH_WriteoneBytetest(void);     //写一个字节,用于测试
uint8_t SFLASH_ReadoneBytetest(void);	   //读一个字节,用于测试
void SFLASH_ReleasePowerDown(void);     //释放掉电
#endif     //_SPI_FLASH_H
.c文件如下:
[C] 纯文本查看 复制代码
#include "spi_flash.h"
#include "delay.h"
#include "usart1.h"
#define SST_HOLD_HIGH			  GPIO_SetBits(SST_HOLD_GPIOx,SST_HOLD_PIN)
#define SST_HOLD_LOW			  GPIO_ResetBits(SST_HOLD_GPIOx,SST_HOLD_PIN)
#define SST_WP_HIGH		    	GPIO_SetBits(SST_WP_GPIOx,SST_WP_PIN)
#define SST_WP_LOW			    GPIO_ResetBits(SST_WP_GPIOx,SST_WP_PIN)

#define SST_CE_DISABLE			    GPIO_SetBits(SST_CE_GPIOx,SST_CE_PIN)     //失能
#define SST_CE_ENABLE			      GPIO_ResetBits(SST_CE_GPIOx,SST_CE_PIN)   //使能

#define SST_SCLK_HIGH		  	GPIO_SetBits(SST_SCLK_GPIOx,SST_SCLK_PIN)
#define SST_SCLK_LOW			  GPIO_ResetBits(SST_SCLK_GPIOx,SST_SCLK_PIN)

#define SST_MOSI_HIGH		  	GPIO_SetBits(SST_MOSI_GPIOx,SST_MOSI_PIN)
#define SST_MOSI_LOW		  	GPIO_ResetBits(SST_MOSI_GPIOx,SST_MOSI_PIN)

#define SST_MISO_READ			    	GPIO_ReadInputDataBit(SST_MISO_GPIOx,SST_MISO_PIN)
/************************************************
函数名称 : SPI_FLASH_config
功    能 : Flash引脚配置
参    数 : 无
返 回 值 : 无 
*************************************************/
void SPI_FLASH_config(void)
{
    GPIO_InitTypeDef GPIO_initStructure;
    RCC_APB2PeriphClockCmd(SST_GPIO_RCC_CONFIG,ENABLE);
    
    GPIO_initStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_initStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
    GPIO_initStructure.GPIO_Pin = SST_HOLD_PIN;
    GPIO_Init (SST_HOLD_GPIOx,&GPIO_initStructure); 

		GPIO_initStructure.GPIO_Pin = SST_WP_PIN;
    GPIO_Init (SST_WP_GPIOx,&GPIO_initStructure);
		
		GPIO_initStructure.GPIO_Pin = SST_CE_PIN;
    GPIO_Init (SST_CE_GPIOx,&GPIO_initStructure);
	
		GPIO_initStructure.GPIO_Pin = SST_SCLK_PIN;
    GPIO_Init (SST_SCLK_GPIOx,&GPIO_initStructure);
		
		GPIO_initStructure.GPIO_Pin = SST_MOSI_PIN;
    GPIO_Init (SST_MOSI_GPIOx,&GPIO_initStructure);
	
		GPIO_initStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
		GPIO_initStructure.GPIO_Pin = SST_MISO_PIN;
    GPIO_Init (SST_MISO_GPIOx,&GPIO_initStructure);
}
/************************************************
函数名称 : SPI_Initconfig
功    能 : SPI_Flash初始化
参    数 : 无
返 回 值 : 无 
*************************************************/
void SPI_Initconfig(void)
{
	SPI_FLASH_config();     //GPIO引脚配置
	SST_CE_DISABLE;      //失能
	SST_SCLK_HIGH;       //初始拉高
	SST_MOSI_HIGH;
	SST_HOLD_HIGH;
	SST_WP_HIGH;
}

/************************************************
函数名称 : SPI_WriteByte
功    能 : 写一个字节
参    数 : 无
返 回 值 : 无 
*************************************************/
void SPI_WriteByte(uint8_t txdata)
{
	uint8_t cnt;
//	uint8_t testdata=0;
	for(cnt =0;cnt <8;cnt ++)
	{
		SST_SCLK_LOW;
		delay_us (2);
		if((txdata&0x80)==0x80)
			SST_MOSI_HIGH;
		else 
			SST_MOSI_LOW;
		txdata<<=1;
		/*********************************/
//		testdata<<=1;
//		if(SST_MISO_READ)
//		{
//			testdata |=0x01;
//		}
		/*********************************/
		
		SST_SCLK_HIGH;
		delay_us(2);
	}
//	return testdata ;
}

/************************************************
函数名称 : SPI_ReadByte
功    能 : 读取一个字节
参    数 : 无
返 回 值 : 读取的字节 
*************************************************/
uint8_t SPI_ReadByte(void)
{
	uint8_t cnt;
	uint8_t rxdata=0;
	for(cnt =0;cnt <8;cnt++)
	{
		SST_SCLK_LOW;
		delay_us (1);
		rxdata<<=1;
		if(SST_MISO_READ)
		{
			rxdata |=0x01;
		}
		SST_SCLK_HIGH;
		delay_us (1);
	}
	return rxdata;
}
uint32_t SFLASH_ReadDevice_ID(void)
{
  uint32_t ID = 0;
  SST_CE_ENABLE;                                 //使能器件

  SPI_WriteByte(SFLASH_JEDEC_ID);                //《JEDEC_ID》指令

  SPI_WriteByte(0);                      //读取ID
  SPI_WriteByte(0);
  SPI_WriteByte(0);
	ID |= SPI_ReadByte();
  SST_CE_DISABLE;                                //失能器件
  return ID;
}
/************************************************
函数名称 : SFLASH_ReadJEDEC_ID
功    能 : 读取芯片JEDEC_ID
参    数 : 无
返 回 值 : ID --- 24位ID号 
*************************************************/
uint32_t SFLASH_ReadJEDEC_ID(void)
{
  uint32_t ID = 0;
  SST_CE_ENABLE;                                 //使能器件

  SPI_WriteByte(SFLASH_JEDEC_ID);                //《JEDEC_ID》指令

  ID |= SPI_ReadByte()<<16;                      //读取ID
  ID |= SPI_ReadByte()<<8;
  ID |= SPI_ReadByte();
  SST_CE_DISABLE;                                //失能器件
  return ID;
}
/************************************************
函数名称 : SFLASH_WriteEnable
功    能 : SPI_FLASH写使能,将WEL置位
参    数 : 无
返 回 值 : 无 
*************************************************/
static void SFLASH_WriteEnable(void)
{
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_WRITE_ENABLE);            //《写使能》指令06
  SST_CE_DISABLE;                                //失能器件
}
/************************************************
函数名称 : SFLASH_WriteDisable
功    能 : SPI_FLASH写禁止,将WEL清零
参    数 : 无
返 回 值 : 无
*************************************************/
static void SFLASH_WriteDisable(void)
{
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_WRITE_DISABLE);           //《写失能》指令
  SST_CE_DISABLE;                                //失能器件
}
/************************************************
函数名称 : SFLASH_ReadSR
功    能 : 读取SFLASH状态寄存器
参    数 : 无
返 回 值 : Byte --- 读取字节
*************************************************/
uint8_t SFLASH_ReadSR(void)
{
  uint8_t data_tmp;
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_READ_STATUS_REG);         //《读状态寄存器》指令
  data_tmp = SPI_ReadByte();                     //读取一个字节
  SST_CE_DISABLE;                                //失能器件
  return data_tmp;
}
/************************************************
函数名称 : SFLASH_WriteSR
功    能 : 写SFLASH状态寄存器
参    数 : SR --- 写状态寄存器命令
返 回 值 : 无
*************************************************/
void SFLASH_WriteSR(uint8_t SR)
{
  SFLASH_WriteEnable();                          //写使能
	SST_CE_ENABLE;
  SPI_WriteByte(SFLASH_WRITE_STATUS_REG);        //《写状态寄存器》指令
  SPI_WriteByte(SR);                             //写入一个字节
  SST_CE_DISABLE;                                //失能器件
}

/************************************************
函数名称 : SFLASH_ReadNByte
功    能 : 从ReadAddr地址开始连续读取SFLASH的nByte
参    数 : pBuffer ---- 数据存储区首地址
            ReadAddr --- 要读取SFLASH Flash的首地址地址
            nByte ------ 要读取的字节数(最大65535B = 64K 块)
返 回 值 : 无
*************************************************/
void SFLASH_ReadNByte(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t nByte)
{
	uint16_t i;
	SST_CE_DISABLE;
	delay_us (2);
  SST_CE_ENABLE;                                 //使能器件

  SPI_WriteByte(SFLASH_READ_DATA);               //《读数据》指令
  SPI_WriteByte((uint8_t)((ReadAddr>>16)&0xff));      //发送24bit地址
  SPI_WriteByte((uint8_t)((ReadAddr>>8)&0xff));
  SPI_WriteByte((uint8_t)(ReadAddr&0xff));

	for(i=0;i<nByte;i++)
	{
		*(pBuffer+i)=SPI_ReadByte();
	}
//  while(nByte--)                                 //循环读数
//  {
//    *pBuffer = SPI_ReadByte();
//    pBuffer++;
//  }

  SST_CE_DISABLE;                                //失能器件
}

/************************************************
函数名称 : SFLASH_FastReadNByte
功    能 : 从ReadAddr地址开始连续快速读取SFLASH的nByte
参    数 : pBuffer ---- 数据存储区首地址
            ReadAddr --- 要读取SFLASH Flash的首地址地址
            nByte ------ 要读取的字节数(最大65535B = 64K 块)
返 回 值 : 无
*************************************************/
void SFLASH_FastReadNByte(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t nByte)
{
	SST_CE_DISABLE;
	delay_us (2);
  SST_CE_ENABLE;                                 //使能器件
	
  SPI_WriteByte(SFLASH_FAST_READ);               //《快读数据》指令
  SPI_WriteByte((uint8_t)(((ReadAddr)>>16)&0xff));      //发送24bit地址
  SPI_WriteByte((uint8_t)(((ReadAddr)>>8)&0xff));
  SPI_WriteByte((uint8_t)(ReadAddr&0xff));
  SPI_WriteByte(0xFF);                           //等待8个时钟

  while(nByte--)                                 //循环读数
  {
    *pBuffer = SPI_ReadByte();
    pBuffer++;
  }

  SST_CE_DISABLE;                                //失能器件
}
/************************************************
函数名称 : SFLASH_WaitForNoBusy
功    能 : 等待不忙
参    数 : 无
返 回 值 : 无
*************************************************/
void SFLASH_WaitForNoBusy(void)
{
   u8 FLASH_Status = 0;

  /* 选择 FLASH: CS 低 */
  SST_CE_ENABLE;

  /* 发送 读状态寄存器 命令 */
  SPI_WriteByte(SFLASH_READ_STATUS_REG);

 
  /* 若FLASH忙碌,则等待 */
  do
  {
    /* 读取FLASH芯片的状态寄存器 */
    FLASH_Status = SPI_ReadByte();	 
  }
  while ((FLASH_Status & 0x01) == 0x01); /* 正在写入标志 */

  /* 停止信号  FLASH: CS 高 */
  SST_CE_DISABLE;
}

/************************************************
函数名称 : SFLASH_WritePage
功    能 : 在SFLASH内写入少于1页(256个字节)的数据
参    数 : pBuffer ----- 写入数据区首地址
            WriteAddr --- 要写入Flash的地址
            nByte ------- 要写入的字节数(最大1页)
返 回 值 : 无
*************************************************/
void SFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte)
{
	SFLASH_WriteEnable(); 	//写使能
	//delay_us(1);
	//SFLASH_WaitForNoBusy();   	//等待空闲(等待写入结束)----------------------
	SST_CE_ENABLE;                                 //使能器件
  
  SPI_WriteByte(SFLASH_WRITE_PAGE);              //《页编程》指令02
  SPI_WriteByte((WriteAddr & 0xFF0000) >> 16);   //写地址高位  //((uint8_t)(((WriteAddr)>>16)&0xff));     //发送24bit地址
  SPI_WriteByte((WriteAddr & 0xFF00) >> 8);      //写地址中位
  SPI_WriteByte(WriteAddr & 0xFF);               //写地址低位

  while (nByte--)
  {
    SPI_WriteByte(*pBuffer);      //写入数据
		//delay_us(1);
    pBuffer++;
  }
  SST_CE_DISABLE;
 
  SFLASH_WaitForNoBusy();   	//等待空闲(等待写入结束)
	 
}
void SFLASH_WriteoneBytetest(void)
{
//	uint8_t testdat;
	SFLASH_WriteEnable(); 	//写使能
	SFLASH_WaitForNoBusy();   	//等待空闲(等待写入结束)--------------
	delay_us(1);
	SST_CE_ENABLE;   
	SPI_WriteByte(SFLASH_WRITE_PAGE);  
//  printf ("这是SFLASH_WriteoneBytetest函数中的testdat=0x%x\n",testdat);	
	SPI_WriteByte(0x00);
//	printf ("这是SFLASH_WriteoneBytetest函数中的testdat=0x%x\n",testdat);
	SPI_WriteByte(0x20);
//	printf ("这是SFLASH_WriteoneBytetest函数中的testdat=0x%x\n",testdat);
	SPI_WriteByte(0x00);
//	printf ("这是SFLASH_WriteoneBytetest函数中的testdat=0x%x\n",testdat);
	SPI_WriteByte(0x3b);
//	printf ("这是SFLASH_WriteoneBytetest函数中的testdat=0x%x\n",testdat);
	SST_CE_DISABLE;
	SFLASH_WaitForNoBusy();   	//等待空闲(等待写入结束)
}
uint8_t SFLASH_ReadoneBytetest(void)
{
//	uint8_t testdat;
  uint8_t ID = 0;
  SST_CE_ENABLE;                                 //使能器件

  SPI_WriteByte(0x03);                //《读字节》指令
//	printf ("这是SFLASH_ReadoneBytetest函数中的testdat=0x%x\n",testdat);
  SPI_WriteByte(0x00);
//	printf ("这是SFLASH_ReadoneBytetest函数中的testdat=0x%x\n",testdat);
	SPI_WriteByte(0x20);
//	printf ("这是SFLASH_ReadoneBytetest函数中的testdat=0x%x\n",testdat);
	SPI_WriteByte(0x00);
//	printf ("这是SFLASH_ReadoneBytetest函数中的testdat=0x%x\n",testdat);
	
  ID |= SPI_ReadByte();
	printf ("读出的数据为ID=0X%x\n",ID);
  SST_CE_DISABLE;                                //失能器件
	
  return ID;
}
/************************************************
函数名称 : SFLASH_WriteNoCheck
功    能 : 无检验写SFLASH
            必须确保所写的地址范围内的数据全部为0xFF,否则在非0xFF处写入的数据将失败!
            具有自动换页功能
            在指定地址开始写入指定长度的数据,但是要确保地址不越界!
参    数 : pBuffer ----- 写入数据区首地址
            WriteAddr --- 要写入Flash的地址
            nByte ------- 要写入的字节数
返 回 值 : 无
*************************************************/
void SFLASH_WriteNoCheck(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte)
{
  uint16_t PageRemain = 256 - WriteAddr%256;     //单页剩余可写的字节数

  if(nByte <= PageRemain)
    PageRemain = nByte;                          //不大于256个字节

  while(1)
  {
    SFLASH_WritePage(pBuffer, WriteAddr, PageRemain);
    if(nByte == PageRemain)                      //写入结束
      break;
    else                                         //写入未结束
    {
      pBuffer += PageRemain;                     //下一页写入数据
      WriteAddr += PageRemain;                   //下一页写入数据地址
      nByte -= PageRemain;                       //待写入字节数递减

      if(nByte > 256)
        PageRemain = 256;                        //待写入1页(256字节)的数据
      else
        PageRemain = nByte;                      //待写入少于1页(256字节)的数据
    }
  }
	SFLASH_WaitForNoBusy();                        //等待空闲(等待写入结束)
}
/************************************************
函数名称 : SFLASH_EraseBlock
功    能 : 擦除块
            擦除块需要一定时间
参    数 : BlockAddr --- 块地址 0~127
返 回 值 : 无
*************************************************/
void SFLASH_EraseBlock(uint32_t BlockAddr)
{
  BlockAddr *= 65536;                            //块首地址
  SFLASH_WriteEnable();                          //写使能
  SFLASH_WaitForNoBusy();
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_ERASE_BLOCK);             //《擦除块》指令
  SPI_WriteByte((uint8_t)(((BlockAddr)>>16)&0xff));     //擦除地址
  SPI_WriteByte((uint8_t)(((BlockAddr)>>8)&0xff));
  SPI_WriteByte((uint8_t)(BlockAddr&0xff));
  SST_CE_DISABLE;

  SFLASH_WaitForNoBusy();                        //等待擦除完成
}

/************************************************
函数名称 : SFLASH_EraseSector
功    能 : 擦除扇区
参    数 : SectorAddr --- 扇区地址 0~511
返 回 值 : 无
*************************************************/
void SFLASH_EraseSector(uint32_t SectorAddr)
{
  SectorAddr *= 4096;                            //扇区首地址
  SFLASH_WriteEnable();                          //写使能
  SFLASH_WaitForNoBusy();
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_ERASE_SECTOR);            //《擦除扇区》指令
  SPI_WriteByte((uint8_t)(((SectorAddr)>>16)&0xff));    //擦除地址
  SPI_WriteByte((uint8_t)(((SectorAddr)>>8)&0xff));
  SPI_WriteByte((uint8_t)(SectorAddr&0xff));
  SST_CE_DISABLE;

  SFLASH_WaitForNoBusy();                        //等待擦除完成
}

/************************************************
函数名称 : SFLASH_EraseChip
功    能 : 擦除整个芯片(整片擦除时间较长)
参    数 : 无
返 回 值 : 无
*************************************************/
void SFLASH_EraseChip(void)
{
  SFLASH_WriteEnable();                          //写使能
  SFLASH_WaitForNoBusy();
  SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_ERASE_CHIP);              //《擦除芯片》指令
  SST_CE_DISABLE;

  SFLASH_WaitForNoBusy();                        //等待芯片擦除结束
}

/************************************************
函数名称 : SFLASH_WriteNByte
功    能 : 从ReadAddr地址开始连续写入nByte到SFLASH中
参    数 : pBuffer ----- 写入数据区首地址
            WriteAddr --- 要写入Flash的地址
            nByte ------- 要写入的字节数(最大65535B = 64K 块)
返 回 值 : 无
*************************************************/
void SFLASH_WriteNByte(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t nByte)
{
  static uint8_t SectorBuf[4096];                //扇区buf
  uint32_t SecPos;                               //扇区位置
  uint16_t SecOff;                               //扇区偏移
  uint16_t SecRemain;                            //剩余扇区
  uint16_t i;
	SFLASH_WriteEnable();                          //写使能
  SecPos = WriteAddr/4096;                       //地址所在扇区(0~511)
  SecOff = WriteAddr%4096;                       //地址所在扇区的偏移
  SecRemain = 4096-SecOff;                       //地址所在扇区剩余字节数(扇区大小4096B=4KB)

  if(nByte <= SecRemain)
    SecRemain = nByte;                           //写入数据大小 < 剩余空间大小 (即剩余空间够保存这些数据)

  while(1)
  {
    /* 第1步·校验 */
    SFLASH_ReadNByte(SectorBuf, SecPos*4096, 4096);        //读出整个扇区的内容
    for(i=0; i<SecRemain; i++)                             //校验数据,是否需要擦除
    {
      if(SectorBuf[SecOff + i] != 0xFF)                    //存储数据不为0xFF 则需要擦除
        break;
    }
    if(i < SecRemain)                                      //需要擦除
    {
      SFLASH_EraseSector(SecPos);                          //擦除该扇区
      for(i=0; i<SecRemain; i++)                           //保存写入的数据(第1次时,是写入那扇区后面剩余的空间)
      {
        SectorBuf[SecOff + i] = pBuffer[i];
      }
      SFLASH_WriteNoCheck(SectorBuf, SecPos*4096, 4096);   //写入整个扇区(扇区 = 老数据 + 新写入数据)
    }
    else
      SFLASH_WriteNoCheck(pBuffer, WriteAddr, SecRemain);  //不需要擦除,直接写入扇区剩余空间

    if(nByte == SecRemain)                       //写入结束
    {
      SFLASH_WriteDisable();                     //写失能, 退出写
      break;
    }
    else                                         //写入未结束
    {
      SecPos++;                                  //扇区地址增1
      SecOff = 0;                                //偏移位置归零
      pBuffer += SecRemain;                      //指针偏移
      WriteAddr += SecRemain;                    //写地址偏移
      nByte -= SecRemain;                        //待写入字节数递减
      if(nByte > 4096)
        SecRemain = 4096;                        //待写入1扇区(4096字节)的数据
      else
        SecRemain = nByte;                       //待写入少于1扇区(4096字节)的数据
    }
  }
	 SFLASH_WaitForNoBusy();                        //等待芯片擦除结束
}
/************************************************
函数名称 : SFLASH_ReleasePowerDown
功    能 : 释放掉电
参    数 : 无
返 回 值 : 无
*************************************************/
void SFLASH_ReleasePowerDown(void)
{
	SST_CE_ENABLE;                                 //使能器件
  SPI_WriteByte(SFLASH_RELEASE_POWER_DOWN);           //《释放掉电》指令
  SST_CE_DISABLE;                                //失能器件
}


然后设置的1秒读取发送一次,代码如下:
[C] 纯文本查看 复制代码
/************************************************
函数名称 : Spi_Flash_WriteTest
功    能 : 存储器写入测试
参    数 : 无
返 回 值 : 无
*************************************************/
void  Spi_Flash_WriteTest(void)
{
		uint8_t SFlash_ReadArray[100];      //将从存储器中读取的数据存入此数组中
	  uint8_t SFlash_WriteArray[10];      //将要写入存储器中的数据暂存在此数组中
		uint8_t Flash_Readcount,Flash_Writecount;
	  uint8_t i=0;
	  SFLASH_EraseSector(0x10000);   //擦除要写入的扇区
		for(Flash_Writecount=0;Flash_Writecount<10;Flash_Writecount++)
	  {
			SFlash_WriteArray[Flash_Writecount]=0x10;
		}
		SFLASH_WritePage(SFlash_WriteArray, 0x10000, 10);//从地址0,连续写入6字节数据(ABCDEF)
		delay_ms (1);
		SFLASH_ReadNByte(SFlash_ReadArray,0x10000,100);
		printf ("本存储器芯片的前100个字节数据为:\n");
		for(Flash_Readcount=0;Flash_Readcount<100;Flash_Readcount++)
		{
			i++;
			printf ("0x%x ",SFlash_ReadArray[Flash_Readcount]);
			if(i==10)
			{
				i=0;
				printf ("\n");
			}
		}
}

奇怪的就是在这个板子上面就有问题,然后我把程序刷到野火的F429挑战者上面读取的数据就没有问题。

图1:读取的数据

图1:读取的数据

图2:原理图

图2:原理图
回复

使用道具 举报

发表于 2019-8-14 17:28:53 | 显示全部楼层
:):):):):):):):):)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

野火电子公众号

手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号-2 大学生ARM嵌入式2群

GMT+8, 2019-8-23 17:48 , Processed in 0.156695 second(s), 29 queries , Gzip On.

野火电子论坛

© 2014-2016 www.firebbs.cn

快速回复 返回顶部 返回列表