废话少说,直接上代码:
DataFlash_reg.h:
/*
Using SPIO simulator
PB8 -- spi cs
PA9 -- spi clock
PA10 -- spi MOSI
PB7 -- spi MISO
PA8 -- hold
PC4 -- Write protect
*/
#define SPI_CS_Port gpioPortB
#define SPI_CS_Pin 8
#define SPI_CS (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_CS_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_CS_Pin * 4))))
#define SPI_CLK_Port gpioPortA
#define SPI_CLK_Pin 9
#define SPI_CLK (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_CLK_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_CLK_Pin * 4))))
#define SPI_MOSI_Port gpioPortA
#define SPI_MOSI_Pin 10
#define SPI_MOSI (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_MOSI_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_MOSI_Pin * 4))))
#define SPI_MISO_Port gpioPortB
#define SPI_MISO_Pin 7
#define SPI_MISO (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_MISO_Port].DIN) - PER_MEM_BASE) * 32) + (SPI_MISO_Pin * 4))))
unsigned char DataFlash_Write_Byte(unsigned char Data);
DataFlash_cmd.h:
#ifndef __DATAFLASH_CMD_H__
#define __DATAFLASH_CMD_H__
#define W25X_BUSY 0
#define W25X_NotBUSY 1
#define Dummy_Byte1 0xA5
/*********************************************
- W25X16的操作指令表,MCU通过向W25X16
发送以下指令就可以对W25X16进行以下的操作
*********************************************/
#define W25X_WriteEnable 0x06 //Write Enable
#define W25X_WriteEnableVSR 0x50 //Write Enable for Volatile Status Register
#define W25X_WriteDisable 0x04 //Write Disable
#define W25X_ReadStatusReg1 0x05 //读状态寄存器1:S7~S0
#define W25X_ReadStatusReg2 0x35 //读状态寄存器2:S15~S8
#define W25X_WriteStatusReg 0x01 //写读状态寄存器:BYTE1:S7~S0 BYTE2:S15~S8
#define W25X_PageProgram 0x02 //单页编程:BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0 BYTE4:D7~D0
#define W25X_SectorErase 0x20 //扇区擦除:4K BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0
#define W25X_BlockErase32K 0x52 //块擦除:32K BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0
#define W25X_BlockErase64K 0xD8 //块擦除:64K BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0
#define W25X_ChipErase 0xC7 //芯片擦除
#define W25X_EraseSuspend 0x75 //暂停擦除
#define W25X_EraseResume 0x7A //恢复擦除
#define W25X_PowerDown 0xB9 //掉电
#define W25X_ContinuousReadMode 0xFF //连续读模式
#define W25X_ReadData 0x03 //读数据:BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0 BYTE4:D7~D0
#define W25X_FastReadData 0x0B //快速读取:BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0 BYTE4:dummy BYTE5:D7~D0
#define W25X_FastReadDual 0x3B //快速双读取:BYTE1:A23~A16 BYTE2:A15~A8 BYTE3:A7~A0 BYTE4:dummy BYTE5:D7~D0
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
#endif
DataFlash_reg.c:
#include <stdint.h>
#include <stdbool.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "DataFlash_reg.h"
#include "DataFlash_cmd.h"
/*
Using SPIO simulator
PB8 -- spi cs
PA9 -- spi clock
PA10 -- spi MOSI
PB7 -- spi MISO
PA8 -- hold
PC4 -- Write protect
*/
void DataFlash_Initial_IO(void)
{
GPIO_PinModeSet(gpioPortB,8,gpioModePushPull,1);
GPIO_PinModeSet(gpioPortA,9,gpioModePushPull,1);
GPIO_PinModeSet(gpioPortA,10,gpioModePushPull,1);
GPIO_PinModeSet(gpioPortB,7,gpioModeInputPull,1);
GPIO_PinModeSet(gpioPortA,8,gpioModePushPull,1);
GPIO_PinModeSet(gpioPortC,4,gpioModePushPull,1);
}
//*************** Write enable **************************** OK
void DataFlash_WriteEnable (void)
{
SPI_CS = 0;
__NOP();
__NOP();
DataFlash_Write_Byte(W25X_WriteEnable);
__NOP();
__NOP();
SPI_CS = 1;
}
//*************** Write disable **************************** OK
void DataFlash_WriteDisable (void)
{
SPI_CS = 0;
__NOP();
__NOP();
DataFlash_Write_Byte(W25X_WriteDisable);
__NOP();
__NOP();
SPI_CS = 1;
}
//***************判BUSY********************************
unsigned char DataFlash_SPI_BUSY_OrNot (void) //在读和写之前得先判断FLASH是否BUSY
{ //BUSY的原因是擦除,或是连续读写
unsigned char k; //如果没有以上方式,不必判定可以写读
SPI_CS = 0;
__NOP();
__NOP();
DataFlash_Write_Byte(W25X_ReadStatusReg1);
k = DataFlash_Write_Byte(Dummy_Byte1);
__NOP();
__NOP();
SPI_CS = 1;
if(k&0x01)return (W25X_BUSY);
else return (W25X_NotBUSY);
}
void SPI_Flash_Read(uint32_t ReadAddr, uint32_t numBytes,void *data)
{
uint8_t *rxBuffer = (uint8_t *) data;
/* Enable chip select */
SPI_CS = 0;
__NOP();
__NOP();
DataFlash_Write_Byte(W25X_ReadData);
DataFlash_Write_Byte(ReadAddr >> 16);
DataFlash_Write_Byte(ReadAddr >> 8);
DataFlash_Write_Byte(ReadAddr);
while (numBytes--)
{
*rxBuffer = DataFlash_Write_Byte(Dummy_Byte1); //Read one byte
rxBuffer++;
}
/* Disable chip select */
__NOP();
__NOP();
SPI_CS = 1;
}
/*******************************************************************************
* Function Name : SPI_FLASH_ReadID
* Description : Reads FLASH identification.
* Input : None
* Output : None
* Return : FLASH identification
*******************************************************************************/
unsigned long SPI_Flash_ReadID(void)
{
unsigned int Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/* Enable chip select */
SPI_CS = 0;
__NOP();
__NOP();
/* Send "RDID " instruction */
DataFlash_Write_Byte(0x9F);
/* Read a byte from the FLASH */
Temp0 = DataFlash_Write_Byte(Dummy_Byte1);
/* Read a byte from the FLASH */
Temp1 = DataFlash_Write_Byte(Dummy_Byte1);
/* Read a byte from the FLASH */
Temp2 = DataFlash_Write_Byte(Dummy_Byte1);
/* Disable chip select */
__NOP();
__NOP();
SPI_CS = 1;
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
////每次写一页面 地址低8位应为0
//void SPI_Flash_Page_Write(uint32_t pageNum, unsigned char* data)
//{
// uint8_t *rxBuffer = data;
// while(1)
// {
// if(SPI_BUSY_OrNot() == W25X_NotBUSY) break;
// }
//
// WriteEnable(); //写允许
//
// /* Enable chip select */
// GPIO_PinOutClear(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//
// SPI_FlashWrite(W25X_PageProgram);
//
// unsigned int WriteAddr = pageNum<<8;
//
// SPI_FlashWrite((WriteAddr >> 16));
// SPI_FlashWrite((uint32_t)(WriteAddr >> 8));
// SPI_FlashWrite((uint32_t) WriteAddr);
//
// for(int i=0;i<SPI_FLASH_PAGE_SIZE;i++)
// {
// SPI_FlashWrite(*rxBuffer);
// rxBuffer++;
// }
// /* Disable chip select */
// GPIO_PinOutSet(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//
// WriteDisable();//写禁止
//}
//
////**************片擦除****************** OK
//void SPI_EraseDevice(void)
//{
// while(1)
// {
// if(SPI_BUSY_OrNot() == W25X_NotBUSY) break;
// }
// WriteEnable(); //写允许
// GPIO_PinOutClear(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
// SPI_FlashWrite(W25X_ChipErase);
// GPIO_PinOutSet(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//}
unsigned char DataFlash_Write_Byte(unsigned char Data)
{
unsigned char Out = 0;
unsigned char i = 0;
SPI_CLK = 0;
for(i = 0; i < 8; i++)
{
if(Data & 0x80)SPI_MOSI = 1;
else SPI_MOSI = 0;
Data = Data << 1;
__NOP();
__NOP();
__NOP();
SPI_CLK = 1;
if(SPI_MISO)Out |= 0x80 >> i;
__NOP();
__NOP();
__NOP();
SPI_CLK = 0;
}
SPI_CLK = 0;
return Out;
}