#include "spi.h"
#include "prototype.h"
#define CE_High() CE = 1; /* set CE high */
#define CE_Low() CE = 0; /* clear CE low */
void EWSR();
void WREN();
void WRSR(uchar byte);
unsigned char Read_Status_Register();
void WRDI();
/*
*Function: SPIInit
*Description: SPI初始化
*Author: Chevkio
*Date: 2010/2/8
*/
void SPIInit(void)
{
//SPI interrupts disable 0
//SPI enable 1
//MSB first in data transmission 0
//Selects Master mode 1
//SCK is low when idle (Active High) 1
//Shift triggered on the leading edge of the clock 1
//SCK = fOSC divided by 16 0, 1
SPCR = 0x5D;
CE_High();
//Enable-Write-Status-Register
EWSR();
//禁止写保护
WRSR(0);
}
/*
*Function: MasterIO
*Description: 利用89LV51单片机自带的SPI端口写入/输出;
主从SPI各自8位寄存器组成16位循环寄存器
*Parameter: HW_SPI_out, 要通过SPI端口输出的数值
*Return: 返回SPI端口接收到的数值
*Author: Chevkio
*Date: 2010/2/8
*/
unsigned char MasterIO(unsigned char HW_SPI_out)
{
unsigned char temp;
//发送数据, 同时生成CLOCK脉冲
SPDR = HW_SPI_out;
//等待发送完毕
do
{
temp = SPSR & SPIF;
}while(temp!= SPIF);
//清除SPIF
SPSR = SPSR & ~SPIF;
return SPDR;
}
/************************************************************************/
/* PROCEDURE: EWSR */
/* */
/* This procedure Enables Write Status Register. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void EWSR()
{
CE_Low(); /* enable device */
MasterIO(0x50); /* enable writing to the status register */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: WRSR */
/* */
/* This procedure writes a byte to the Status Register. */
/* */
/* Input: */
/* byte */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WRSR(uchar byte)
{
CE_Low(); /* enable device */
MasterIO(0x01); /* select write to status register */
MasterIO(byte); /* data that will change the status of BPx
or BPL (only bits 2,3,4,5,7 can be written) */
CE_High(); /* disable the device */
}
/************************************************************************/
/* PROCEDURE: WREN */
/* */
/* This procedure enables the Write Enable Latch. It can also be used */
/* to Enables Write Status Register. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WREN()
{
CE_Low(); /* enable device */
MasterIO(0x06); /* send WREN command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: WRDI */
/* */
/* This procedure disables the Write Enable Latch. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WRDI()
{
CE_Low(); /* enable device */
MasterIO(0x04); /* send WRDI command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Read */
/* */
/* This procedure reads one address of the device. It will return the */
/* byte read in variable byte. */
/* */
/* */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 1FFFFFH */
/* */
/* */
/* Returns: */
/* byte */
/* */
/************************************************************************/
unsigned char ByteRead(unsigned long Dst)
{
unsigned char byte = 0;
CE_Low(); /* enable device */
MasterIO(0x03); /* read command */
MasterIO(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
MasterIO(((Dst & 0xFFFF) >> 8));
MasterIO(Dst & 0xFF);
byte = MasterIO(0);
CE_High(); /* disable device */
return byte; /* return one byte read */
}
/*
*Function: StreamReadStart
*Description: 连续流读取开始
*parameter: 要读取得起始地址
*Note: StreamReadStart必须和StreamReadEnd配套使用
*Author: Chevkio
*Date: 2010/2/8
*/
void StreamReadStart(unsigned long Dst)
{
CE_Low(); /* enable device */
MasterIO(0x03); /* read command */
MasterIO(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
MasterIO(((Dst & 0xFFFF) >> 8));
MasterIO(Dst & 0xFF);
}
/*
*Function: StreamRead
*Description: 流读取,每调用一次返回一个字节, 且地址自动加一
*Return: 当前读取的地址内容
*Author: Chevkio
*Date: 2010/2/8
*/
unsigned char StreamRead()
{
return MasterIO(0);
}
/*
*Function: StreamReadEnd
*Description: 流读取结束
*Note: StreamReadStart必须和StreamReadEnd配套使用
*Author: Chevkio
*Date: 2010/2/8
*/
void StreamReadEnd()
{
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Byte_Program */
/* */
/* This procedure programs one address of the device. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 1FFFFFH */
/* byte: byte to be programmed */
/* */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Byte_Program(unsigned long Dst, unsigned char byte)
{
WREN(); //Write-Enable
CE_Low(); /* enable device */
MasterIO(0x02); /* send Byte Program command */
MasterIO(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
MasterIO(((Dst & 0xFFFF) >> 8));
MasterIO(Dst & 0xFF);
MasterIO(byte); /* send byte to be programmed */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: StreamWriteStart */
/* */
/* This procedure programs consecutive addresses of 2 bytes of data into*/
/* the device: 1st data byte will be programmed into the initial */
/* address [A23-A1] and with A0 = 0. The 2nd data byte will be be */
/* programmed into initial address [A23-A1] and with A0 = 1. This */
/* is used to to start the AAI process. It should be followed by */
/* Auto_Add_IncB. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* */
/* Note: Only RDSR command can be executed once in AAI mode with SO */
/* disable to output RY/BY# status. Use WRDI to exit AAI mode */
/* unless AAI is programming the last address or last address of */
/* unprotected block, which automatically exits AAI mode. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 1FFFFFH */
/* byte1: 1st byte to be programmed */
/* byte1: 2nd byte to be programmed */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void StreamWriteStart(unsigned long Dst, unsigned char byte1, unsigned char byte2)
{
//如果Flash忙, 则等待...
while(Read_Status_Register() & 1 == 1)
{
NOP();
NOP();
}
WREN(); //Write-Enable
CE_Low(); /* enable device */
MasterIO(0xAD); /* send AAI command */
MasterIO(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
MasterIO(((Dst & 0xFFFF) >> 8));
MasterIO(Dst & 0xFF);