📄 at45.c
字号:
/****************************************************************
* ATMEL的DATAFLASH操作函数库(FOR AT45DB161D) *
* *
* 作者:gxlujd(彩虹) *
* 最后修改时间:2007年2月18日(大年初一) *
* *
* 感谢www.ouravr.com、阿莫和坛子里的哥们一直以来的热心帮助 *
* *
* 如果这些资源能帮到你,请保留以上这些信息,同时也请你把自 *
* 己的一些日常积累拿出来分享,这个世界需要更多的无私开源, *
* 别让金钱和利益蒙住了内心的真诚,谢谢! *
*****************************************************************/
/*modify:avenbbs(8785116@qq.com)*/
#include <avr/io.h>
#include <util/delay.h>
#include "AT45.h"
#include "spi_soft.h"
#define SPI_DF_EN() PORTD&=~(1<<PD2)
#define SPI_DF_DIS() PORTD|=(1<<PD2)
/*DATA_FLASH端口及指令定义*/
//#define DF_SPI_ON SPCR = 0x5F
//#define DF_SPI_OFF SPCR = 0x00
//#define DF_CON_PORT PORTC
//#define DF_STA_PORT PINC
//#define DF_STATE PC2
//#define DF_CS_1 PC1
//#define DF_SELECT_1 DF_CON_PORT &=~_BV(DF_CS_1)
//#define DF_DESELECT_1 DF_CON_PORT |=_BV(DF_CS_1)
#define BUFFER_1_WRITE 0x84 // 写入第一缓冲区
#define BUFFER_2_WRITE 0x87 // 写入第二缓冲区
#define BUFFER_1_READ 0xD4 // 读取第一缓冲区
#define BUFFER_2_READ 0xD6 // 读取第二缓冲区
#define B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 // 将第一缓冲区的数据写入主存储器(擦除模式)
#define B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 // 将第二缓冲区的数据写入主存储器(擦除模式)
#define MM_PAGE_TO_B1_XFER 0x53 // 将主存储器的指定页数据加载到第一缓冲区
#define MM_PAGE_TO_B2_XFER 0x55 // 将主存储器的指定页数据加载到第二缓冲区
#define PAGE_ERASE 0x81 // 页删除(每页512/DF_BUFFER_SIZE字节)
#define SECTOR_ERASE 0x7C // 扇区擦除(每扇区128K字节)
#define READ_STATE_REGISTER 0xD7 // 读取状态寄存器
//extern unsigned char DF_buffer[DF_BUFFER_SIZE];
//unsigned char DF_buffer[DF_BUFFER_SIZE];
extern unsigned char buf[];
#define DF_buffer buf
//往SPI口写一个字节的数据
/*void spiSWTransmit(unsigned char data)
{
SPDR = data;
while (!(SPSR & 0x80));
}*/
//格式化主存储器(以扇区<0A,0B,1……15>为单位删除所有页数据)
void DF_format(void)
{
unsigned char i;
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();// DF_SELECT_1;
spiSWTransmit(SECTOR_ERASE);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
SPI_DF_DIS();// DF_DESELECT_1;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(SECTOR_ERASE);
spiSWTransmit(0x00);
spiSWTransmit(0x20);
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
for (i=1;i<16;i++)
{
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(SECTOR_ERASE);
spiSWTransmit(i << 2);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
}
//DF_SPI_OFF;
}
//擦除指定的主存储器页(地址范围0-4095)
void DF_page_earse(unsigned int page)
{
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(PAGE_ERASE);
spiSWTransmit((unsigned char)(page >> 6));
spiSWTransmit((unsigned char)(page << 2));
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
}
//将保存在数组DF_buffer[]中的一页数据写入第二缓冲区后送入主存储区
//(先擦除后写入模式,页地址范围0-4095)
void DF_write_page(unsigned int page)
{
unsigned int i;
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(BUFFER_2_WRITE);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
for (i=0;i<DF_BUFFER_SIZE;i++)
{
unsigned char tmp;
tmp=DF_buffer[i];
spiSWTransmit(tmp);
}
SPI_DF_DIS();//DF_DESELECT_1;
if (page<4096)
{
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(B2_TO_MM_PAGE_PROG_WITH_ERASE);
spiSWTransmit((unsigned char)(page>>6));
spiSWTransmit((unsigned char)(page<<2));
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
DF_wait_busy();
}
//DF_SPI_OFF;
}
//将指定主存储器页的数据转入第一缓冲区后读出,保存在DF_buffer[]数组中
//(页地址范围0-4095)
void DF_read_page(unsigned int page)
{
unsigned int i;
//DF_SPI_ON;
// while(!(DF_STA_PORT & (1<< DF_STATE)));
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(MM_PAGE_TO_B1_XFER);
spiSWTransmit((unsigned char)(page >> 6));
spiSWTransmit((unsigned char)(page << 2));
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(BUFFER_1_READ);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
for (i=0;i<DF_BUFFER_SIZE;i++)
{
DF_buffer[i] =spiSWTransmit(0xFF);
//DF_buffer[i] = SPDR;
}
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
}
//以直接读取方式读取指定的主存储器页数据(页地址范围0-4095)
/*void DF_MM_read_page(unsigned int page)
{
unsigned int i;
//DF_SPI_ON;
while(!(DF_STA_PORT & (1<< DF_STATE)));
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(MAIN_MEMORY_PAGE_READ);
spiSWTransmit((unsigned char)(page >> 6));
spiSWTransmit((unsigned char)(page << 2));
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
spiSWTransmit(0x00);
for (i=0;i<DF_BUFFER_SIZE;i++)
{
DF_buffer[i] = spiSWTransmit(0x00);
//DF_buffer[i] = SPDR;
}
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
}*/
//读取状态寄存器
// bit7 bit6 bit6 bit6 bit6 bit6 bit6 bit6
//RDY/BUSY COMP 1 0 1 1 PROTECT PAGE SIZE
unsigned char DF_read_reg(void)
{
unsigned char temp;
//DF_SPI_ON;
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(READ_STATE_REGISTER);
//spiSWTransmit(0x00);
//spiSWTransmit(0x00);
//spiSWTransmit(0x00);
temp=spiSWTransmit(0x00);
//temp=SPDR;
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
return temp;
}
//检查状态寄存器最高位是否为忙,并等待空闲
void DF_wait_busy(void)
{
unsigned char state_reg=0x00;
SPI_DF_EN();//DF_SELECT_1;
spiSWTransmit(READ_STATE_REGISTER);
//spiSWTransmit(0x00);
//spiSWTransmit(0x00);
//spiSWTransmit(0x00);
while((state_reg&0x80) == 0)
{
state_reg = spiSWTransmit(0x00);
//state_reg = SPDR ;
}
SPI_DF_DIS();//DF_DESELECT_1;
}
//将指定主存储器页的数据转入指定缓冲区
void DF_mm_to_buf(unsigned char buffer,unsigned int page)
{
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
if (buffer==1)
spiSWTransmit(MM_PAGE_TO_B1_XFER);
else
spiSWTransmit(MM_PAGE_TO_B2_XFER);
spiSWTransmit((unsigned char)(page >> 6));
spiSWTransmit((unsigned char)(page << 2));
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
}
//读取指定缓冲区指定单元的数据,保存在DF_buffer[]数组中
unsigned char DF_read_buf(unsigned char buffer,unsigned int start_address,unsigned int length)
{
unsigned int i;
if ((DF_BUFFER_SIZE-1-start_address)>=length)
{
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
if (buffer==1)
spiSWTransmit(BUFFER_1_READ);
else
spiSWTransmit(BUFFER_2_READ);
spiSWTransmit(0x00);
spiSWTransmit((unsigned char)(start_address >> 8));
spiSWTransmit((unsigned char)start_address);
spiSWTransmit(0x00);
for (i=0;i<length;i++)
{
DF_buffer[i] = spiSWTransmit(0xFF);
//DF_buffer[i] = SPDR;
}
SPI_DF_DIS();//DF_DESELECT_1;
//DF_SPI_OFF;
return 1;
}
else
return 0;
}
//将DF_buffer[]数组中指定长度的数据写入指定缓冲区
unsigned char DF_write_buf(unsigned char buffer,unsigned int start_address,unsigned int length)
{
unsigned int i;
if ((DF_BUFFER_SIZE-1-start_address)>=length)
{
//DF_SPI_ON;
DF_wait_busy();
SPI_DF_EN();//DF_SELECT_1;
if (buffer==1)
spiSWTransmit(BUFFER_1_WRITE);
else
spiSWTransmit(BUFFER_2_WRITE);
spiSWTransmit(0x00);
spiSWTransmit((unsigned char)(start_address >> 8));
spiSWTransmit((unsigned char)start_address);
for (i=0;i<length;i++)
spiSWTransmit(DF_buffer[i]);
SPI_DF_DIS();//DF_DESELECT_1;
return 1;
}
else
return 0;
}
//将指定缓冲区中的数据写入主存储区的指定页
void DF_buf_to_mm(unsigned char buffer,unsigned int page)
{
//DF_SPI_ON;
DF_wait_busy();
if (page<4096)
{
SPI_DF_EN();//DF_SELECT_1;
if (buffer==1)
spiSWTransmit(B1_TO_MM_PAGE_PROG_WITH_ERASE);
else
spiSWTransmit(B2_TO_MM_PAGE_PROG_WITH_ERASE);
spiSWTransmit((unsigned char)(page>>6));
spiSWTransmit((unsigned char)(page<<2));
spiSWTransmit(0x00);
SPI_DF_DIS();//DF_DESELECT_1;
}
//DF_SPI_OFF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -