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