?? 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 + -