Chinaunix首页 | 论坛 | 博客
  • 博客访问: 488748
  • 博文数量: 164
  • 博客积分: 4024
  • 博客等级: 上校
  • 技术积分: 1580
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-10 16:27
文章分类

全部博文(164)

文章存档

2011年(1)

2010年(108)

2009年(55)

我的朋友

分类: 嵌入式

2009-11-10 16:26:58

 
 
本程序为AVR单片机SPI口访问AT45DB161D提供一组接口函数,通过这一组接口函数可非常容易的完成对AT45DB161D的读写操作.

AT45DB161D按页组织和操作(读写擦等等)内部的FLASH存储器,每页为528字节(特殊用途时可通过命令配置成512字节),其内部共集成4096页,即4096*528=2162688字节。本程序将为您提供读写这2162688字节存储区的线性操作方法。使用这些函数,用户可不必考虑AT45DB161D内部的存储器组织结构,如同读写一个文件一样进行读写操作。

void df_init(void);
这是SPI口初始化函数,它必须在所有这些接口函数调用之前得到调用

void df_read_open(uint32_t addr);
读操作初始化函数,addr指定接下来的读函数的开始读取位置。程序内部维护一个当前读取计数器,用户每读一字节该计数器加一

void df_write_open(uint32_t addr);
写操作初始化函数,addr指定接下来的写函数的开始写入位置。程序内部维护一个当前写入计数器,用户每写入一个字节该计数器加一

uint8_t df_getc(void);
此函数从当前读位置读取一字节后返回,内部的读计数器加一

void df_putc(uint8_t c);
此函数向当前写位置写入一字节的数据,并使内部写计数器加一

void df_read(uint8_t *buf,uint8_t size);
此函数从当前读位置读取size个字节的数据到缓冲区buf,并使内部读计数器加size

void df_write(uint8_t *buf,uint8_t size);
此函数从缓冲区buf向当前写位置写入size字节的数据,并使内部写计数器加size

void df_read_seek(uint32_t addr);
调整当前读计数器,调用此函数前必须已调用df_read_open

void df_write_seek(uint32_t addr);
调整当前写计数器,调用此函数前必须已调用df_write_open

void df_read_close(void);
关闭读操作

void df_write_close(void);
关闭写操作,所有的写入操作完成后必须调用此函来结束写操作,以便数据能够完整的保存到AT45DB161D主存储器当中
 

源程序:

/**********************************
AVR单片机SPI口读写at45db161d接口程序
文件名:dataflash.c
编译:WinAVR-20070525

芯艺设计室 2004-2007 版权所有
转载请保留本注释在内的全部内容
WEB:
Email: changfutong@sina.com
**********************************/

#i nclude
#i nclude "at45db161d.h"
#i nclude "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;idata[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;ispi_write(data[i]);

UNSELECT_CHIP;
}

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

void df_init(void)
{
//MISO设置为输入,上拉电阻关闭,其它默认为1
PORTB |= _BV(FLASH_SCK)|_BV(FLASH_MOSI)|_BV(FLASH_CS)|_BV(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); //缓冲区内容写入到主存储器
}

dataflash.h文件:

#ifndef DATAFLASH_H
#define DATAFLASH_H

//硬件引脚定义
#define FLASH_MOSI PB3
#define FLASH_MISO PB4
#define FLASH_SCK PB5
#define FLASH_CS PB1
#define UNSELECT_CHIP PORTB|=_BV(FLASH_CS)
#define SELECT_CHIP PORTB&=~_BV(FLASH_CS)

//
#define DF_PAGE_SIZE 528
#define DF_READ_BUFFER 0
#define DF_WRITE_BUFFER 1

#endif



   测试电路图和实物照片:

 

阅读(1771) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~