STM32单片机AT45DB161源码程序详解

AT45DB161D是一款2.5V或2.7V,串行接口的FLASH存储器,是各种数字语音,图像,程序代码和数据存储应用的理想选择。AT45DB161D支持RapidS串行接口,适用于要求高速操作的应用。RapidS串行接口兼容SPI,最高频率可达66MHz。AT45DB161D的存储容量为17,301,504位,组织形式为4,096页,每页512或528页。
  除了主存储器外,AT45DB161D还包含2个512/528字节的SRAM缓冲区。缓冲区允许在对主存储器的页面重新编程时接收数据,也可写入连续的数据串。通过独立的“读-改-写”三步操作,可以轻松实现EEPROM仿真(可设置成位或字节)。DataFlash通过RapidS串行接口顺序访问数据,而不像传统FLASH存储器那样通过复用总线和并行接口随机存取。
  简单顺序访问机制极大的减少了有效引脚的数量,有利于硬件布局,增强了系统可靠性,将切换噪音降至最小,并缩小了封装的尺寸。
对于许多要求高容量,低引脚数,低电压和低功耗的商业级或工业级应用来讲,AT45DB161D是最佳的选择。
  为了实现简单的在系统重复编程,AT45DB161D并不需要高输入电压来支持编程。AT45DB161D工作在独立的2.5V至3.6V或者2.7V至3.6V电压下,用于编程和读取操作。AT45DB161D可通过片选引脚(/CS)使能,并通过3-wire接口访问,3-wire由串行输入(SI),串行输出(SO),和串行时钟(SCK)组成。
 所有的编程和擦除周期都遵循自时序。

一些为at46db161的.c/.h文件,STM32多款多系列单片机实测可用

/*
 ============================================================
 MODEL 	  NAME  : AT45DB161D.c
 MODEL FUNCTION : Define system globe variables and functions
 RELATION MODEL : Others models in project
 ============================================================
 */

 #include "at45db161.h"

 /***********************************************************
	Define implements of functions in AT45DB161D.c model
 ************************** START **************************/

static __IO uint32_t  SPITimeout = SPIT_LONG_TIMEOUT;    
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);


/**
  * @brief  SPI_FLASH初始化
  * @param  无
  * @retval 无
  */
void SPI_FLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 使能SPI时钟 */
	FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );
	
	/* 使能SPI引脚相关的时钟 */
 	FLASH_SPI_CS_APBxClock_FUN ( FLASH_SPI_CS_CLK|FLASH_SPI_SCK_CLK|
																	FLASH_SPI_MISO_PIN|FLASH_SPI_MOSI_PIN, ENABLE );
	
  /* 配置SPI的 CS引脚,普通IO即可 */
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
	
  /* 配置SPI的 SCK引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);

  /* 配置SPI的 MISO引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
  GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);

  /* 配置SPI的 MOSI引脚*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
  GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);

  /* 停止信号 FLASH: CS引脚高电平*/
  SPI_FLASH_CS_HIGH();

  /* SPI 模式配置 */
  // FLASH芯片 支持SPI模式0及模式3,据此设置CPOL CPHA
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(FLASH_SPIx , &SPI_InitStructure);

  /* 使能 SPI  */
  SPI_Cmd(FLASH_SPIx , ENABLE);
	
}




//***********************************************************************													
// 函数名称: uint8_t SPIx_ReadWriteByte(uint8_t TxData)					
// 入口参数: TxData  命令或地址															
// 出口参数: 接收到的数据
// 备    注: 通过硬件SPI发送一个字节															
//***********************************************************************
uint8_t SPIx_ReadWriteByte(uint8_t TxData)
{		
  SPITimeout = SPIT_FLAG_TIMEOUT;
  /* 等待发送缓冲区为空,TXE事件 */
  while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) == RESET)
	{
    if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
   }

  /* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
  SPI_I2S_SendData(FLASH_SPIx , TxData);

	SPITimeout = SPIT_FLAG_TIMEOUT;
  /* 等待接收缓冲区非空,RXNE事件 */
  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_ReadSR(void) 					
