📄 at45db041d._c
字号:
/************************************************************
*本驱动只用于AT45DB041D默认页大小为264的情况
*页改为256后可以有些不同
*页的大小只能改一次(从264改为256),不能改回
************************************************************/
#include <iom16v.h>
#include <macros.h>
#include "AT45DB041D.h"
#include "eeprom.h"
/************************************************************
*SPI宏定义
************************************************************/
#define SPI_DDR DDRB
#define SPI_PORT PORTB
#define RESET 3
#define SS 4
#define MOSI 5
#define MISO 6
#define SCK 7
/************************************************************
*延时函数
************************************************************/
void DF_Delay(unsigned int n)
{
unsigned int i;
unsigned int j;
for(i=0;i<n;i++)
{
for(j=0;j<255;j++)
{
asm("nop");
}
}
}
/************************************************************
*Init SPI Port
************************************************************/
void SPI_Port_Init(void)
{
SPI_DDR |= ((1<<SS)|(1<<SCK)|(1<<MOSI));//设为输出
SPI_DDR &=~ (1<<MISO); //设为输入
SPI_PORT |= (1<<SS)|(1<<SCK)|(1<<MOSI); //输出高电平
SPI_PORT |= (1<<MOSI); //上拉
SPI_DDR|=(1<<RESET); //复位引脚设为输出
}
/************************************************************
*初始化SPI
************************************************************/
void SPI_Init(void)//最高能到fOSC/16
{
SPI_Port_Init();
//SPI使能, master模式, MSB 前, SPI 模式 3, SCK频率Fcl/4 平时SCK为高电平
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL);
//频率加倍
SPSR |= (1<<SPI2X);
}
/************************************************************
*使能SPI
************************************************************/
void SPI_Start(void)
{
SPCR |= (1<<SPE);
}
/************************************************************
*禁止SPI
************************************************************/
void SPI_Stop(void)
{
SPCR &=~ (1<<SPE);
}
/************************************************************
*SPI send a Byte
************************************************************/
void SPI_Write_Byte(unsigned char cData)
{
SPDR = cData; //write data
while(!(SPSR & (1<<SPIF))); //wait write ok
}
/************************************************************
*SPI send Bytes
************************************************************/
void SPI_Write_Bytes(unsigned char *cData,unsigned int DataLen)
{
unsigned int i;
for(i=0;i<DataLen;i++)
{
SPDR = *(cData+i); //write data
while(!(SPSR & (1<<SPIF))); //wait write ok
}
}
/************************************************************
*SPI Read char
************************************************************/
unsigned char SPI_Read_Byte(unsigned char cData)
{
SPDR = cData; //write data
while(!(SPSR & (1<<SPIF))); //wait receive ok
return SPDR; //返回数据
}
/************************************************************
*使能FLASH(低电平使能)
************************************************************/
void Enable_DFLASH(void)
{
unsigned char i=255;
while(i--); //延长上一次高电平时间
SPI_PORT&=~(1<<SS);
}
/************************************************************
*禁止FLASH(高电平禁止)
************************************************************/
void Disable_DFLASH(void)
{
unsigned char i=255;
SPI_PORT|=(1<<SS);
while(i--); //延长高电平时间
}
/************************************************************
*读取FLASH内部状态寄存器
*Bit 7:Ready/busy status (1:no busy ; 0:busy)
*Bit 6:Compare (1: no matche ; 0:matche) 最近的一次比较结果
*Bit 0:PAGE SIZE (1:256 bytes ; 0:264 bytes)
************************************************************/
unsigned char DF_Read_status_Register(void)
{
unsigned char rData=0;
Enable_DFLASH();
SPI_Write_Byte(Status_Register_Opcode);//write opcode
rData = SPI_Read_Byte(0x00);//read device's status
Disable_DFLASH();
return rData;
}
/************************************************************
*读取FLASH的页大小
*返回1表示每一页的大小为264 bytes,否则为256 bytes
************************************************************/
unsigned char DF_Check_Page_Size(void)
{
unsigned char Page_Size;
Page_Size=DF_Read_status_Register();
if(Page_Size&0x01) return 0;
return 1;
}
/************************************************************
*读取FLASH忙标志位(最多判断255次,不行还是返回且返回0)
************************************************************/
unsigned char DF_Check_Busy_State(void)
{
unsigned char state;
unsigned char i=255;
while(i)
{
state=DF_Read_status_Register();
if(state & 0x80) break; //读取的最高位0时器件忙
--i;
}
return i;
}
/************************************************************
*读取FLASH的产家ID的芯片ID等内容;
*以下函数会返回四个值,第一个数对AT45DB041D来说为0x1F;
*第四个数为 0x00;
*用此函数可以判断芯片的好坏,是否正常;
************************************************************/
void DF_Manufacturer_and_Device_ID(unsigned char *ID)
{
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
SPI_Write_Byte(Device_ID_Opcode);
for(i=0;i<4;i++)
{
ID[i] = SPI_Read_Byte(0);
}
Disable_DFLASH();
}
/************************************************************
*测试FLASH产家ID,正常返回1,否则返回0
************************************************************/
unsigned char Test_Manufacturer_ID(void)
{
unsigned char Test_Buf[4];
DF_Manufacturer_and_Device_ID(Test_Buf);
if(Test_Buf[0]!=0x1F) return 0; //产家ID不为0x1F则返回0
return 1;//正确返回 1
}
/************************************************************
*使FLASH进入Deep_Power_Down
************************************************************/
void DF_Deep_Power_Down(void)
{
DF_Check_Busy_State();
Enable_DFLASH();
SPI_Write_Byte(0xB9);//写Deep Power-down操作码
Disable_DFLASH();
}
/************************************************************
*使FLASH退出Deep_Power_Down
************************************************************/
void DF_Resume_from_Deep_Power_Down(void)
{
DF_Check_Busy_State();
Enable_DFLASH();
SPI_Write_Byte(0xAB);//写Resume from Deep Power-down操作码
Disable_DFLASH();
}
/************************************************************
*使能扇区保护
************************************************************/
void DF_Enable_Sector_Protection(void)
{
unsigned char Enable_Sector_Protection_Command[4]={0x3D,0x2A,0x7F,0xA9}; //使能扇区保护操作码
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)
{
SPI_Write_Byte(Enable_Sector_Protection_Command[i]);//写使能扇区保护操作码
}
Disable_DFLASH();
}
/************************************************************
*禁止扇区保护
************************************************************/
void DF_Disable_Sector_Protection(void)
{
unsigned char Disable_Sector_Protection_Command[4]={0x3D,0x2A,0x7F,0x9A};//禁止扇区保护操作码
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)
{
SPI_Write_Byte(Disable_Sector_Protection_Command[i]);//写禁止扇区保护操作码
}
Disable_DFLASH();
}
/************************************************************
*擦除扇区保护
************************************************************/
void DF_Erase_Sector_Protection_Register(void)
{
unsigned char Erase_Sector_Protection_Command[4]={0x3D,0x2A,0x7F,0xCF};//擦除扇区保护操作码
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)
{
SPI_Write_Byte(Erase_Sector_Protection_Command[i]);//写擦除扇区保护操作码
}
Disable_DFLASH();
}
/************************************************************
*设置扇区保护
*注意:会改变BUFFER1中的内容
*Sector_Protection_Register:数组中的0~7字节对对应0~7个扇区(0xFF:写保护)(0x00:擦除保护)
The Sector Protection Register can be reprogrammed while the sector protection enabled or dis-
abled. Being able to reprogram the Sector Protection Register with the sector protection enabled
allows the user to temporarily disable the sector protection to an individual sector rather than
disabling sector protection completely
************************************************************/
void DF_Program_Sector_Protection_Register(unsigned char *Sector_Protection_Register)
{
unsigned char Program_Sector_Protection_Command[4]={0x3D,0x2A,0x7F,0xFC};//设置扇区保护操作码
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)
{
SPI_Write_Byte(Program_Sector_Protection_Command[i]);//写设置扇区保护操作码
}
for(i=0;i<8;i++)
{
SPI_Write_Byte(Sector_Protection_Register[i]);//写设置扇区保护数据
}
Disable_DFLASH();
}
/************************************************************
*读取扇区保护寄存器内容(返回8个字节,对应8个扇区的情况)
---------------------------------------
|Sector Number |0 (0a, 0b) |1 to 7 |
---------------------------------------
|Protected | | FFH |
---------------- See PDF -----------
|Unprotected | | 00H |
---------------------------------------
************************************************************/
void DF_Read_Sector_Protection_Register(unsigned char *Sector_Protection_Register)
{
unsigned char Read_Sector_Protection_Register_Command[4]={0x32,0,0,0};
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)//write
{
SPI_Write_Byte(Read_Sector_Protection_Register_Command[i]);
}
for(i=0;i<8;i++)//read
{
Sector_Protection_Register[i] = SPI_Read_Byte(0);
}
Disable_DFLASH();
}
/************************************************************
*取消所有扇区保护
*返回1表示成功取消扇区所以保护
************************************************************/
unsigned char DF_Cancel_Sector_Protection(void)
{
unsigned char Sector_Protection_Register_for_Write[8]={0,0,0,0,0,0,0,0};//写入0为去保护
unsigned char Sector_Protection_Register_for_Read[8]={1,1,1,1,1,1,1,1};//防止默认值为0
unsigned int i;
unsigned char j=1;
//使能扇区保护
DF_Enable_Sector_Protection();
//设置扇区保护
DF_Program_Sector_Protection_Register(Sector_Protection_Register_for_Write);
//读取扇区保护寄存器内容
DF_Read_Sector_Protection_Register(Sector_Protection_Register_for_Read);
//判断扇区保护寄存器内容
for(i=0;i<8;i++)
{
if(Sector_Protection_Register_for_Read[i]!=0) j++;
}
//禁止扇区保护
DF_Disable_Sector_Protection();
return j;
}
/************************************************************
*设置扇区锁(被锁后不能再次解锁)
*被设置的扇区就只能读不能写
*非一般情况不要使用(除非数据不用再改)
*Sector_Addr :地址在哪个扇区中就会锁上那个扇区
************************************************************/
void DF_Program_Sector_Lockdown(unsigned long Sector_Addr)
{
//unsigned char Sector_Lockdown_Command=[4]={0x3D,0x2A,0x7F,0x30};//加锁操作码
unsigned char Sector_Lockdown_Command[4]={0x00,0x00,0x00,0x00};//防止写到,这里乱写
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
for(i=0;i<4;i++)//write
{
SPI_Write_Byte(Sector_Lockdown_Command[i]);
}
//write address
SPI_Write_Byte((unsigned char)(Sector_Addr>>16));
SPI_Write_Byte((unsigned char)(Sector_Addr>>8));
SPI_Write_Byte((unsigned char)Sector_Addr);
Disable_DFLASH();
}
/************************************************************
*读取扇区加锁寄存器(返回8个扇区的加锁寄存器值)
*如果有读到不为0的表示已被加锁
*(0扇区的高四位为0也表示没加锁,其它扇区一定要全为O)
************************************************************/
void DF_Read_Sector_Lockdown_Register(unsigned char *Sector_Lockdown_Register)
{
unsigned char Read_Sector_Lockdown_Register[4]={0x35,0x00,0x00,0x00};
unsigned char i;
DF_Check_Busy_State();
Enable_DFLASH();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -