⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dataflash.c

📁 at45db161d的测试
💻 C
字号:
/************************
	AVR单片机SPI口读写at45db161d接口程序
	文件名:dataflash.c
	编译:WinAVR-20070525
	设计思路:AT45DB161D内部有两个页缓冲BUFFER1和BUFFER2
					本程序将它们分别用于读和写,当用户调用df_read_open函数时
					将主存储器内的数据读到BUFFER1中,当用户调用df_getc或df_read时
					从BUFFER1中给出要求长度的数据并对读进度进行记录,当读地址超出
					当前页范围时向缓冲区装入下一页数据。
					写入功能与读类似,但它使用BUFFER2.每更新一页时使用BUFFER到主
					存储区的带擦除功能的命令,为此写之前不必考虑先擦器件。
					
					调用示例:
					
					//以下三行实现在1300地址处写入0xaa
					df_write_open(1300);
					df_putc(0xaa);
					df_write_close();
					
					//以下三行实现读出那1300处的一个字节数据
					df_read_open(1300);
					x=df_getc();
					df_read_close();
					
	注意事项:
					1.尽量避免频繁调用df_write_open和df_write_close
					如果写一组数据到指定地址,实现代码应当是这样的
					df_write_open(xxx);
						...写数据...
						//一次操作中不论写多少字节都应当在这里完成
					df_write_close();
					而不是
					for(i=xxx;i<nnn;i++)
					{
						df_write_open(xxx+i);
						df_putc(buf[i]);
						df_write_close();
					}
					2.df_read和df_write一次可读或写多个字节,它们比df_getc和df_putc
					 效率会高一些
					
	
	芯艺设计室 2004-2007  版权所有 
	转载请保留本注释在内的全部内容
	WEB: http://www.chipart.cn
	Email: changfutong@sina.com
*******************************/

#include <avr/io.h>
#include "at45db161d.h"
#include "dataflash.h"

/*****下面是全局变量定义******/
static uint16_t g_CurReadPage;//当前读的页地址
static uint16_t g_CurReadByte;//当前读的字节(页中地址)
static uint16_t g_CurWritePage;//当前写的页地址
static uint16_t g_CurWriteByte;//当前写的字节地址(页中地址)

/*****下面是文件内部使用的函数******/

//从SPI口输出一字节数据
static uint8_t spi_write(uint8_t data)
{
	SPDR = data;
	while(!(SPSR & _BV(SPIF)));
	return SPDR;
}

//检测并等待器件忙状态,8引脚封闭器件没有 RDY/BUSY引脚 为些通过读状态寄存器来检测忙状态
static void df_wait_busy(void)
{
	SELECT_CHIP;
	spi_write(STATUS_REGISTER);
	while(1)
	{
		if(spi_write(0) & 0x80) //读取的最高位0时器件忙
			break;
	}
	UNSELECT_CHIP;
}

//读主存储器指定页到读缓冲区(BUFFER1)
static void load_page_to_buffer(uint16_t page,uint8_t buffer)
{
	SELECT_CHIP;
	
	if(buffer == DF_READ_BUFFER)            
		spi_write(MM_PAGE_TO_B1_XFER);    
	else
		spi_write(MM_PAGE_TO_B2_XFER);
	spi_write((uint8_t)(page >> 6));
	spi_write((uint8_t)(page << 2));
	spi_write(0x00);
	
	UNSELECT_CHIP; 
	
	df_wait_busy();
}

//将写缓冲区内容写入到主存储器中指定页
static void write_page_from_buffer(uint16_t page,uint8_t buffer)
{
	SELECT_CHIP;
	
	if(buffer == DF_WRITE_BUFFER) 
		spi_write(B2_TO_MM_PAGE_PROG_WITH_ERASE);
	else
		spi_write(B1_TO_MM_PAGE_PROG_WITH_ERASE);
	spi_write((uint8_t)(page>>6));
	spi_write((uint8_t)(page<<2));
	spi_write(0x00);  // don't cares
	
	UNSELECT_CHIP;
	
	df_wait_busy();
}

//从读缓冲区读数据
static void read_buffer(uint16_t addr,uint8_t *data,uint8_t size)
{
	uint8_t i;
	
	SELECT_CHIP;
	
	spi_write(BUFFER_1_READ);
	spi_write(0x00);                        
	spi_write((uint8_t)(addr>>8));
	spi_write((uint8_t)addr); 
	for(i=0;i<size;i++)      
		data[i]=spi_write(0);
		                 
	UNSELECT_CHIP;	
}

//将数据写入写缓冲区
static void write_buffer(uint16_t addr,uint8_t *data,uint8_t size)
{
	uint8_t i;
	
	SELECT_CHIP;
	
	spi_write(BUFFER_2_WRITE);
	spi_write(0x00);                        
	spi_write((uint8_t)(addr>>8));
	spi_write((uint8_t)addr); 
	for(i=0;i<size;i++)      
		spi_write(data[i]);
		                 
	UNSELECT_CHIP;
}

/*****下面是为外部调用而提供的接口函数******/