// 入口参数: 无															
// 出口参数: 返回状态寄存器的值
// 备    注: 读取SPI_FLASH的状态寄存器																
//-----------------------------------------------------------------------
//Status Register Format
//Bit 7     Bit 6  Bit 5  Bit 4  Bit 3  Bit 2  Bit 1      Bit 0
//RDY/BUSY  COMP   1      0      1      1      PROTECT    PAGE SIZE
//BUSY:忙标记位(0,忙;1,空闲)
//PAGE SIZE  0:512b  1:528b
//默认:0x00
//***********************************************************************
uint8_t SPI_Flash_ReadSR(void)   
{  
	uint8_t byte=0;   
	SPI_FLASH_CS_LOW();;                            //使能器件   
	SPIx_ReadWriteByte(Status_Read);            //发送读取状态寄存器命令    
	byte=SPIx_ReadWriteByte(0Xa5);              //读取一个字节  
	SPI_FLASH_CS_HIGH();;                            //取消片选     
	return byte;   
}
//***********************************************************************													
// 函数名称: void SPI_Flash_Wait_Busy(void)					
// 入口参数: 无															
// 出口参数: 无
// 备    注: 芯片空闲等待															
//*********************************************************************** 		    
void SPI_Flash_Wait_Busy(void)   
{   
	while (!(SPI_Flash_ReadSR()&0x80));//等待BUSY置1
} 
//***********************************************************************													
// 函数名称: uint16_t SPI_Flash_ReadID(void)					
// 入口参数: 无															
// 出口参数: AT45DB161的ID
// 备    注: 读取芯片ID AT45DB161 的ID:0X1F26															
//***********************************************************************
uint32_t SPI_Flash_ReadID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0,Temp3;

  // Select the FLASH: Chip Select low */
	SPI_FLASH_CS_LOW();				    

  // Send "RDID " instruction */
  SPIx_ReadWriteByte(0x9F);

  // Read a byte from the FLASH */
  Temp0 = SPIx_ReadWriteByte(Dummy_Byte);

  // Read a byte from the FLASH */
  Temp1 = SPIx_ReadWriteByte(Dummy_Byte);

  // Read a byte from the FLASH */
  Temp2 = SPIx_ReadWriteByte(Dummy_Byte);

  // Read a byte from the FLASH */
  Temp3 = SPIx_ReadWriteByte(Dummy_Byte);
  
  // Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();

  Temp = (Temp0 << 24) | (Temp1 << 16) | (Temp2<<8) | Temp3;

  return Temp;
}

