武林教你學PIC32(十七)SPI操作M25P16 FLASH存儲器
首先介紹下TI的M25P16,它是16Mbit(2Mbyte)的FLASH存儲器,與常用的華邦公司的W25X16,ATMEL公司的AT51DB161比較接近。最高支持50M的SPI時鐘,存儲器可以以1到256字節(jié)byte,使用頁編程操作將2M的容量分為32個塊(Block),每個塊含有256頁,每頁里有256字節(jié)寬帶,因此整個存儲器包含8192頁或者2,097,152字節(jié)。操作命令為:
我們根據這些命令,做好下面封裝函數:
//需要外接函數
extern unsigned char SPI_FLASH_SendByte(unsigned char ch);
extern unsigned char SPI_FLASH_ReadByte(unsigned char ch);
//高級函數
u32 SPI_FLASH_ReadID(void);//讀取芯片ID正確發(fā)回0X202015
u8 SPI_FLASH_ByteRead(u32 ReadAddr);//讀一個數據
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);//頁寫
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
void SPI_FLASH_SectorErase(u32 SectorAddr);//扇區(qū)擦除
void SPI_FLASH_BulkErase(void);//全部擦除
void SPI_Flash_PowerDown(void); //進入掉電模式
void SPI_Flash_WAKEUP(void);//喚醒
//底層函數
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WriteDisable(void);
void SPI_FLASH_WaitForWriteEnd(void);
我們申請到的FLASH模塊與SPI2連接,如圖所示:
主函數里面實現(xiàn)這樣的測試功能:首先測試芯片的型號,看是不是TI M25P16芯片,然后擦除扇區(qū),再寫入要測試的數據,最后讀回來看是不是這些內容。
主函數代碼:
#include "usart2.h"
#include "spi2.h"
#include "m25p16.h"
#include "led.h"
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
#defineFLASH_WriteAddress0x00100
#defineFLASH_ReadAddressFLASH_WriteAddress
#defineFLASH_SectorToEraseFLASH_WriteAddress
#definesFLASH_ID0x202015
#defineBufferSize (countof(Tx_Buffer)-1)
/* Private macro -------------------------------------------------------------*/
#define countof(a) (sizeof(a) / sizeof(*(a)))
/* Private variables ---------------------------------------------------------*/
uint8_t Tx_Buffer[] = "nr歡迎訪問EEFOUCS MIPS社區(qū)http://mips.eefocus.com/bbs/index_list.htmlrn SPI Flash Test Example: communication with an TI M25P16 SPI FLASHrn";
uint8_t Index, Rx_Buffer[BufferSize];
volatile TestStatus TransferStatus1 = FAILED, TransferStatus2 = PASSED;
uint32_t FlashID = 0;
/* Private function prototypes -----------------------------------------------*/
TestStatus Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength);
int main(void)
{
usart2_init(9600);
init_spi2();
LED_INIT();
/* Get SPI Flash Device ID */
FlashID = SPI_FLASH_ReadID();
printf("rn Device ID is 0x%X rn", FlashID);
if (FlashID == sFLASH_ID)
{
/* Turn on LED1 */
LED1_ON();//表明檢測到FLASH芯片
printf("rn ST M25P16 Identitied!rn");
/* Perform a write in the Flash followed by a read of the written data */
/* Erase SPI FLASH Sector to write on */
SPI_FLASH_SectorErase(FLASH_SectorToErase);
printf("Tx_Buffer:%s", Tx_Buffer);
/* Write Tx_Buffer data to SPI FLASH memory */
SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize);
/* Read data from SPI FLASH memory */
SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);
printf("Rx_Buffer:%s", Rx_Buffer);
/* Check the corectness of written dada */
TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);
/* Perform an erase in the Flash followed by a read of the written data */
/* Erase SPI FLASH Sector to write on */
SPI_FLASH_SectorErase(FLASH_SectorToErase);
/* Read data from SPI FLASH memory */
SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);
/* Check the corectness of erasing operation dada */
for (Index = 0; Index < BufferSize; Index++)
{
if (Rx_Buffer[Index] != 0xFF)//因為擦除后都為0XFF
{
TransferStatus2 = FAILED;
break;
}
}
/* TransferStatus2 = PASSED, if the specified sector part is erased */
/* TransferStatus2 = FAILED, if the specified sector part is not well erased */
if((PASSED == TransferStatus1) && (PASSED == TransferStatus2))
{
/* OK: Turn on LED2 */
LED2_ON();
printf("rn M25P16 Test Suceed!nr");
}
else
{
LED4_ON();
printf("rn -->Failed: M25P16 Test Failed!nr");
}
}
else
{
/* Error: Turn on LED3 */
LED3_ON();
printf("rn M25P16 not detected!nr");
}
while(1);
}
TestStatus Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength)
{
while(BufferLength--)
{
if(*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}