PC通过串口发送flash数据给单片机写入AT45DB041D-SU
sbit CSN= P1^2;
sbit MOSI= P1^3;
sbit MISO= P1^4;
sbit SCK= P1^5;
bdata unsigned char st=0;
sbit st_1=st^0;
sbit st_2=st^1;
sbit st_3=st^2;
sbit st_4=st^3;
sbit st_5=st^4;
sbit st_6=st^5;
sbit st_7=st^6;
sbit st_8=st^7;
bdata unsigned char st1=0;
sbit st_11=st1^0;
sbit st_12=st1^1;
sbit st_13=st1^2;
sbit st_14=st1^3;
sbit st_15=st1^4;
sbit st_16=st1^5;
sbit st_17=st1^6;
sbit st_18=st1^7;
uchar SPI_RW(uchar byte)
{
//uchar bit_ctr;
st=byte;
MOSI=st_8;
SCK = 1;
st_18=MISO;
SCK = 0;
MOSI=st_7;
SCK = 1;
st_17=MISO;
SCK = 0;
MOSI=st_6;
SCK = 1;
st_16=MISO;
SCK = 0;
MOSI=st_5;
SCK = 1;
st_15=MISO;
SCK = 0;
MOSI=st_4;
SCK = 1;
st_14=MISO;
SCK = 0;
MOSI=st_3;
SCK = 1;
st_13=MISO;
SCK = 0;
MOSI=st_2;
SCK = 1;
st_12=MISO;
SCK = 0;
MOSI=st_1;
SCK = 1;
st_11=MISO;
SCK = 0;
return(st1); // return read byte
}
/**************************************************/
/**************************************************
Function: SPI_Read_Buf();
Description:
Reads 'bytes' #of bytes from register 'reg'
Typically used to read RX payload, Rx/Tx address
/**************************************************/
uchar SPI_Read_Buf(BYTE *pBuf,BYTE wbytes, BYTE rbytes)
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
for(byte_ctr=0; byte_ctr<wbytes; byte_ctr++) // then write all byte in buffer(*pBuf)
{
//DebugInfoChar(pBuf[byte_ctr]);
SPI_RW(pBuf[byte_ctr] );
}
for(byte_ctr=0;byte_ctr<rbytes;byte_ctr++)
{
//pBuf[byte_ctr] = SPI_RW(0); // Perform SPI_RW to read byte from
//DebugInfoChar(pBuf[byte_ctr]);
if(byte_ctr==0){
status=SPI_RW(0);
//DebugInfoChar(status);
}
//else DebugInfoChar(SPI_RW(0));
else SPI_RW(0);
}
CSN = 1; // Set CSN high again
return(status); // return status byte
}
#define ACK_NONE 0x0
#define ACK_SUMERR 0x1
#define ACK_UNSPORT 0x2
#define ACK_DONE 0x3
//=============================
#define CMD_WRITE_START 0
#define CMD_WRITE_END 1
#define CMD_WRITE_DATA 2
#define CMD_READ 3
#define CMD_GET_PAGESIZE 4
#define CMD_ERASE_PAGE 5
//
#define CMD_INDEX 0
#define CMD_HIGH 1
#define CMD_LOW 2
#define CMD_END_HIGH 3
#define CMD_END_LOW 4
//#define CMD_CHECKSUM 18
//#define CMD_MAX 19
//2048 2112
#define SECTOR_SZIE 2048
#define SECTOR_ADDR_A 0x0a
#define SECTOR_ADDR_B 0x0b
#define SECTOR_ADDR_START 1
#define SECTOR_ADDR_END 7
//2048 2112
#define BLOCK_SZIE 2048
#define BLOCK_ADDR_START 0
#define BLOCK_ADDR_END 255
#define BLOCK_COUNT 256
//256 264
#define PAGE_ADDR_COUNT 2048
u16 u16PageSize=256;
//256 bytes CMD opcode page address byte/buffer address
// cmd + A18-A8 + A7-A0/BFA7-BFA0
//Except Status Register Read D7
//Manufacturer and Device ID Read 9F
//low frequency:opcode 03h
uchar ReadStatusRegister(void)
{
uchar cmd=0xD7;
return SPI_Read_Buf(&cmd,1,1);
}
//0 is busy
uchar CheckBusy(void)
{
u16 count=1000;
u8 states;
while(count--)
{
states = ReadStatusRegister();
if(states&0x80)
{
if(states&0x01)u16PageSize=256;
else u16PageSize=264;
return 1;
}
delay_ms(10);
}
return 0;
}
void ReadManufacturer(void)
{
uchar cmd=0x9F;
CheckBusy();
SPI_Read_Buf(&cmd,1,4);
}
/*
//Chip Erase
void ChipErase(void)
{
u8 cmd[4];
cmd[0]=0xC7;
cmd[0]=0x94;
cmd[0]=0x80;
cmd[0]=0x9A;
SPI_Read_Buf(cmd,4,0);
}
void EnableSectorProtectionCommand(void)
{
u8 cmd[4];
cmd[0]=0x3D;
cmd[0]=0x2A;
cmd[0]=0x7F;
cmd[0]=0xA9;
SPI_Read_Buf(cmd,4,0);
}
void DisableSectorProtectionCommand(void)
{
u8 cmd[4];
cmd[0]=0x3D;
cmd[0]=0x2A;
cmd[0]=0x7F;
cmd[0]=0x9A;
SPI_Read_Buf(cmd,4,0);
}
//7C H A18-A11 0a 0b 1-7 sector
void SectorErase(u8 addr)
{
u8 cmd[4];
CheckBusy();
cmd[0]=0x81;
//A18 - A11
if(addr == 0x0a )
{
cmd[1]=0;//A23-A16
cmd[2]=0;//A15-A8
cmd[3]=0;//A7-A0
}
else if( addr == 0x0b)
{
cmd[1]=0;//A23-A16
cmd[2]=0x08;//A15-A8
cmd[3]=0;//A7-A0
}
//A18-A16
else
{
cmd[1]=(addr>>8)&0x7;//A23-A16
cmd[2]=(addr>>8)&0xff;//A15-A8
cmd[3]=0;//A7-A0
}
SPI_Read_Buf(cmd,4,0);
}
//50 H A18-A11 Block0=0-7page page=256/264 bytes 0-255block
void BlockErase(u8 addr)
{
u8 cmd[4];
CheckBusy();
cmd[0]=0x50;
if(u16PageSize == 256)
{
cmd[1]=(addr>>5)&0x7;//A23-A16
cmd[2]=(addr<<3)&0xf8;//A15-A8
}
else//264
{
cmd[1]=(addr>>4)&0x0f;//A23-A16
cmd[2]=(addr<<4)&0xf0;//A15-A8
}
cmd[3]=0;//A7-A0
SPI_Read_Buf(cmd,4,0);
}
*/
//81 H A18-A8 page=256/264 bytes 0-2047page
void PageErase(u16 addr)
{
u8 cmd[4];
CheckBusy();
cmd[0]=0x81;
if(u16PageSize == 256)
{
cmd[1]=(addr>>8)&0x7;//A23-A16
cmd[2]=addr&0xff;//A15-A8
}
else//264
{
cmd[1]=(addr>>7)&0x0f;//A23-A16
cmd[2]=(addr<<1)&0xfe;//A15-A8
}
cmd[3]=0;//A7-A0
SPI_Read_Buf(cmd,4,0);
}
//Main Memory Page Program Through Buffer
//82 buffer1 85 buffer2 A18-A8
//84 87 -> 83 86
//Buffer to Main Memory Page Program with Built-in Erase
//83 buffer1 86h buffer2
void MainMemoryPageProgramThroughBuffer(u16 addr,u16 vender)
{
u8 cmd[4],i;
cmd[0]=0x85;
if(u16PageSize == 256)
{
cmd[1]=(addr>>8)&0x7;//A23-A16
cmd[2]=addr&0xff;//A15-A8
cmd[3]=vender;//A7-A0
}
else //264
{
cmd[1]=(addr>>7)&0xf;//A23-A16
cmd[2]=(addr<<1)&0xfe;//A15-A8
cmd[2]|=(vender>>8)&0x01;//A15-A8
cmd[3]=vender&0xff;//A7-A0
}
for(i=0; i<4; i++) // then write all byte in buffer(*pBuf)
{
SPI_RW(cmd[i]);
}
}
//Main Memory Page Read
//D2 The first 11 bits (A18 - A8) of the 19-bits sequence specify which page of the main memory array to read
//the last 8 bits (A7 - A0) of the 19-bits address sequence specify the starting byte address within the page
void MainMemoryPageRead(u16 addr,u16 vender,u8 dummy,u16 size)
{
u8 cmd[4];
u16 i;
cmd[0]=0xD2;
if(u16PageSize == 256)
{
cmd[1]=(addr>>8)&0x7;//A23-A16
cmd[2]=addr&0xff;//A15-A8
cmd[3]=vender;//A7-A0
}
else //264
{
cmd[1]=(addr>>7)&0xF;//A23-A16
cmd[2]=(addr<<1)&0xfe;//A15-A8
cmd[2]|=(vender>>8)&0x01;//A15-A8
cmd[3]=vender&0xff;//A7-A0
}
CheckBusy();
CSN = 0; // Set CSN low, init SPI tranaction
for(i=0;i<4; i++) // then write all byte in buffer(*pBuf)
{
SPI_RW(cmd[i]);
}
for(i=0;i<dummy; i++) // then write all byte in buffer(*pBuf)
{
SPI_RW(0);
}
for(i=0; i<size; i++)
{
DebugInfoChar(SPI_RW(0));
}
CSN = 1;
}
void UartPageCmd()
{
u8 cmd=0;
u16 addr=0,i=0;
//checksum
if(DataCheckSum() == 0)
{
DebugInfoStr("err:sum");
delay_ms(30);
addr = COM1.RX_Cnt;
for(i=0;i<addr;i++){
if(i < COM_RX1_Lenth)
{
DebugInfoChar(RX1_Buffer[i]);
}
else
{
DebugInfoChar(RX1_XBuffer[i-COM_RX1_Lenth]);
}
}
return;
}
cmd = RX1_Buffer[CMD_INDEX];
switch(cmd)
{
case CMD_WRITE_START:
{
addr = (RX1_Buffer[CMD_HIGH]<<8) | (RX1_Buffer[CMD_LOW]);
PageErase(addr);
CheckBusy();
CSN = 0; // Set CSN low, init SPI tranaction
MainMemoryPageProgramThroughBuffer(addr,0);
DebugInfoStr("done");
}break;
case CMD_WRITE_END:
{
DebugInfoStr("done");
CSN = 1;
}
break;
case CMD_WRITE_DATA:
{
addr = (RX1_Buffer[CMD_HIGH]<<8) | (RX1_Buffer[CMD_LOW]);
for(i=3; i<(addr+3); i++)
{
if(i < COM_RX1_Lenth)
{
SPI_RW(RX1_Buffer[i]);
}
else
{
SPI_RW(RX1_XBuffer[i-COM_RX1_Lenth]);
}
}
DebugInfoStr("done");
}
break;
case CMD_READ:
{
i = (RX1_Buffer[CMD_END_HIGH]<<8) | (RX1_Buffer[CMD_END_LOW]);
for(;addr<=i;addr++){
MainMemoryPageRead(addr,0,4,u16PageSize);
}
}break;
case CMD_GET_PAGESIZE:
{
CheckBusy();
DebugInfoChar(u16PageSize>>8);
DebugInfoChar(u16PageSize&0xff);
DebugInfoChar(COM_RX1_Max>>8);
DebugInfoChar(COM_RX1_Max&0xff);
}break;
case CMD_ERASE_PAGE:
{
addr = (RX1_Buffer[CMD_HIGH]<<8) | (RX1_Buffer[CMD_LOW]);
PageErase(addr);
CheckBusy();
DebugInfoStr("done");
}break;
default:
{
DebugInfoStr("cmd unsuport");
delay_ms(30);
addr = COM1.RX_Cnt;
for(i=0;i<addr;i++){
if(i < COM_RX1_Lenth)
{
DebugInfoChar(RX1_Buffer[i]);
}
else
{
DebugInfoChar(RX1_XBuffer[i-COM_RX1_Lenth]);
}
}
}
break;
}
}