//***********************************************************************													
// 函数名称: void SPI_FLASH_PageErase(uint32_t PageAddr)					
// 入口参数: 页擦出地址															
// 出口参数: 无
// 备    注: 芯片页擦除															
//***********************************************************************
void SPI_FLASH_PageErase(uint32_t PageAddr)
{	
	SPI_Flash_Wait_Busy();    												    
	SPI_FLASH_CS_LOW();               //使能器件   
	SPIx_ReadWriteByte(Page_Erase);//发送页擦除指令
	SPIx_ReadWriteByte(PageAddr >> 6);
	SPIx_ReadWriteByte(PageAddr << 2);
	SPIx_ReadWriteByte( 0);
	SPI_FLASH_CS_HIGH();     	      
}
//***********************************************************************													
// 函数名称: void SPI_FLASH_SectorErase(uint32_t SectorAddr)					
// 入口参数: 扇区擦出地址															
// 出口参数: 无
// 备    注: 芯片扇区擦除  														
//***********************************************************************
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
	SPI_Flash_Wait_Busy();    												    
	SPI_FLASH_CS_LOW();                 //使能器件   
	SPIx_ReadWriteByte(Sector_Erase);//发送扇区擦除指令
	SPIx_ReadWriteByte((SectorAddr & 0xFF0000) >> 16);
	SPIx_ReadWriteByte((SectorAddr & 0xFF00) >> 8);
	SPIx_ReadWriteByte(SectorAddr  & 0xFF);
	SPI_FLASH_CS_HIGH();                 //取消片选     	      
}
//***********************************************************************													
// 函数名称: void SPI_FLASH_PageWrite(uint8_t *pBuffer,uint16_t Page, uint16_t Byte,uint16_t NumByteToWrite)					
// 入口参数: uint8_t *pBuffer       :要写入的数据
//           uint16_t Pag           : 要写入数据的页地址
//           uint16_t Byte          : 要写入数据的页偏移
//           uint16_t NumByteToWrite: 要写入数据的长度															
// 出口参数: 无
// 备    注: 对芯片进行页写 														
//***********************************************************************
void SPI_FLASH_PageWrite(uint8_t *pBuffer,uint16_t Page, uint16_t Byte,uint16_t NumByteToWrite)
{   
    //写入缓冲区 										    
	SPI_FLASH_CS_LOW();     //使能器件   
	SPIx_ReadWriteByte(	Buffer1_Write);
	SPIx_ReadWriteByte(0X00);
	SPIx_ReadWriteByte((uint8_t)(Byte >> 8));
	SPIx_ReadWriteByte((uint8_t)Byte);
	while (NumByteToWrite--)
	{
		//Send the current byte
		SPIx_ReadWriteByte(*pBuffer);
		//Point on the next byte to be written 
		pBuffer++;
	}
	SPI_FLASH_CS_HIGH();//取消片选
	SPI_Flash_Wait_Busy();
	//缓冲区向FLASH写入								    
	SPI_FLASH_CS_LOW(); //使能器件   
	SPIx_ReadWriteByte(Buffer1ToMMPage_WithErase);//发送写指令
	
	SPIx_ReadWriteByte((uint8_t)(Page >> 6));
	SPIx_ReadWriteByte((uint8_t)(Page << 2));
	SPIx_ReadWriteByte(0x00);

	SPI_FLASH_CS_HIGH();     //取消片选
	SPI_Flash_Wait_Busy();		     	      
}
//***********************************************************************													
// 函数名称: void SPI_FLASH_BufferWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)					
// 入口参数: uint8_t *pBuffer       :要写入的数据
//           uint32_t WriteAddr     :要写入数据的地址
//           uint16_t NumByteToWrite: 要写入数据的长度															
// 出口参数: 无
// 备    注: 对芯片的块写入数据														
//***********************************************************************
void SPI_FLASH_BufferWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
	uint16_t NumOfPage=0,NumOfSingle=0,temp=0;
	uint16_t Addr=0,count=0,Page_adress = 0;

	Addr       = WriteAddr % SPI_FLASH_PageSize;
	count      = SPI_FLASH_PageSize - Addr;
	NumOfPage  = NumByteToWrite / SPI_FLASH_PageSize;
	NumOfSingle= NumByteToWrite % SPI_FLASH_PageSize;
	Page_adress= WriteAddr / SPI_FLASH_PageSize;

	if (Addr == 0) //WriteAddr is SPI_FLASH_PageSize aligned  
	{
		if (NumOfPage == 0)// NumByteToWrite < SPI_FLASH_PageSize 
		{
			SPI_FLASH_PageWrite(pBuffer, Page_adress, 0, NumOfSingle);
		}
		else // NumByteToWrite > SPI_FLASH_PageSize 
		{
			while(NumOfPage--)
			{
				SPI_FLASH_PageWrite(pBuffer, Page_adress, 0 , SPI_FLASH_PageSize);
				Page_adress ++;
		        WriteAddr +=  SPI_FLASH_PageSize;
		        pBuffer += SPI_FLASH_PageSize;
			}
			SPI_FLASH_PageWrite(pBuffer, Page_adress, 0, NumOfSingle);
		}
	}
	else //WriteAddr is not SPI_FLASH_PageSize aligned
	{
		if (NumOfPage == 0)//NumByteToWrite < SPI_FLASH_PageSize
		{
			if (NumOfSingle > count)// (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize
			{
				temp = NumOfSingle - count;
                SPI_FLASH_PageWrite(pBuffer, Page_adress, Addr, count);
				Page_adress ++;

				WriteAddr +=  count;
				pBuffer += count;
				
				SPI_FLASH_PageWrite(pBuffer, Page_adress, 0, temp);
			}
			else
			{
				SPI_FLASH_PageWrite(pBuffer, Page_adress, Addr, NumByteToWrite);
			}
		}
		else//NumByteToWrite > SPI_FLASH_PageSize
		{
			NumByteToWrite -= count;
			NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
			NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
			
			SPI_FLASH_PageWrite(pBuffer, Page_adress, Addr, count);
			Page_adress++;

			WriteAddr +=  count;
			pBuffer += count;
	
			while (NumOfPage--)
			{
			  SPI_FLASH_PageWrite(pBuffer, Page_adress, 0, SPI_FLASH_PageSize);
			  Page_adress++;
			  WriteAddr +=  SPI_FLASH_PageSize;
			  pBuffer += SPI_FLASH_PageSize;
			}
			if (NumOfSingle != 0)
			{
				SPI_FLASH_PageWrite(pBuffer, Page_adress, 0, NumOfSingle);
			}
		}
	}
}
//***********************************************************************													
// 函数名称: void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)					
// 入口参数: uint8_t *pBuffer       : 读数据暂存区
//           uint32_t ReadAddr      : 要读数据的地址
//           uint16_t NumByteToRead : 要读数据的长度															
// 出口参数: 无
// 备    注: 读取芯片块中的数据														
//***********************************************************************
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
	uint16_t  Byte=0,Page=0;
	Byte =  ReadAddr % SPI_FLASH_PageSize;
  Page =  ReadAddr / SPI_FLASH_PageSize ;

	SPI_Flash_Wait_Busy();    												    
	SPI_FLASH_CS_LOW();    //使能器件   
	SPIx_ReadWriteByte(0XE8);//发送读指令
	SPIx_ReadWriteByte((uint8_t)(Page >> 6));
	SPIx_ReadWriteByte((uint8_t)((Page<<2) | ( Byte>>8)));
	SPIx_ReadWriteByte((uint8_t)Byte);
	SPIx_ReadWriteByte(Dummy_Byte);
	SPIx_ReadWriteByte(Dummy_Byte);
	SPIx_ReadWriteByte(Dummy_Byte);
	SPIx_ReadWriteByte(Dummy_Byte);
	while (NumByteToRead--)//while there is data to be read 
	{
		//Read a byte from the FLASH 
		*pBuffer = SPIx_ReadWriteByte(Dummy_Byte);
		//Point to the next location where the byte read will be saved
		pBuffer++;
	}
	SPI_FLASH_CS_HIGH();   	      
}

