📄 at45db161d.c
字号:
/************************************************
flash 读写程序
2008年6月20日
*************************************************/
#include "2008.h"
#define DF_PAGE_SIZE 528
#define DF_READ_BUFFER 0
#define DF_WRITE_BUFFER 1
#define MM_PAGE_TO_B1_XFER 0x53 //主存储器页到缓存区转移命令(缓冲区1 53H 缓冲区2 55H)
// main memory page to buffer 2 transfer
#define MM_PAGE_TO_B2_XFER 0x55 //主存储器页到缓存区转移命令(缓冲区1 53H 缓冲区2 55H)
// buffer 1 to main memory page program with built-in erase
#define B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83
// buffer 2 to main memory page program with built-in erase
#define B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86
// buffer 1 read
#define BUFFER_1_READ 0xd1 //0xD4
// buffer 2 read
#define BUFFER_2_READ 0xd3 //0xD6
// buffer 1 write
#define BUFFER_1_WRITE 0x84
// buffer 2 write
#define BUFFER_2_WRITE 0x87
#define STATUS_REGISTER 0xD7
#define UNSELECT_CHIP PORTB |= 0x10;
#define SELECT_CHIP PORTB &= 0xef;
uint g_CurReadPage;//当前读的页地址
uint g_CurReadByte;//当前读的字节(页中地址)
uint g_CurWritePage;//当前写的页地址
uint g_CurWriteByte;//当前写的字节地址(页中地址)
//====================================================================
void df_init(void)
{
//MISO设置为输入,上拉电阻关闭,其它默认为1
//PORTB |= _BV(FLASH_SCK)|_BV(FLASH_MOSI)|_BV(FLASH_CS)|_BV(PB2);
//PORTB |= 1 2 4 0
PORTB |= 0x17;
/*
注:使用AVR单片机SPI口,并用作主器件时SS引脚(ATMEGA8中PB2)要拉高或设置成输出!
*/
//SCK,MOSI和CS端口对应脚设置为输出
//DDRB |= _BV(FLASH_SCK)|_BV(FLASH_MOSI)|_BV(FLASH_CS);
//DDRB |= 1 2 4
DDRB |= 0X16; //配置为输出
// SPI中断禁止, SPI使能, master模式, MSB 前, SPI 模式 3, SCK频率Fcl/4
//SPCR = _BV(SPE)|_BV(MSTR)|_BV(CPHA)|_BV(CPOL);//|_BV(SPR1)|_BV(SPR0);
SPCR = 0x5c; //SPI控制寄存器
}
//======================================================================
//写初始化功能函数,addr为打开后读到的初始地址
void df_write_open(uint addr)
{
g_CurWritePage=addr/DF_PAGE_SIZE;
g_CurWriteByte=addr%DF_PAGE_SIZE;
load_page_to_buffer(g_CurWritePage,DF_WRITE_BUFFER);
}
//======================================================================
//读初始化功能函数,addr为打开后读到的初始地址
void df_read_open(uint addr)
{
g_CurReadPage=addr/DF_PAGE_SIZE;
g_CurReadByte=addr%DF_PAGE_SIZE;
load_page_to_buffer(g_CurReadPage,DF_READ_BUFFER);
}
//=======================================================================
//读主存储器指定页到读缓冲区(BUFFER1)
void load_page_to_buffer(uint page,uint buffer)
{
SELECT_CHIP;
if(buffer == DF_READ_BUFFER) //=0
spi_write(MM_PAGE_TO_B1_XFER); //0x53
else
spi_write(MM_PAGE_TO_B2_XFER); //0x55
spi_write((uint)(page >> 6));
spi_write((uint)(page << 2));
spi_write(0x00);
UNSELECT_CHIP;
df_wait_busy();
}
//=======================================================================
//从SPI口输出一字节数据
uint spi_write(uint data)
{
SPDR = data;
while(!(SPSR & 0x80)); //判断 SPIF
return SPDR;
}
//=======================================================================
//检测并等待器件忙状态,8引脚封闭器件没有 RDY/BUSY引脚 为些通过读状态寄存器来检测忙状态
void df_wait_busy(void)
{
SELECT_CHIP;
spi_write(STATUS_REGISTER);
while(1)
{
if(spi_write(0) & 0x80) //读取的最高位0时器件忙
break;
}
UNSELECT_CHIP;
}
//=======================================================================
void df_write(uint *buf,uint size) //buf 源数据 size 写多少个字节
{
uint 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);
}
}
}
//========================================================================
//将数据写入写缓冲区2 命令 0x87
void write_buffer(uint addr,uint *data,uint size)
{
uint i;
SELECT_CHIP;
spi_write(BUFFER_2_WRITE);
spi_write(0x00); //写入缓冲区地址15位无关位
spi_write((uint)(addr>>8)); //写入缓冲区地址
spi_write((uint)addr); //写入缓冲区地址 总共写了三个字节地址 24位 15位无关位
for(i=0;i<size;i++)
spi_write(data[i]); //写数据
UNSELECT_CHIP;
}
//========================================================================
//将写缓冲区内容写入到主存储器中指定页
void write_page_from_buffer(uint page,uint buffer)
{
SELECT_CHIP;
if(buffer == DF_WRITE_BUFFER)
spi_write(B2_TO_MM_PAGE_PROG_WITH_ERASE); //0x86
else
spi_write(B1_TO_MM_PAGE_PROG_WITH_ERASE); //0x83
spi_write((uint)(page>>6)); //2个无关位,12位页地址 PA11~PA0 与10个无关位
spi_write((uint)(page<<2));
spi_write(0x00); // don't cares
UNSELECT_CHIP;
df_wait_busy();
}
//========================================================================
void df_write_close(void)
{
write_page_from_buffer(g_CurWritePage,DF_WRITE_BUFFER); //缓冲区内容写入到主存储器
}
//========================================================================
void df_read_close(void)
{
;//此处不做任何处理
}
//========================================================================
void df_read(uint *buf,uint size)
{
uint 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 read_buffer(uint addr,uint *data,uint size)
{
uint i;
SELECT_CHIP;
spi_write(BUFFER_1_READ);
spi_write(0x00);
spi_write((uint)(addr>>8));
spi_write((uint)addr);
for(i=0;i<size;i++)
data[i]=spi_write(0);
UNSELECT_CHIP;
}
//========================================================================
void Read_Page(uint page,uint page_address, uint *buf,uint size) //page 页地址, page_address 页内地址, buf 数据 , size 多少个字节
{
load_page_to_buffer(page,DF_READ_BUFFER); // 将主存储器指定的页内容读到缓冲区
read_buffer(page_address,buf,size); //从读缓冲区读数据
}
//========================================================================
void Write_page(uint page, uint page_address, uint *buf,uint size) //page 页地址, page_address 页内地址, buf 数据 , size 多少个字节
{
load_page_to_buffer(page,DF_WRITE_BUFFER); // 将主存储器指定的页内容读到缓冲区
write_buffer(page_address,buf,size); //将数据写入写缓冲区
write_page_from_buffer(page,DF_WRITE_BUFFER); //将缓冲区内容写入到主存储器中指定页中
}
//========================================================================
void Page_Scrape(uint page) //page 要擦除的页
{
SELECT_CHIP;
spi_write(0x81); //页擦除
spi_write((uint)(page>>6)); //2个无关位,12位页地址 PA11~PA0 与10个无关位
spi_write((uint)(page<<2));
spi_write(0x00); // don't cares
UNSELECT_CHIP;
df_wait_busy();
}
//========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -