现在的位置: 首页 > 综合 > 正文

外部FLASH AT45DB642D的读写说明及AT91SAM7X256下C实现

2018年08月26日 ⁄ 综合 ⁄ 共 3106字 ⁄ 字号 评论关闭

AT45DB642是一种单2.7V供电,具有两种接口方式:一种为SI/SO方式,一种为I/O0-I/O7方式。这种两接口方式可使得它同时接在一个DSP和一个微控制器上。可用于数字声音、图像、程序代码及数据存储。

AT45DB642使用串行或并行方式顺序访问数据,支持SPI方式0和SPI方式3.通过片选引脚(CS)激活,通过串行输入(SI)、串行输出(SO)、串行时钟(SCK)连接。或通过并行输入、输出(I/O0-I/07)和时钟(clk)连接。SCK和CLK共用一个引脚,且向存储器提供相同时钟。

AT45DB642的存储阵列划分为三个等级:扇区、块和页。所有的编程操作基础是页-页过程。而对于擦除操作可使用块和页两种方式。

芯片操作!!

AT45DB642通过接收主控制器发来的指令来完成相应的操作。两种交互的指令是以操作码的形式实现。如读命令如下:

一个有效指令必须以CS片选信号的下降沿开始,后面伴随的是8位的指令码及要使用的BUFFER(缓存)或主存储器位置信息。CS引脚拉低后,伴随着SCK/CLK引脚时钟信号,通过SI引脚(串行方式)或I/O0-I/O7(并行方式)输入指令码及要使用的地址信息。注:所有指令、地址及数据都是先传送最高有效位方式完成传递。

 

连续读!

通过提供主存储器中首个要读取数据的地址信息,连续读命令即可根据时钟信号读出连续的数据流。之所以不需要额外的命令或地址信息,是因为AT45DB642内部集成了一个地址计数器,它在每一个时钟周期过后自动增加。若执行一个连续读操作,则需要在0x68h或e8h操作码后紧跟着输入的三个地址字节(包括24位的页地址和字节地址)及串行无关字节(串行无关为4个字节或并行无关60个字节)。伴随着无关位的正确输入,串行的SO或并行IO口会输出连续数据流。

 

FLASH整体擦除

可通过执行芯片擦除指令来完成整个FLASH区域的擦除。时序图如下:

因为是整体存储区域擦除,因此不需要地址或数据信息。

 

AT91SAM7X256下C程序实现:

void  Read_Flash_Buffer1				   //基本都使用缓存的地址信息
(
 unsigned int  BufferAddr,
 unsigned char *pValue,	 
 unsigned int  ByteNum
)
{
   	int i,j;
	unsigned int  AddrLocal;
	unsigned char AddrByte[3];
	unsigned char StatusCommand;
	
	AT91PS_SPI SPI0 = AT91C_BASE_SPI0;
	StatusCommand = READ_BUF1_HIGH;

	//parse the address to 3 address bytes for SPI chansfer
	AddrLocal =BufferAddr;
    	for(i=0;i<3;i++)
	   AddrByte[i]=AddrLocal>>(i*8);

   	 //send opcode
	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	AT91F_SPI_PutChar(SPI0,StatusCommand,3);
	for(j=0;j<10;j++);

    	//send start address
    	for(i=2;i>=0;i--)
	{
	   while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	   AT91F_SPI_PutChar(SPI0,AddrByte[i],3);
	   for(j=0;j<8;j++);
	}

	//send one dummy byte
	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	AT91F_SPI_PutChar(SPI0,0x00,3);
	for(j=0;j<8;j++);

    	//receive data   
	for(i=0;i<ByteNum;i++)
	{
	   while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	   AT91F_SPI_PutChar(SPI0,0x00,3);
	   for(j=0;j<10;j++);
	   while(!(SPI0->SPI_SR & AT91C_SPI_RDRF));    
	   *(pValue+i)=AT91F_SPI_GetChar(SPI0); 
	}
}
void  Write_Flash_Buffer1
(
 unsigned int  BufferAddr,
 unsigned char *pValue,	 
 unsigned int  ByteNumber
)
{
    	int i,j;
	unsigned int  AddrLocal;
	unsigned char AddrByte[3];
	unsigned char StatusCommand;   //StatusCommand为0x84h  为实现缓冲区数据加载,一个字节操作码(缓冲区1为0x84h,缓冲区2为0x87h)                               			      //伴随三个字节的地址,其中包括14个不关心位和10bit缓存区地址位。
	AT91PS_SPI SPI0 = AT91C_BASE_SPI0;
	StatusCommand = WRITE_BUF1;

	//parse the address to 3 address bytes for SPI transfer 
	AddrLocal =BufferAddr;
   	for(i=0;i<3;i++)
	   AddrByte[i]=AddrLocal>>(i*8);

	//send opcode
    	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	for(j=0;j<100;j++);
	AT91F_SPI_PutChar(SPI0,StatusCommand,3);
    	for(j=0;j<10;j++);

	//send start address
   	for(i=2;i>=0;i--)
	{
	   while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	   AT91F_SPI_PutChar(SPI0,AddrByte[i],3);
	   for(j=0;j<8;j++);
	}

    	//send the data   		   //地址字节被正确写入之后,才开始进行数据的写入
	for(i=0;i<ByteNumber;i++)
	{
	   while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	   for(j=0;j<100;j++);
	   AT91F_SPI_PutChar(SPI0,*(pValue+i),3);   
	   for(j=0;j<10;j++);	 
	}

	//置NPCS3为高电平  
	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	SPI0->SPI_TDR = 0x00|AT91C_SPI_LASTXFER;		                
}

void Chip_Erase(void)
{
	unsigned int i;
	AT91PS_SPI SPI0 = AT91C_BASE_SPI0;

	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));	//数据发送准备完毕
	AT91F_SPI_PutChar(SPI0,0xC7,3);
	for(i=0;i<10;i++);
    	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	AT91F_SPI_PutChar(SPI0,0x94,3);
	for(i=0;i<10;i++);
	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	AT91F_SPI_PutChar(SPI0,0x80,3);
	for(i=0;i<10;i++);
	while(!(SPI0->SPI_SR & AT91C_SPI_TDRE));
	AT91F_SPI_PutChar(SPI0,0x9A,3);
}

(文章原创,转载请声明)

抱歉!评论已关闭.