/**
  * @brief  等待超时回调函数
  * @param  None.
  * @retval None.
  */
static  uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* 等待超时后的处理,输出错误信息 */
  //FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);
  return 0;
}



//-------------------the  end-----------------------//	

以下为.h文件:

/*
 ============================================================
 MODEL 	  NAME  : AT45DB161D.h
 MODEL FUNCTION : Declare
 RELATION MODEL : Others models in project
 ============================================================
 */
 #ifndef __AT45DB161D_H
 #define __AT45DB161D_H
 
 / define constant 
 /***********************************************************
	Define variables in AT45DB161D.c model
 ************************** START **************************/
 #ifdef VAR_GLOBALS
 #define VAR_EXT
 #else
 #define VAR_EXT extern
 #endif
 /************************** End ***************************/
   
 /***********************************************************
	Declare prototype of functions in AT45DB161D.c model
 ************************** START **************************/


#define  		SPI_FLASH_CS_LOW()     						GPIO_ResetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN )
#define  		SPI_FLASH_CS_HIGH()    						GPIO_SetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN )


//定义flash的分区,9个分区,每个区 14563*16Byte   0x200000
#define   DataStart_Local		    0       //    0——14562 
#define   DataStart_3512C	  14563		    //14563——29125
#define   DataStart_3512D		29126       //29126——43688
#define   DataStart_3028		43688       //43689——58251
#define   DataStart_3512A		58252       //58252——72814
#define   DataStart_3512B		72815       //72815——87377
#define   DataStart_3512E		87378       //87378——101940
#define   DataStart_3512W	 101941       //101941——116503
#define   DataStart_3512L	 116504       //116504——131066


#define SPI_SPEED_2   0
#define SPI_SPEED_4   1
#define SPI_SPEED_8   2
#define SPI_SPEED_16  3
#define SPI_SPEED_256 4

#define Dummy_Byte            0xA5
#define SPI_FLASH_PageSize    0x210	//528
//指令表
/**************操作指令码定义******************************/
#define Buffer_1_Read                0xD4//读取缓冲器1(速率最高为66MHz)
#define Buffer_2_Read                0xD3//Buffer 2 Read (Low Frequency)
#define Page_Read                    0xD2//读取一页Main Memory Page Read
#define Status_Read                  0xD7//读取状态寄存器
#define Continuous_Array_Read        0x0B//Continuous Array Read (High Frequency)
//写指令
#define WRITE                        0x82  /* Write to Memory instruction */
#define Buffer1_Write                0x84//一
#define Buffer2_Write                0x87//写入第二缓冲区
#define Buffer1ToMMPage_WithErase    0x83//一
#define Buffer2ToMMPage_WithErase    0x86//将第二缓冲区的数据写入主存储器(擦除模式)
#define Buffer1ToMMPage_WithoutErase 0x88//Buffer 1 to Main Memory Page Program without Built-in Erase
#define Buffer2ToMMPage_WithoutErase 0x89//Buffer 2 to Main Memory Page Program without Built-in Erase
#define Page_Erase                   0x81//Page Erase
#define Block_Erase                  0x50//Block Erase
#define Sector_Erase                 0x7C//Sector Erase

void SPI_FLASH_Init(void);
uint32_t SPI_Flash_ReadID(void);
void SPI_FLASH_PageErase(uint32_t PageAddr);
void SPI_FLASH_SectorErase(uint32_t SectorAddr);
void SPI_FLASH_PageWrite(uint8_t *pBuffer,uint16_t Page, uint16_t Byte,uint16_t NumByteToWrite);
void SPI_FLASH_BufferWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
void SPIx_SetSpeed(uint8_t SpeedSet);
uint8_t SPIx_ReadWriteByte(uint8_t TxData);


#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值