【CW32L052 Review】 spi flash read and write test
[Copy link]
This post was last edited by TL-LED on 2023-7-22 06:39
This article tests the SPI flash read and write test based on the board's routines, and the serial port prints the test content.
1. Hardware Circuit
1.1、SPI FLASH on the board
The chip used is W25Q64, connected to the PC00~PC03 pins of the MCU.
1.2、PC00~PC03 pin mapping
1.3. w25q64 instructions
2. Procedure
2.1, fun_flash.c
#include "main.h"
#define BufferSize (ARRAY_SZ(TxBuffer) - 1)
#define FLASH_WriteAddress 0x00000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorToEraseAddress FLASH_WriteAddress
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
//SPI TEST
uint8_t TxBuffer[] = "cw32l052 board write and read spi flash test!";
uint8_t RxBuffer[BufferSize];
uint8_t DeviceID = 0;
uint16_t ManufactDeviceID = 0;
int32_t JedecID = 0;
uint8_t UniqueID[8];
uint8_t status1;
uint8_t status2;
volatile TestStatus TransferStatus = FAILED;
void init_spi_flash(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/************************GPIO Configuration***********************/
RCC_AHBPeriphClk_Enable(FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_CS_GPIO_CLK, ENABLE);
FLASH_SPI_APBClkENx(FLASH_SPI_CLK, ENABLE);
//SPI SCK MOSI MISO ′ó
FLASH_SPI_AF_SCK;
FLASH_SPI_AF_MISO;
FLASH_SPI_AF_MOSI;
//CS
GPIO_InitStructure.Pins = FLASH_SPI_CS_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
//SCK
GPIO_InitStructure.Pins = FLASH_SPI_SCK_GPIO_PIN;
GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
//MOSI
GPIO_InitStructure.Pins = FLASH_SPI_MOSI_GPIO_PIN;
GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
//MISO
GPIO_InitStructure.Pins = FLASH_SPI_MISO_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
//à-CS
FLASH_SPI_CS_HIGH();
/************************SPI Configuration***********************/
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // è1¤
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // ÷ú£ê
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // êyY3¤èa8bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // ê±óDμa
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // μút±2éù
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // DoóéSSI′÷
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // 2¨ìêaPCLKμ8·μ
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // ×óDD§ MSB ê·¢ú°
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; // μíùSPI
SPI_Init(FLASH_SPIx, &SPI_InitStructure);
SPI_Cmd(FLASH_SPIx, ENABLE);
}
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] í¨1ySPIáèò×úμêyY
*
* [url=home.php?mod=space&uid=784970]@return[/url] uint8_t :óêμμêyY
*/
uint8_t SPI_FLASH_ReadByte(void)
{
return (SPI_FLASH_SendByte(FLASH_DUMMY_BYTE));
}
/**
* @brief í¨1ySPI·¢íò×úμêyY£2¢·μóêμμò×úêyY
*
* @param byte :′y·¢íμêyY
* @return uint8_t :óêμμêyY
*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_TXE) == RESET);
SPI_SendData(FLASH_SPIx, byte);
while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_RXNE) == RESET);
return SPI_ReceiveData(FLASH_SPIx);
}
/**
* @brief í¨1ySPI·¢íá×úμêyY£2¢·μóêμμá×úêyY
*
* @param HalfWord :′y·¢íμêyY
* @return uint16_t :óêμμêyY
*/
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{
while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_TXE) == RESET);
SPI_SendData(FLASH_SPIx, HalfWord);
while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_RXNE) == RESET);
return SPI_ReceiveData(FLASH_SPIx);
}
/**
* @brief òFLASH·¢í D′ê1ü á
*
*/
void SPI_FLASH_WriteEnable(void)
{
FLASH_SPI_CS_LOW();
//·¢í D′ê1ü á
SPI_FLASH_SendByte(FLASH_CMD_WriteEnable);
FLASH_SPI_CS_HIGH();
}
/**
* @brief μè′y2á3yò±à3ìíê3é
*
*/
void SPI_FLASH_WaitForWriteEnd(void)
{
uint8_t flashstatus = 0;
FLASH_SPI_CS_LOW();
// ·¢í á×′ì′÷1 á
SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg1);
do
{
//áFLASH×′ì′÷
flashstatus = SPI_FLASH_ReadByte();
}while((flashstatus & FLASH_WIP_FLAG) == SET); //yúD′è£ìD-·
FLASH_SPI_CS_HIGH();
}
/**
* @brief á×′ì′÷1
*
* @return uint8_t
*/
uint8_t SPI_FLASH_ReadStatusReg1(void)
{
uint8_t flashstatus = 0;
FLASH_SPI_CS_LOW();
// ·¢í á×′ì′÷1 á
SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg1);
flashstatus = SPI_FLASH_ReadByte();
FLASH_SPI_CS_HIGH();
return flashstatus;
}
/**
* @brief á×′ì′÷2
*
* @return uint8_t
*/
uint8_t SPI_FLASH_ReadStatusReg2(void)
{
uint8_t flashstatus = 0;
FLASH_SPI_CS_LOW();
// ·¢í á×′ì′÷2 á
SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg2);
flashstatus = SPI_FLASH_ReadByte();
FLASH_SPI_CS_HIGH();
return flashstatus;
}
/**
* @brief D′×′ì′÷1
*
* @param status
*/
void SPI_FLASH_WriteStatusReg1(uint8_t status)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
FLASH_SPI_CS_LOW();
// ·¢í D′×′ì′÷1 á
SPI_FLASH_SendByte(FLASH_CMD_WriteStatusReg1);
//·¢í ×′ì′÷1 éè¨μ
SPI_FLASH_SendByte(status);
FLASH_SPI_CS_HIGH();
//μè′yD′èíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief D′×′ì′÷2
*
* @param status
*/
void SPI_FLASH_WriteStatusReg2(uint8_t status)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
FLASH_SPI_CS_LOW();
// ·¢í D′×′ì′÷2 á
SPI_FLASH_SendByte(FLASH_CMD_WriteStatusReg2);
//·¢í ×′ì′÷2 éè¨μ
SPI_FLASH_SendByte(status);
FLASH_SPI_CS_HIGH();
//μè′yD′èíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief éè2á3y 4KB
*
* @param SectorAddr :′y2á3yμéèμ·
*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
//μè′yD′èíê3é
// SPI_FLASH_WaitForWriteEnd();
FLASH_SPI_CS_LOW();
//·¢í éè2á3y á
SPI_FLASH_SendByte(FLASH_CMD_SectorErase);
//·¢í ′y2á3yéèμ·
SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
SPI_FLASH_SendByte(SectorAddr & 0xFF);
FLASH_SPI_CS_HIGH();
//μè′y2á3yíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief é2á3y 64KB
*
* @param BlockAddr :′y2á3yμéμ·
*/
void SPI_FLASH_BlockErase(uint32_t BlockAddr)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
//μè′yD′èíê3é
// SPI_FLASH_WaitForWriteEnd();
FLASH_SPI_CS_LOW();
//·¢í é2á3y á
SPI_FLASH_SendByte(FLASH_CMD_BlockErase);
//·¢í ′y2á3yéμ·
SPI_FLASH_SendByte((BlockAddr & 0xFF0000) >> 16);
SPI_FLASH_SendByte((BlockAddr & 0xFF00) >> 8);
SPI_FLASH_SendByte(BlockAddr & 0xFF);
FLASH_SPI_CS_HIGH();
//μè′y2á3yíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief 2á3y
*
*/
void SPI_FLASH_ChipErase(void)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
FLASH_SPI_CS_LOW();
//·¢í 2á3y á
SPI_FLASH_SendByte(FLASH_CMD_ChipErase);
FLASH_SPI_CS_HIGH();
//μè′y2á3yíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief ò3D′èêyY
*
* @param pBuffer :′yD′èêyYμ
* @param WriteAddr :D′èμ·
* @param NumByteToWrite :D′èêyY3¤è
* @note
* -Dèòaè2á3y
* -NumByteToWrite <= SPI_FLASH_PerWritePageSize
*/
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
//·¢í D′ê1ü á
SPI_FLASH_WriteEnable();
FLASH_SPI_CS_LOW();
//·¢í ò3D′è á
SPI_FLASH_SendByte(FLASH_CMD_PageProgram);
//·¢í D′μ·
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
SPI_FLASH_SendByte(WriteAddr & 0xFF);
//D′èêyY
while(NumByteToWrite--)
{
SPI_FLASH_SendByte(*pBuffer);
pBuffer++;
}
FLASH_SPI_CS_HIGH();
//μè′yD′èíê3é
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief D′è2¨áêyY
*
* @param pBuffer :′yD′èêyYμ
* @param WriteAddr :D′èμ·
* @param NumByteToWrite :D′èêyY3¤è
* @note
* -Dèòaè2á3y
*/
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
Addr = WriteAddr % SPI_FLASH_PageSize;
count = SPI_FLASH_PageSize - Addr;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
if(Addr == 0) /* WriteAddr o°′ò3 */
{
if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
else /* NumByteToWrite >= SPI_FLASH_PageSize */
{
while(NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
if(NumOfSingle != 0)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
else /* WriteAddr ó SPI_FLASH_PageSize 2 */
{
if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
if(NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
{
temp = NumOfSingle - count;
//D′íêμ±°ò3
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
//D′ê£óàêyY
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
else
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /* NumByteToWrite >= SPI_FLASH_PageSize */
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
//èD′íêμ±°ò3£òoóμ·
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
//WriteAddr o°′ò3
while(NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
if(NumOfSingle != 0)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
/**
* @brief áêyY
*
* @param pBuffer :′′¢á3êyYμ
* @param ReadAddr :áèμ·
* @param NumByteToRead :áèêyY3¤è
*/
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
FLASH_SPI_CS_LOW();
//·¢í áêyY á
SPI_FLASH_SendByte(FLASH_CMD_ReadData);
//·¢í áμ·
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
SPI_FLASH_SendByte(ReadAddr & 0xFF);
//áêyY
while(NumByteToRead--)
{
*pBuffer = SPI_FLASH_ReadByte();
pBuffer++;
}
FLASH_SPI_CS_HIGH();
}
/**
* @brief ˉáèêyY×úDòáD
*
* @param ReadAddr :áèμ·
*/
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{
FLASH_SPI_CS_LOW();
//·¢í áêyY á
SPI_FLASH_SendByte(FLASH_CMD_ReadData);
//·¢í áμ·
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
SPI_FLASH_SendByte(ReadAddr & 0xFF);
}
/**
* @brief áèDevice ID
*
* @return uint8_t :Device ID
*/
uint8_t SPI_FLASH_DeviceID(void)
{
uint8_t Temp = 0;
FLASH_SPI_CS_LOW();
//·¢í áDevice ID á
SPI_FLASH_SendByte(FLASH_CMD_DeviceID);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
//áêyY
Temp = SPI_FLASH_ReadByte();
FLASH_SPI_CS_HIGH();
return Temp;
}
/**
* @brief áèManufacturer / Device ID
*
* @return uint16_t :Manufacturer / Device ID
*/
uint16_t SPI_FLASH_ManufactDeviceID(void)
{
uint16_t Temp = 0, Temp0 = 0, Temp1 = 0;
FLASH_SPI_CS_LOW();
//·¢í áManufacturer / Device ID á
SPI_FLASH_SendByte(FLASH_CMD_ManufactDeviceID);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
//áêyY
Temp0 = SPI_FLASH_ReadByte();
Temp1 = SPI_FLASH_ReadByte();
FLASH_SPI_CS_HIGH();
Temp = (Temp0 << 8) | Temp1;
return Temp;
}
/**
* @brief áèJEDEC ID
*
* @return uint32_t :JEDEC ID
*/
uint32_t SPI_FLASH_JedecID(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
FLASH_SPI_CS_LOW();
//·¢í áJEDEC ID á
SPI_FLASH_SendByte(FLASH_CMD_JedecID);
//áêyY
Temp0 = SPI_FLASH_ReadByte();
Temp1 = SPI_FLASH_ReadByte();
Temp2 = SPI_FLASH_ReadByte();
FLASH_SPI_CS_HIGH();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
/**
* @brief áèUnique ID (64bit)
*
* @param pBuffer :′·UIDμBuffer
*/
void SPI_FLASH_UniqueID(uint8_t* pBuffer)
{
uint8_t NumByteToRead = 8;
FLASH_SPI_CS_LOW();
//·¢í áUnique ID á
SPI_FLASH_SendByte(FLASH_CMD_UniqueID);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
//áêyY
while(NumByteToRead--)
{
*pBuffer = SPI_FLASH_ReadByte();
pBuffer++;
}
FLASH_SPI_CS_HIGH();
}
/**
* @brief èμμ£ê
*
*/
void SPI_FLASH_PowerDown(void)
{
FLASH_SPI_CS_LOW();
//·¢í μμ á
SPI_FLASH_SendByte(FLASH_CMD_PowerDown);
FLASH_SPI_CS_HIGH();
}
/**
* @brief D
*
*/
void SPI_FLASH_WAKEUP(void)
{
FLASH_SPI_CS_LOW();
//·¢í Release Power-down or High Performance Mode á
SPI_FLASH_SendByte(FLASH_CMD_ReleasePowerDown);
FLASH_SPI_CS_HIGH();
}
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while(BufferLength--)
{
if(*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
void SPI_FLASH_Test(void)
{
printf("SPI_FLASH Test Start\r\n");
DeviceID = SPI_FLASH_DeviceID();
ManufactDeviceID = SPI_FLASH_ManufactDeviceID();
JedecID = SPI_FLASH_JedecID();
SPI_FLASH_UniqueID(UniqueID);
printf("\r\nDeviceID = 0x%X\r\nManufactDeviceID = 0x%X\r\nJedecID = 0x%X\r\n", DeviceID, ManufactDeviceID, JedecID);
// printf("\r\nUniqueID = 0x ");
// for(uint8_t i = 0;i<8;i++)
// {
// printf("%X ", UniqueID[i]);
// }
/* á×′ì′÷ */
status1 = SPI_FLASH_ReadStatusReg1();
status2 = SPI_FLASH_ReadStatusReg2();
// printf("\r\nstatus1 = 0x%X\r\nstatus2 = 0x%X\r\n", status1, status2);
// /* D′×′ì′÷ */
// SPI_FLASH_WriteStatusReg1(0x00);
// SPI_FLASH_WriteStatusReg2(0x00);
// status1 = SPI_FLASH_ReadStatusReg1();
// status2 = SPI_FLASH_ReadStatusReg2();
// printf("\r\nstatus1 = 0x%X\r\nstatus2 = 0x%X\r\n", status1, status2);
/* Check JEDEC ID */
if(JedecID == sJedecID)
{
//2á3yéè 4KB
SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);
//D′êyY
SPI_FLASH_BufferWrite(TxBuffer, FLASH_WriteAddress, BufferSize);
printf("D′èμêyYa£o%s\r\n", TxBuffer);
//áêyY
SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
printf("á3μêyYa£o%s\r\n", RxBuffer);
//ì2éD′èμêyYóá3μêyYê·ò
TransferStatus = Buffercmp(TxBuffer, RxBuffer, BufferSize);
if(TransferStatus == PASSED)
{
printf("SPI_FLASH Test OK\r\n");
}
else
{
printf("\r\nSPI_FLASH Test Error:Read and Write Data is not same\r\n");
while(1);
}
//2á3yéè 4KB
SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);
//áêyY
SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
for(uint8_t j = 0; j < BufferSize; j++)
{
if(RxBuffer[j] != 0xFF)
{
printf("\r\nSPI_FLASH Test Error:FLASH Erase fail\r\n");
while(1);
}
}
}
else// (FlashID £= sFLASH_ID)
{
printf("\r\nSPI_FLASH Test Error:Read JEDEC ID Error\r\n");
while(1);
}
}
2.2, fun_flash.h
#ifndef __FUN_FLASH_H
#define __FUN_FLASH_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "cw32l052.h"
//#include "cw32l052_rcc.h"
//#include "cw32l052_gpio.h"
//#include "cw32l052_spi.h"
/******************************************************************************
* type definitions ('typedef')
******************************************************************************/
/******************************************************************************
* pre-processor symbols/macros ('#define')
******************************************************************************/
//Manufacturer and Device Identification (W25Q64)
#define sDeviceID 0x16
#define sManufactDeviceID 0xEF16
#define sJedecID 0x5E4017
/* SPI FLASH supported commands */
#define FLASH_CMD_WriteEnable 0x06
#define FLASH_CMD_WriteDisable 0x04
#define FLASH_CMD_ReadStatusReg1 0x05
#define FLASH_CMD_ReadStatusReg2 0x35
#define FLASH_CMD_WriteStatusReg1 0x01
#define FLASH_CMD_WriteStatusReg2 0x31
#define FLASH_CMD_ReadData 0x03
#define FLASH_CMD_FastReadData 0x0B
#define FLASH_CMD_FastReadDual 0x3B
#define FLASH_CMD_PageProgram 0x02
#define FLASH_CMD_SectorErase 0x20
#define FLASH_CMD_BlockErase 0xD8
#define FLASH_CMD_ChipErase 0xC7
#define FLASH_CMD_PowerDown 0xB9
#define FLASH_CMD_ReleasePowerDown 0xAB
#define FLASH_CMD_DeviceID 0xAB
#define FLASH_CMD_ManufactDeviceID 0x90
#define FLASH_CMD_JedecID 0x9F
#define FLASH_CMD_UniqueID 0x4B
/* Write In Progress (WIP) flag */
#define FLASH_WIP_FLAG 0x01
#define FLASH_DUMMY_BYTE 0xFF
#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256
//SPIx
#define FLASH_SPIx CW_SPI1
#define FLASH_SPI_CLK RCC_APB2_PERIPH_SPI1
#define FLASH_SPI_APBClkENx RCC_APBPeriphClk_Enable2
//SPIx GPIO
#define FLASH_SPI_SCK_GPIO_CLK RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_SCK_GPIO_PORT CW_GPIOC
#define FLASH_SPI_SCK_GPIO_PIN GPIO_PIN_1
#define FLASH_SPI_MISO_GPIO_CLK RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_MISO_GPIO_PORT CW_GPIOC
#define FLASH_SPI_MISO_GPIO_PIN GPIO_PIN_2
#define FLASH_SPI_MOSI_GPIO_CLK RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_MOSI_GPIO_PORT CW_GPIOC
#define FLASH_SPI_MOSI_GPIO_PIN GPIO_PIN_3
#define FLASH_SPI_CS_GPIO_CLK RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_CS_GPIO_PORT CW_GPIOC
#define FLASH_SPI_CS_GPIO_PIN GPIO_PIN_0
//GPIO AF
#define FLASH_SPI_AF_SCK PC01_AFx_SPI1SCK()
#define FLASH_SPI_AF_MISO PC02_AFx_SPI1MISO()
#define FLASH_SPI_AF_MOSI PC03_AFx_SPI1MOSI()
//CS LOW or HIGH
#define FLASH_SPI_CS_LOW() PC00_SETLOW()
#define FLASH_SPI_CS_HIGH() PC00_SETHIGH()
/******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/******************************************************************************
* Global function prototypes
******************************************************************************/
/* SPI FLASH 3êˉ*/
void init_spi_flash(void);
/* Low layer functions */
uint8_t SPI_FLASH_ReadByte(void);
uint8_t SPI_FLASH_SendByte(uint8_t byte);
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WaitForWriteEnd(void);
/* áD′×′ì′÷ */
uint8_t SPI_FLASH_ReadStatusReg1(void);
uint8_t SPI_FLASH_ReadStatusReg2(void);
void SPI_FLASH_WriteStatusReg1(uint8_t status);
void SPI_FLASH_WriteStatusReg2(uint8_t status);
/* High layer functions */
void SPI_FLASH_SectorErase(uint32_t SectorAddr);
void SPI_FLASH_BlockErase(uint32_t BlockAddr);
void SPI_FLASH_ChipErase(void);
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr);
uint8_t SPI_FLASH_DeviceID(void);
uint16_t SPI_FLASH_ManufactDeviceID(void);
uint32_t SPI_FLASH_JedecID(void);
void SPI_FLASH_UniqueID(uint8_t* pBuffer);
void SPI_FLASH_PowerDown(void);
void SPI_FLASH_WAKEUP(void);
void SPI_FLASH_Test(void);
#ifdef __cplusplus
}
#endif
#endif
2.3, main.c
#include "main.h"
void Delay(uint16_t nCount);
void rcc_config(void)
{
uint8_t res = 0U;
RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_FLASH, ENABLE);
RCC_LSI_Enable( ); //开启外部高速时钟LSI
res = RCC_SysClk_Switch( RCC_SYSCLKSRC_LSI ); //切换系统时钟到LSI
if( res == 0x00 ) //系统时钟切换成功
{
RCC_HSI_Disable(); //切换时钟到PLL后关闭源时钟HSI
FirmwareDelay( 400 ); //about 100mS
}
RCC_HSI_Enable( RCC_HSIOSC_DIV1 ); //开启内部高速时钟HSI = HSIOSC / 2
FLASH_SetLatency(FLASH_Latency_3);
res = RCC_SysClk_Switch( RCC_SYSCLKSRC_HSI ); //切换系统时钟到HSI
if( res == 0x00 ) //系统时钟切换成功
{
RCC_LSI_Disable(); //切换时钟到HSI后关闭LSI时钟
FirmwareDelay( 275000 ); //about 100mS
}
RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
RCC_HCLK_OUT(); //通过PA04观察HCLK频率
}
int32_t main(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
rcc_config();
init_uart();
init_led();
init_spi_flash();
InitTick( 48000000 ); //初始化SysTick
SPI_FLASH_Test();
while (1)
{
led2_tog();
SysTickDelay(100);
//printf("CW32L052 UART Printf Test!\r\n");
}
}
/**
* @brief 循环延时
*
* @param nCount
*/
void Delay(__IO uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
/******************************************************************************
* EOF (not truncated)
******************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
3. Program running
Download the program, and the serial port output content of the development board is as follows:
|