📄 at25f512_drv.c~
字号:
/*C**************************************************************
/ Function: at25f512_drv
/----------------------------------------------------------------
/ Description: ATMEL FLASH (AT25F512A) Driver
/----------------------------------------------------------------
/ Note:
/----------------------------------------------------------------
/ Author: Sam Lu
/ Version: V1.00
/ Date: 2006/02/05
*****************************************************************/
/*_____________I N C L U D E____________________________________*/
#include <mega168.h>
#include <driver\spi\spi_drv.h>
#include <driver\at25f512\at25f512_drv.h>
/*_____________V A R I A B L E__________________________________*/
/*_____________E N D____________________________________________*/
/*F**************************************************************
/ Function: at25f512_initial
/----------------------------------------------------------------
/ Description: atmel at25f512a initial
/----------------------------------------------------------------
/ Parameter:
/ Return:
/----------------------------------------------------------------
/ Note:
*****************************************************************/
void at25f512_initial(void)
{
spi_state = READY_TO_SEND;
}
/*F**************************************************************
/ Function: spi_stc
/----------------------------------------------------------------
/ Description: spi stc (interrupt service routine)
/----------------------------------------------------------------
/ Parameter:
/ Return:
/----------------------------------------------------------------
/ Note:
*****************************************************************/
interrupt [SPI_STC] void spi_stc(void)
{
switch (spi_state)
{
case INSTRUCTION : /* INSTRUCTION STATE */
spi_state = ADDRESS;
byte_cnt = 1;
SPDR = (unsigned char)(address>>16); /* Address phase is 3 byte long for SPI flashes */
break;
case ADDRESS : /* ADDRESS STATE */
if (byte_cnt == NB_ADDR_BYTE) /* is the last address byte reached? */
{
spi_state = DATA; /* go to the DATA state */
byte_cnt = 0;
SPDR = *data_ptr; /* send the first byte */
}
else if (byte_cnt == 1) /* must the middle address byte be sent? */
{
byte_cnt ++;
SPDR = (unsigned char)(address>>8);
}
else
{
byte_cnt ++;
SPDR = (unsigned char)(address);
}
break;
case DATA : /* DATA STATE */
data_ptr++; /* point to the next byte (even if it was the last) */
if (byte_cnt == nb_byte - 1 ) /* is the last byte sent? */
{
AT25F512A_CS = 1; /* Disable AT25F512 Chip Select (H) */
SPIF;
//SPCR &= ~(1<<SPIE);
SPCR &= ~((1<<SPE)|(1<<SPIE));
spi_state = READY_TO_SEND; /* return to the idle state */
}
else
{
byte_cnt ++;
SPDR = *data_ptr;
}
break;
default :
{
spi_state = READY_TO_SEND;
}
}
}
/*F**************************************************************
/ Function: write_command
/----------------------------------------------------------------
/ Description: write command for at25f512 (WREN / WRDI)
/----------------------------------------------------------------
/ Parameter: op_code : WREN/WRDI instruction code
/ Return: TRANSFER_COMPLETED : the write access was completed without error
BUSY : the SPI peripheral or the serial memory is busy
/----------------------------------------------------------------
/ Note:
*****************************************************************/
unsigned char write_command(unsigned char op_code)
{
unsigned char sr; /* status register byte */
if (read_status_register(&sr) == TRANSFER_COMPLETED) /* Is the SPI interface not currently busy */
{
if (!(sr & (1<<RDY))) /* is the serial memory ready ? */
{
SPCR |= (1<<SPE); /* Enable SPI Interface */
AT25F512A_CS = 0; /* Enable AT25F512A Chip Select (L) */
spi_transfer(op_code); /* transmitt the op_code */
AT25F512A_CS = 1; /* Enable AT25F512A Chip Select (H) */
SPCR &= ~(1<<SPE); /* Disable SPI Interface */
return TRANSFER_COMPLETED;
}
else
{
return BUSY;
}
}
else
{
return BUSY;
}
}
/*F**************************************************************
/ Function: read_status_register
/----------------------------------------------------------------
/ Description: Read Status Register (RDSR)
/----------------------------------------------------------------
/ Parameter: op_code : status variable address
/ Return: TRANSFER_COMPLETED : the read access is completed without error
BUSY : the SPI peripheral is busy
/----------------------------------------------------------------
/ Note:
*****************************************************************/
unsigned char read_status_register(unsigned char *status)
{
if (spi_state == READY_TO_SEND)
{
SPCR |= (1<<SPE); /* Enable SPI Interface */
AT25F512A_CS = 0; /* Enable AT25F512A Chip Select (L) */
spi_transfer(RDSR); /* transmitt the op_code RDSR */
*status = spi_transfer(0xFF); /* get the status register value, send the value 0xFF to avoid toggle on the MOSI line */
AT25F512A_CS = 1; /* Disable AT25F512A Chip Select (H) */
SPCR &= ~(1<<SPE); /* Disable SPI Interface */
return TRANSFER_COMPLETED;
}
else
{
*status = 1;
return BUSY;
}
}
/*F**************************************************************
/ Function: write_status_register
/----------------------------------------------------------------
/ Description: Write Status Register (WRSR)
/----------------------------------------------------------------
/ Parameter: op_code : status variable address
/ Return: TRANSFER_COMPLETED : the read access is completed without error
BUSY : the SPI peripheral is busy
/----------------------------------------------------------------
/ Note:
*****************************************************************/
unsigned char write_status_register(unsigned char status_register)
{
unsigned char sr; /* read status register */
if (read_status_register(&sr) == TRANSFER_COMPLETED) /* Is the SPI interface currently not busy */
{
if (!(sr & (1<<RDY))) /* is the serial memory ready ? */
{
while(write_command(WREN) != TRANSFER_COMPLETED); /* write commande - write enable */
SPCR |= (1<<SPE);
AT25F512A_CS = 0;
spi_transfer(WRSR); /* transmit the WRSR op_code */
spi_transfer(status_register); /* transmit the status register value */
AT25F512A_CS = 1; /* Disable AT25F512A Chip Select (H) */
SPCR &= ~(1<<SPE); /* Disable SPI Interface */
return TRANSFER_COMPLETED;
}
else
{
return BUSY;
}
}
else
{
return BUSY;
}
}
/*F**************************************************************
/ Function: get_char_array
/----------------------------------------------------------------
/ Description: get data by block mode and put on buffer
/----------------------------------------------------------------
/ Parameter: address : get data address
nb_of_byte : get number of byte
destination : the result area
/ Return: TRANSFER_COMPLETED : the read access is completed without error
BUSY : the SPI peripheral is busy
OUT_OF_RANGE : address out of range (0x00FFFF)
/----------------------------------------------------------------
/ Note:
*****************************************************************/
unsigned char get_char_array(unsigned long address, unsigned long nb_of_byte, unsigned char *destination)
{
unsigned char sr; /* SPI memory status register */
unsigned char AccessStatus; /* Access status value */
unsigned int byteread_cnt; /* Read byte counter (range 1 to memory size) */
unsigned char *current_dest;
current_dest = destination; /* copy destination pointer because it needs to be incremented */
if ((address) <= TOP_ADDR) /* TOP ADDR = 0x00FFFF */
{
if (read_status_register(&sr) == TRANSFER_COMPLETED) /* Is the SPI interface currently not busy */
{
if (!(sr & (1<<RDY))) /* is the SPI memory ready ? */
{
SPCR |= (1<<SPE); /* Enable SPI Interface */
AT25F512A_CS = 0; /* Enable AT25F512A Chip Select (L) */
spi_transfer(READ); /* transmitt the op_code READ */
spi_transfer((unsigned char)(address>>16)); /* Address phase is 3 byte long for SPI flashes */
spi_transfer((unsigned char)(address>>8)); /* send MSByte address first */
spi_transfer((unsigned char)(address)); /* send LSByte address */
byteread_cnt = 0;
while (byteread_cnt < nb_of_byte)
{
*current_dest++ = spi_transfer(0xFF); /* store read byte, post increment the current_dest pointer */
byteread_cnt++;
}
AT25F512A_CS = 1; /* Disable AT25F512A Chip Select (H) */
SPCR &= ~(1<<SPE); /* Enable SPI Interface */
AccessStatus = TRANSFER_COMPLETED;
}
else
{
AccessStatus = BUSY;
}
}
else
{
AccessStatus = BUSY;
}
}
else
{
AccessStatus = OUT_OF_RANGE;
}
return AccessStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -