|
发表于 2010-9-7 10:06:09
|
显示全部楼层
#include <p33fxxxx.h>
#define READ 0x03 // READ instruction code
#define WRITE 0x02 // WRITE instruction code
#define WRDI 0x04 // WR DISBALE instruction code
#define WREN 0x06 // WR ENABLE instruction code
#define RDSR 0x05 // RD STATUS instruction code
#define WRSR 0x01 // WR STATUS instruction code
#define NOPROT 0x00 // NO WRITE PROTECTION
#define ENPROT 0b0001100
#define Eprom_CS LATGbits.LATG3 //
typedef union
{
unsigned char Byte[16];
unsigned int Word[8];
}B16W8;
unsigned char EpromWriteStep = 255; // status of write
// 255: no write
// 220: start check status
// 221: check status step2
// 222: check status step3
// 223: check status step4
// 224: check status reasult
// 200: send WREN
// 199: send WREN complete
// 197: send WRITE
// 196: send Address high
// 195: send Address low
// 100: write complete
// default: send byte
unsigned char EpromReadStep = 255; // status of read
// 255: no read
// 220: start check status
// 221: check status step2
// 222: check status step3
// 223: check status step4
// 224: check status reasult
// 200: send READ
// 198: send Address high
// 197: send Address low
// 196: send first read clock cycle
// 254: Read complete
// default: send byte
unsigned char PageWrite; // Eprom page you want to write
unsigned char PageRead; // Eprom page you want to read
B16W8 Eprom_WriteBuf; // Eprom write buffer
B16W8 Eprom_ReadBuf; // Eprom Read buffer
const unsigned char Eprom_AddressTable[32][3]=
{
/*
addressH,
addressL,
length, max 16
*/
{ 0, 0, 16}, // 0
{ 0, 16, 16}, // 1
{ 0, 32, 16}, // 2
{ 0, 48, 16}, // 3
{ 0, 64, 16}, // 4
{ 0, 80, 16}, // 5
{ 0, 96, 16}, // 6
{ 0,112, 16}, // 7
{ 0,128, 16}, // 8
{ 0,144, 16}, // 9
{ 0,160, 16}, // 10
{ 0,176, 16}, // 11
{ 0,192, 16}, // 12
{ 0,208, 16}, // 13
{ 0,224, 16}, // 14
{ 0,240, 16}, // 15
{ 1, 0, 16}, // 16
{ 1, 16, 16}, // 17
{ 1, 32, 16}, // 18
{ 1, 48, 16}, // 19
{ 1, 64, 16}, // 20
{ 1, 80, 16}, // 21
{ 1, 96, 16}, // 22
{ 1,112, 16}, // 23
{ 1,128, 16}, // 24
{ 1,144, 16}, // 25
{ 1,160, 16}, // 26
{ 1,176, 16}, // 27
{ 1,192, 16}, // 28
{ 1,208, 16}, // 29
{ 1,224, 16}, // 30
{ 1,240, 16} // 31
};
//-----------------------------------Eprom_Init
void Eprom_Init(void)
{
/*Port set as output*/
TRISGbits.TRISG3 = 0;
/*No open Dran*/
ODCGbits.ODCG3 = 0;
}
oid WritePage(void)
{
static unsigned char temp;
switch (EpromWriteStep)
{
case 255:
{
break;
};
case 220: // start check status
{
LCD_Hold(); // stop Lcd
Eprom_CS = 0;
SPI1BUF = WREN; // send WREN
EpromWriteStep = 221;
break;
};
case 221: // check status step2
{
Eprom_CS = 1;
EpromWriteStep = 222;
break;
};
case 222: // check status step3
{
Eprom_CS = 0;
SPI1BUF = RDSR; // send RDSR-------------------------
EpromWriteStep = 223;
break;
};
case 223: // check status step4
{
temp = SPI1BUF; // before first cycle need clear the SPIBUF
SPI1STATbits.SPIROV = 0;
SPI1BUF = 0x00; // initiate bus cycle
EpromWriteStep = 224;
break;
};
case 224: // check status result
{
temp = SPI1BUF;
Eprom_CS = 1;
if((temp & 0x01) == 1) // internal write
{
EpromWriteStep = 220;
}
else // no busy
{
EpromWriteStep = 200;
};
break;
};
case 200: // send WREN
{
Eprom_CS = 0;
SPI1BUF = WREN;
EpromWriteStep = 199;
break;
};
case 199: // send WREN complete
{
Eprom_CS = 1;
EpromWriteStep = 197;
break;
};
case 197: // 199: send WRITE
{
Eprom_CS = 0;
SPI1BUF = WRITE;
EpromWriteStep = 196;
break;
};
case 196: // 198: send Address high
{
SPI1BUF = Eprom_AddressTable[PageWrite][0];
EpromWriteStep = 195;
break;
};
case 195: // 197: send Address low
{
SPI1BUF = Eprom_AddressTable[PageWrite][1];
EpromWriteStep = 0;
break;
};
case 100: // write complete
{
EpromWriteStep = 255;
Eprom_CS = 1;
break;
};
default: // default: send byte
{
SPI1BUF = Eprom_WriteBuf.Byte[EpromWriteStep]; // write data
EpromWriteStep++;
if( EpromWriteStep == (Eprom_AddressTable[PageWrite][2]) )
{
EpromWriteStep = 100;
};
break;
};
};
}
void ReadPage(void)
{
static unsigned char temp;
switch (EpromReadStep)
{
case 255: // no read
{
break;
};
case 220: // start check status
{
LCD_Hold(); // stop Lcd
Eprom_CS = 0;
SPI1BUF = WREN; // send WREN
EpromReadStep = 221;
break;
};
case 221: // check status step2
{
Eprom_CS = 1;
EpromReadStep = 222;
break;
};
case 222: // check status step3
{
Eprom_CS = 0;
SPI1BUF = RDSR; // send RDSR--------------
EpromReadStep = 223;
break;
};
case 223: // check status step4
{
temp = SPI1BUF; // before first cycle need clear the SPIBUF
SPI1STATbits.SPIROV = 0;
SPI1BUF = 0x00; // initiate bus cycle
EpromReadStep = 224;
break;
};
case 224: // check status result
{
temp = SPI1BUF;
Eprom_CS = 1;
if((temp & 0x01) == 1) // internal write
{
EpromReadStep = 220;
}
else // no busy
{
EpromReadStep = 200;
};
break;
};
case 200: // send Read
{
Eprom_CS = 0;
SPI1BUF = READ;
EpromReadStep = 198;
break;
};
case 198: // send Address high
{
SPI1BUF = Eprom_AddressTable[PageRead][0];
EpromReadStep = 197;
break;
};
case 197: // send Address low
{
SPI1BUF = Eprom_AddressTable[PageRead][1];
EpromReadStep = 196;
break;
};
case 196: // first read cycle
{
temp = SPI1BUF; // before first cycle need clear the SPIBUF
SPI1STATbits.SPIROV = 0;
SPI1BUF = 0x00; // initiate bus cycle
EpromReadStep = 0;
break;
};
default: // default: read byte
{
Eprom_ReadBuf.Byte[EpromReadStep] = SPI1BUF;
EpromReadStep++;
if( EpromReadStep == (Eprom_AddressTable[PageRead][2]))
{
Eprom_CS = 1;
EpromReadStep = 254; // data are ready
}
else
{
SPI1BUF = 0x00; // start another read clock cycle
}
break;
};
};
}
//----------------------------------SPI1硬件设置------------------------------------------
/*
BIT 15 14 13 12 11 10 9 8 7 6 5 4-2 1-0
NAME X X X DISSCK DISSDO MODE16 SMP CKE SSEN CKP MSTEN SPRE PPRE
SPI1CON1 1 1 1 0 0 0 0 1 0 0 1 101 10
*/
// Fcy = 40Mhz ,SPI Baud Rate = 3.3Mbps
SPI1CON1 = 0B1110000100110110;
SPI1CON2 = 0;
//---------------------------------------------------------------------------------------
使用例子:
假如你在function4()中需要读25LC160的第0页(因为我用的是25LC160,如果是25LC256你应该知道要改哪些的)
void function4(void)
{
...
PageRead = 0; //设置需要操作的页为0,见Eprom_AddressTable【】,这里面存贮了我保存数据的页地址,及数据长度,根据自己需要定义的
EpromReadStep = 220; // 改变25LC160读操作步骤数值,主程序中的“ReadPage();”将有机会执行。数据会保存在Eprom_ReadBuf【16】中,通过查询EpromReadStep是否为254,确定数据是否读完
}
main()
{
function1();
function2();
function3();
.......
ReadPage();
WritePage();
function4();
}
注意25LC系列的数据手册,因为25LC256系列的速度在4.5V~5.5V供电时最高10MHz时钟频率,2.5~4.5V时最高5MHz,所以SPI口的预分频你得注意设置,不要过快,否则也不会操作成功。
并且要保证
function1();
function2();
function3();
这些程序运行所占用的时间要大于SPI口发送一个字节的数据,因为我用这些子程序作为延时用。如果你只是测试,需要在主程序中插入延时程序,以保证每次进入ReadPage();或WritePage();时SPI口的数据操作已经完成。
或者你可以将上面我的程序改成一次性读、写完成的程序,只是在每个步骤间需要插入足够的延时。我弄了5天才搞定. |
|