void df_init(void)
{
	//MISO设置为输入,上拉电阻关闭,其它默认为1
	PORTB |= _BV(FLASH_SCK)|_BV(FLASH_MOSI)|_BV(FLASH_CS)|_BV(PB2);	
	/*
		注:使用AVR单片机SPI口,并用作主器件时SS引脚(ATMEGA8中PB2)要拉高或设置成输出!
	*/
	
	//SCK,MOSI和CS端口对应脚设置为输出
	DDRB |= _BV(FLASH_SCK)|_BV(FLASH_MOSI)|_BV(FLASH_CS);                            
	
	// SPI中断禁止, SPI使能, master模式, MSB 前,  SPI 模式 3, SCK频率Fcl/4
	SPCR = _BV(SPE)|_BV(MSTR)|_BV(CPHA)|_BV(CPOL);//|_BV(SPR1)|_BV(SPR0);
}

//读初始化功能函数,addr为打开后读到的初始地址
void df_read_open(uint32_t addr)
{
	g_CurReadPage=addr/DF_PAGE_SIZE;	
	g_CurReadByte=addr%DF_PAGE_SIZE;
	load_page_to_buffer(g_CurReadPage,DF_READ_BUFFER);
}

void df_write_open(uint32_t addr)
{
	g_CurWritePage=addr/DF_PAGE_SIZE;
	g_CurWriteByte=addr%DF_PAGE_SIZE;
	load_page_to_buffer(g_CurWritePage,DF_WRITE_BUFFER);
}

uint8_t df_getc(void)
{
	uint8_t c;
	
	read_buffer(g_CurReadByte,&c,1);
	g_CurReadByte++;
	if(g_CurReadByte ==DF_PAGE_SIZE)
	{
		g_CurReadPage++;
		load_page_to_buffer(g_CurReadPage,DF_READ_BUFFER);
		g_CurReadByte=0;
	}
	
	return c;
}

void df_putc(uint8_t c)
{
	write_buffer(g_CurWriteByte,&c,1);
	g_CurWriteByte++;
	if(g_CurWriteByte == DF_PAGE_SIZE)
	{
		g_CurWriteByte=0;
		write_page_from_buffer(g_CurWritePage,DF_WRITE_BUFFER);
		g_CurWritePage++;
		load_page_to_buffer(g_CurWritePage,DF_WRITE_BUFFER);
	}
}

void df_read(uint8_t *buf,uint8_t size)
{
	uint8_t temp;
	
	if((g_CurReadByte + size) > DF_PAGE_SIZE) //如果当前页未读取数据不够size字节
	{
		//读当前页剩余数据
		temp=DF_PAGE_SIZE - g_CurReadByte;
		read_buffer(g_CurReadByte,buf,temp);
		
		//装入下一页
		load_page_to_buffer(++g_CurReadPage,DF_READ_BUFFER);
		
		//从下一页读剩余数据
		g_CurReadByte=size-temp;
		read_buffer(0,buf+temp,g_CurReadByte);
	}
	else			//如果当前页数据有size字节
	{
		read_buffer(g_CurReadByte,buf,size);
		g_CurReadByte+=size;
		
		//如果当前页数据已全部读完
		if(g_CurReadByte==DF_PAGE_SIZE)
		{
			load_page_to_buffer(++g_CurReadPage,DF_READ_BUFFER);
			g_CurReadByte=0;			
		}
	} 
}

void df_write(uint8_t *buf,uint8_t size)
{
	uint8_t temp;
	
	if((g_CurWriteByte + size) > DF_PAGE_SIZE) //如果当前页未写空间不够size字节
	{
		//写当前页剩余空间的数据
		temp=DF_PAGE_SIZE - g_CurWriteByte;
		write_buffer(g_CurWriteByte,buf,temp);
		//保存当前页
		write_page_from_buffer(g_CurWritePage,DF_WRITE_BUFFER);
		g_CurWritePage++;
		load_page_to_buffer(g_CurWritePage,DF_WRITE_BUFFER);
		
		//写入到下一页对应缓冲区
		g_CurWriteByte=size-temp;
		write_buffer(0,buf+temp,g_CurWriteByte);
	}
	else
	{
		write_buffer(g_CurWriteByte,buf,size);
		g_CurWriteByte+=size;
		
		//缓冲已满,写入到主存储区
		if(g_CurWriteByte==DF_PAGE_SIZE)
		{
			g_CurWriteByte=0;
			write_page_from_buffer(g_CurWritePage,DF_WRITE_BUFFER);
			g_CurWritePage++;		
			load_page_to_buffer(g_CurWritePage,DF_WRITE_BUFFER);			
		}
	} 	
}

//调整写指针
void df_read_seek(uint32_t addr)
{
	df_read_close();
	df_read_open(addr);
}

//调整读指针
void df_write_seek(uint32_t addr)
{
	df_write_close();
	df_write_open(addr);	
}

void df_read_close(void)
{
	//此处不做任何处理
}

void df_write_close(void)
{
	write_page_from_buffer(g_CurWritePage,DF_WRITE_BUFFER); //缓冲区内容写入到主存储器
}

//下面两个函数用于测试
/* //全片擦除
void df_erase(void)
{
	uint16_t block_counter = 0;
	
	while (block_counter < 512)
	{
		SELECT_CHIP;
		
		spi_write(BLOCK_ERASE);
		spi_write((uint8_t)(block_counter>>3));
		spi_write((uint8_t)(block_counter<<5));
		spi_write(0x00);
		
		UNSELECT_CHIP;
		
		block_counter++;
		df_wait_busy();
	}
}
*/
/*//读芯片ID
void df_read_deviceid(uint8_t *buf)
{
	uint8_t i;
	
	SELECT_CHIP;
	
	spi_write(0x9f);
	for(i=0;i<4;i++)
		buf[i]=spi_write(0xff);
	
	UNSELECT_CHIP;
}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -