- /**
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] Main program body
- *
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.0.0
- *
- * [url=home.php?mod=space&uid=212281]@date[/url] 2024-12-01
- *
- * @attention
- *
- * Copyright (C) 2024-2025 Geehy Semiconductor
- *
- * You may not use this file except in compliance with the
- * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
- *
- * The program is only for reference, which is distributed in the hope
- * that it will be useful and instructional for customers to develop
- * their software. Unless required by applicable law or agreed to in
- * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
- * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
- * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
- * and limitations under the License.
- */
- /* Includes ***************************************************************/
- #include "main.h"
- #include "bsp_w25q16.h"
- /* Private includes *******************************************************/
- #include <stdio.h>
- /* Private macro **********************************************************/
- /* printf function configs to USART */
- #define DEBUG_USART USART1
- #define DATA_BUF_SIZE 128
- typedef enum {FALSE, TRUE} BOOL;
- W25Q16_INFO_T w25q16Info;
- uint16_t txDataBufSPI1[DATA_BUF_SIZE] = {0};
- uint16_t rxDataBufSPI1[DATA_BUF_SIZE] = {0};
- /** SPI TX Buffer*/
- const uint16_t SPI_Data_TX[DATA_BUF_SIZE] =
- {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
- };
- /* Private function prototypes ********************************************/
- void USART_Init(void);
- void Delay(uint32_t count);
- void W25Q16_SPI_Test(void);
- void Print_Buffer(uint16_t* pBuffer, uint16_t BufferLength);
- uint8_t BufferCompare(uint16_t* buf1, uint16_t* buf2, uint8_t size);
- /* External variables *****************************************************/
- /* External functions *****************************************************/
- /*!
- * @brief Main program
- *
- * @param None
- *
- * @retval None
- */
- int main(void)
- {
- USART_Init();
- W25Q16_SPI_Init();
-
- /* Get Flash Device ID */
- w25q16Info.deviceID = W25Q16_ReadFlashDeviceID();
- printf("Device ID:0x%X\r\n",w25q16Info.deviceID);
-
- /* Get Flash ID */
- w25q16Info.flashID = W25Q16_ReadFlashID();
- printf("Flash ID:0x%X\r\n",w25q16Info.flashID);
- W25Q16_SPI_Test();
- /* Infinite loop */
- while (1)
- {
- }
- }
- /*!
- * @brief USART INIT
- *
- * @param None
- *
- * @retval None
- *
- * @note
- */
- void USART_Init(void)
- {
- USART_Config_T USART_ConfigStruct;
- GPIO_Config_T GPIO_ConfigStruct;
- // 使能 USART1 和 GPIO 端口时钟
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1 | RCM_APB2_PERIPH_GPIOA);
- // 配置 TX 引脚为复用推挽输出
- GPIO_ConfigStruct.pin = GPIO_PIN_9;
- GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
- GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
- GPIO_Config(GPIOA, &GPIO_ConfigStruct);
- // 配置 RX 引脚为浮空输入
- GPIO_ConfigStruct.pin = GPIO_PIN_10;
- GPIO_ConfigStruct.mode = GPIO_MODE_IN_FLOATING;
- GPIO_Config(GPIOA, &GPIO_ConfigStruct);
- // USART 配置
- USART_ConfigStructInit(&USART_ConfigStruct);
- USART_ConfigStruct.baudRate = 115200;
- USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
- USART_ConfigStruct.mode = USART_MODE_TX_RX; // 同时启用发送和接收模式
- USART_ConfigStruct.parity = USART_PARITY_NONE;
- USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
- USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
- USART_Config(USART1, &USART_ConfigStruct);
- // 使能 USART1
- USART_Enable(USART1);
- }
- /*!
- * @brief Using SPI operate W25Q16 flash
- *
- * @param None
- *
- * @retval None
- *
- * @note
- */
- void W25Q16_SPI_Test(void)
- {
- uint16_t i = 0;
-
- /* initialization Buffer*/
- for (i = 0; i < DATA_BUF_SIZE; i++)
- {
- txDataBufSPI1[i] = SPI_Data_TX[i] + 0x1010;
- rxDataBufSPI1[i] = 0;
- }
- printf("SPI write Data to flash \r\n");
- /* Erase SPI FLASH Sector */
- W25Q16_EraseSector(W25Q16_FLASH_WRITE_ADDR);
- /* Write data to flash */
- W25Q16_WriteBuffer((uint8_t*)txDataBufSPI1, W25Q16_FLASH_WRITE_ADDR, DATA_BUF_SIZE * 2);
- printf("\r\nWrite data: \r\n");
- Print_Buffer(txDataBufSPI1, DATA_BUF_SIZE);
- /* Read data from flash */
- W25Q16_ReadBuffer((uint8_t*)rxDataBufSPI1, W25Q16_FLASH_READ_ADDR, DATA_BUF_SIZE * 2);
- printf("\r\nRead data: \r\n");
- Print_Buffer(rxDataBufSPI1, DATA_BUF_SIZE);
- /* Compare receive Buffer */
- /* Data is ok then turn on LED2 */
- if (BufferCompare(txDataBufSPI1, rxDataBufSPI1, DATA_BUF_SIZE) == TRUE)
- {
- printf("\r\nSPI Flash test OK! LED2 on\n\r");
- }
- else
- {
- printf("\r\nSPI Flash test fail! LED3 on\n\r");
- }
- }
- /*!
- * @brief Compares two buffers
- *
- * @param buf1: First buffer to be compared
- *
- * @param buf1: Second buffer to be compared
- *
- * @param size: Buffer size
- *
- * @retval Return TRUE if buf1 = buf2. If not then return FALSE
- */
- uint8_t BufferCompare(uint16_t* buf1, uint16_t* buf2, uint8_t size)
- {
- uint8_t i;
- for (i = 0; i < size; i++)
- {
- if (buf1[i] != buf2[i])
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- /*!
- * @brief Print Buffer Data
- *
- * @param pBuffer:buffer
- *
- * @param length : length of the Buffer
- *
- * @retval None
- */
- void Print_Buffer(uint16_t* pBuffer, uint16_t BufferLength)
- {
- uint16_t i;
- for (i=0; i < BufferLength; i++)
- {
- printf("0x%04X ", pBuffer[i]);
- if ((i+1)%8 == 0)
- {
- printf("\r\n");
- }
- }
- }
- /*!
- * @brief Delay
- *
- * @param count: delay count
- *
- * @retval None
- */
- void Delay(uint32_t count)
- {
- uint16_t i = 0;
- while (count--)
- {
- i = 7995;
- while (i--);
- }
- }
- #if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param ch: The characters that need to be send.
- *
- * @param *f: pointer to a FILE that can recording all information
- * needed to control a stream
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int fputc(int ch, FILE* f)
- {
- /* send a byte of data to the serial port */
- USART_TxData(DEBUG_USART, (uint8_t)ch);
- /* wait for the data to be send */
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
- return (ch);
- }
- #elif defined (__GNUC__)
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param ch: The characters that need to be send.
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int __io_putchar(int ch)
- {
- /* send a byte of data to the serial port */
- USART_TxData(DEBUG_USART, ch);
- /* wait for the data to be send */
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
- return ch;
- }
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param file: Meaningless in this function.
- *
- * @param *ptr: Buffer pointer for data to be sent.
- *
- * @param len: Length of data to be sent.
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int _write(int file, char* ptr, int len)
- {
- UNUSED(file);
- int i;
- for (i = 0; i < len; i++)
- {
- __io_putchar(*ptr++);
- }
- return len;
- }
- #else
- #warning Not supported compiler type
- #endif
SPI Flash 驱动.c
- /*!
- * @file bsp_sdio.c
- *
- * @brief SDIO board support package body
- *
- * @version V1.0.0
- *
- * @date 2022-09-30
- *
- * @attention
- *
- * Copyright (C) 2022 Geehy Semiconductor
- *
- * You may not use this file except in compliance with the
- * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
- *
- * The program is only for reference, which is distributed in the hope
- * that it will be useful and instructional for customers to develop
- * their software. Unless required by applicable law or agreed to in
- * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
- * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
- * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
- * and limitations under the License.
- */
- /* Includes */
- #include "bsp_w25q16.h"
- /** @addtogroup Board
- @{
- */
- /** @addtogroup Board_APM32E103_EVAL
- @{
- */
- /** @defgroup APM32E103_EVAL_Fuctions
- @{
- */
- /*!
- * @brief W25Q16 SPI Initialization
- *
- * @param None
- *
- * @retval None
- */
- void W25Q16_SPI_Init(void)
- {
- GPIO_Config_T gpioConfig;
- SPI_Config_T spiConfig;
- /* Enable related Clock */
- RCM_EnableAPB2PeriphClock(FLASH_SPI_BUS_CLK | FLASH_SPI_GPIO_CLK | FLASH_SPI_CS_GPIO_CLK |RCM_APB2_PERIPH_AFIO);
-
- GPIO_ConfigPinRemap(GPIO_REMAP_SWJ_JTAGDISABLE);
- /* Configure FLASH_SPI pins: SCK */
- gpioConfig.pin = FLASH_SPI_SCK_PIN ;
- gpioConfig.mode = GPIO_MODE_AF_PP;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- GPIO_Config(FLASH_SPI_GPIO_PORT, &gpioConfig);
- /* Configure FLASH_SPI pins: MOSI */
- gpioConfig.pin = FLASH_SPI_MOSI_PIN;
- GPIO_Config(FLASH_SPI_GPIO_PORT, &gpioConfig);
- /* Configure FLASH_SPI pins: MISO */
- gpioConfig.pin = FLASH_SPI_MISO_PIN;
- gpioConfig.mode = GPIO_MODE_IN_FLOATING;
- GPIO_Config(FLASH_SPI_GPIO_PORT, &gpioConfig);
- /* Configure FLASH_SPI_CS_PIN pin: sFLASH Card CS pin */
- gpioConfig.pin = FLASH_SPI_CS_PIN;
- gpioConfig.mode = GPIO_MODE_OUT_PP;
- GPIO_Config(FLASH_SPI_CS_GPIO_PORT, &gpioConfig);
- /* Deselect the FLASH: Chip Select high */
- FLASH_SPI_CS_SET();
- /* SPI configuration */
- spiConfig.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
- spiConfig.mode = SPI_MODE_MASTER;
- spiConfig.length = SPI_DATA_LENGTH_8B;
- spiConfig.polarity = SPI_CLKPOL_HIGH;
- spiConfig.phase = SPI_CLKPHA_2EDGE;
- spiConfig.nss = SPI_NSS_SOFT;
- spiConfig.baudrateDiv = SPI_BAUDRATE_DIV_4;
- spiConfig.firstBit = SPI_FIRSTBIT_MSB;
- spiConfig.crcPolynomial =0;
- SPI_Config(FLASH_SPI_BUS, &spiConfig);
- /* Enable SPI */
- SPI_Enable(FLASH_SPI_BUS);
- }
- /*!
- * @brief Erase Falsh Sector
- *
- * @param SectorAddr:Sector Addr
- *
- * @retval None
- */
- void W25Q16_EraseSector(uint32_t SectorAddr)
- {
- /* Flash Write Enable */
- W25Q16_EnableFlashWrite();
- W25Q16_WaitFlashWriteEnd();
- /* Select the FLASH */
- FLASH_SPI_CS_CLR();
- /* send cmd */
- W25Q16_SendByte(W25Q16_SECTOR_ERASE);
- /* send Sector Addr */
- W25Q16_SendByte((SectorAddr & 0xFF0000) >> 16);
- W25Q16_SendByte((SectorAddr & 0xFF00) >> 8);
- W25Q16_SendByte(SectorAddr & 0xFF);
- /* Deselect the FLASH */
- FLASH_SPI_CS_SET();
- /* wait Falsh Erase end */
- W25Q16_WaitFlashWriteEnd();
- }
- /**
- * @brief 擦除FLASH扇区,整片擦除
- * @param 无
- * @retval 无
- */
- void SPI_FLASH_BulkErase(void)
- {
- /* 发送FLASH写使能命令 */
- W25Q16_EnableFlashWrite();
- /* 整块 Erase */
- /* 选择FLASH: CS低电平 */
- FLASH_SPI_CS_CLR();
- /* 发送整块擦除指令*/
- W25Q16_SendByte(W25Q16_CHIP_ERASE);
- /* 停止信号 FLASH: CS 高电平 */
- FLASH_SPI_CS_SET();
- /* 等待擦除完毕*/
- W25Q16_WaitFlashWriteEnd();
- }
- /*!
- * @brief Flash Write Page
- *
- * @param pBuffer: pointer to the Write buffer
- *
- * @param WriteAddr: Write the flash Address
- *
- * @param NumToWrite: the number of byte to write
- *
- * @retval None
- */
- void W25Q16_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumToWrite)
- {
- /* Enable Flash Write */
- W25Q16_EnableFlashWrite();
- /* Select the FLASH */
- FLASH_SPI_CS_CLR();
- /* W25Q16 Page Program */
- W25Q16_SendByte(W25Q16_PAGE_PROGRAM);
- W25Q16_SendByte((WriteAddr & 0xFF0000) >> 16);
- W25Q16_SendByte((WriteAddr & 0xFF00) >> 8);
- W25Q16_SendByte(WriteAddr & 0xFF);
- if (NumToWrite > W25Q16_FLASH_PAGE_SIZE)
- {
- NumToWrite = W25Q16_FLASH_PAGE_SIZE;
- }
- /* Write data to flash*/
- while (NumToWrite--)
- {
- /* 发送当前要写入的字节数据 */
- W25Q16_SendByte(*pBuffer);
- /* 指向下一字节数据 */
- pBuffer++;
- }
- /* Deselect the FLASH */
- FLASH_SPI_CS_SET();
- /* Wait Write End*/
- W25Q16_WaitFlashWriteEnd();
- }
- /*!
- * @brief Flash Write Buffer
- *
- * @param pBuffer: pointer to the Write buffer
- *
- * @param WriteAddr: Write the flash Address
- *
- * @param NumToWrite: the number of byte to write
- *
- * @retval None
- */
- void W25Q16_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumToWrite)
- {
- uint8_t i = 0;
- uint8_t PageNumber = 0;
- uint8_t RemainNumber = 0;
- uint8_t PageRemainNumber = 0;
- /* complete Page need to write */
- PageNumber = NumToWrite / W25Q16_FLASH_PAGE_SIZE;
- /* Remain byte */
- RemainNumber = NumToWrite % W25Q16_FLASH_PAGE_SIZE;
- /* if WriteAddr align */
- if ((WriteAddr % W25Q16_FLASH_PAGE_SIZE) == 0)
- {
- /* NumToWrite < W25Q16_FLASH_PAGE_SIZE */
- if (PageNumber == 0)
- {
- W25Q16_WritePage(pBuffer, WriteAddr, NumToWrite);
- }
- else
- {
- /* write complete Page */
- for (i = 0; i < PageNumber; i++)
- {
- W25Q16_WritePage(pBuffer, WriteAddr, W25Q16_FLASH_PAGE_SIZE);
- WriteAddr += W25Q16_FLASH_PAGE_SIZE;
- pBuffer += W25Q16_FLASH_PAGE_SIZE;
- }
- /* write remain data */
- if (RemainNumber > 0)
- {
- W25Q16_WritePage(pBuffer, WriteAddr, RemainNumber);
- }
- }
- }
- else
- {
- /* Write Address Page Remain Number */
- PageRemainNumber = W25Q16_FLASH_PAGE_SIZE - (WriteAddr % W25Q16_FLASH_PAGE_SIZE);
- /* NumToWrite < W25Q16_FLASH_PAGE_SIZE */
- if (PageNumber == 0)
- {
- if (RemainNumber > PageRemainNumber)
- {
- /* write all over the current page */
- W25Q16_WritePage(pBuffer, WriteAddr, PageRemainNumber);
- WriteAddr += PageRemainNumber;
- pBuffer += PageRemainNumber;
- RemainNumber = RemainNumber - PageRemainNumber;;
- /* write remain data */
- W25Q16_WritePage(pBuffer, WriteAddr, RemainNumber);
- }
- else
- {
- W25Q16_WritePage(pBuffer, WriteAddr, RemainNumber);
- }
- }
- else
- {
- /* write all over the current page */
- W25Q16_WritePage(pBuffer, WriteAddr, PageRemainNumber);
- WriteAddr += PageRemainNumber;
- pBuffer += PageRemainNumber;
- NumToWrite -= PageRemainNumber;
- PageNumber = NumToWrite / W25Q16_FLASH_PAGE_SIZE;
- RemainNumber = NumToWrite % W25Q16_FLASH_PAGE_SIZE;
- /* write complete Page */
- for (i = 0; i < PageNumber; i++)
- {
- W25Q16_WritePage(pBuffer, WriteAddr, W25Q16_FLASH_PAGE_SIZE);
- WriteAddr += W25Q16_FLASH_PAGE_SIZE;
- pBuffer += W25Q16_FLASH_PAGE_SIZE;
- }
- /* write remain data */
- if (RemainNumber > 0)
- {
- W25Q16_WritePage(pBuffer, WriteAddr, RemainNumber);
- }
- }
- }
- }
- /*!
- * @brief Flash Read Buffer
- *
- * @param pBuffer: pointer to the read buffer
- *
- * @param ReadAddr: read the flash Address
- *
- * @param NumToWrite: the number of byte to read
- *
- * @retval None
- */
- void W25Q16_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumToRead)
- {
- uint16_t i = 0;
- /* Select the FLASH */
- FLASH_SPI_CS_CLR();
- /* send read cmd */
- W25Q16_SendByte(W25Q16_READ_DATA);
- W25Q16_SendByte((ReadAddr & 0xFF0000) >> 16);
- W25Q16_SendByte((ReadAddr& 0xFF00) >> 8);
- W25Q16_SendByte(ReadAddr & 0xFF);
- /* read data to flash*/
- for (i = 0; i < NumToRead; i++)
- {
- *pBuffer = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- pBuffer++;
- }
- /* Deselect the FLASH */
- FLASH_SPI_CS_SET();
- }
- /*!
- * @brief Flash Read ID
- *
- * @param None
- *
- * @retval None
- */
- uint32_t W25Q16_ReadFlashID(void)
- {
- uint32_t TempBuffer[3] = {0};
- uint32_t FlashID = 0;
- /* Select the FLASH */
- FLASH_SPI_CS_CLR();
- /* send read ID cmd */
- W25Q16_SendByte(W25Q16_JEDEC_DEVICE_ID);
- TempBuffer[0] = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- TempBuffer[1] = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- TempBuffer[2] = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- /* Deselect the FLASH */
- FLASH_SPI_CS_SET();
- FlashID = (TempBuffer[0] << 16) | (TempBuffer[1] << 8) | TempBuffer[2];
- return FlashID;
- }
- /*!
- * @brief Read Flash DeviceID
- *
- * @param None
- *
- * @retval None
- */
- uint32_t W25Q16_ReadFlashDeviceID(void)
- {
- uint32_t DeviceID = 0;
- /* Select the FLASH */
- FLASH_SPI_CS_CLR();
- /* Send W25Q16 DeviceID cmd */
- W25Q16_SendByte(W25Q16_DEVICE_ID);
- W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- /* Read DeviceID from the FLASH */
- DeviceID = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- /* Deselect the FLASH */
- FLASH_SPI_CS_SET();
- return DeviceID;
- }
- /*!
- * @brief SPI read Byte from flash
- *
- * @param None
- *
- * @retval None
- */
- uint8_t W25Q16_ReadByte(void)
- {
- uint8_t temp = 0;
- temp = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- return temp;
- }
- /*!
- * @brief SPI Send Byte to flash
- *
- * @param None
- *
- * @retval None
- */
- uint8_t W25Q16_SendByte(uint8_t data)
- {
- /* SPI master send data */
- while (SPI_I2S_ReadStatusFlag(FLASH_SPI_BUS, SPI_FLAG_TXBE) == RESET);
- SPI_I2S_TxData(FLASH_SPI_BUS, data);
- /* SPI slave receive data */
- while (SPI_I2S_ReadStatusFlag(FLASH_SPI_BUS, SPI_FLAG_RXBNE) == RESET);
- return SPI_I2S_RxData(FLASH_SPI_BUS);
- }
- /*!
- * @brief Enable Flash Write
- *
- * @param None
- *
- * @retval None
- */
- void W25Q16_EnableFlashWrite(void)
- {
- FLASH_SPI_CS_CLR();
- /* send W25Q16 Write Enable cmd */
- W25Q16_SendByte(W25Q16_WRITE_ENABLE);
- FLASH_SPI_CS_SET();
- }
- /*!
- * @brief Wait Flash Write End
- *
- * @param None
- *
- * @retval None
- */
- void W25Q16_WaitFlashWriteEnd(void)
- {
- uint8_t RegStatus = 0;
- FLASH_SPI_CS_CLR();
- /* send Read W25Q16 Status cmd */
- W25Q16_SendByte(W25Q16_READ_STATUS_REG);
- do
- {
- /* Read W25Q16 Status Reg */
- RegStatus = W25Q16_SendByte(W25Q16_DUMMY_BYTE);
- }
- while ((RegStatus & W25Q16_WIP_FLAG) != 0);
- FLASH_SPI_CS_SET();
- }
- /*!
- * @brief Flash Into PowerDown
- *
- * @param None
- *
- * @retval None
- */
- void W25Q16_IntoPowerDown(void)
- {
- FLASH_SPI_CS_CLR();
- /* send PowerDown cmd*/
- W25Q16_SendByte(W25Q16_POWER_DOWN);
- FLASH_SPI_CS_SET();
- }
- /**@} end of group APM32E103_EVAL_Functions */
- /**@} end of group Board_APM32E103_EVAL */
- /**@} end of group Board */
SPI Flash 驱动.h
- /* Define to prevent recursive inclusion */
- #ifndef __BSP_SPI_FLASH_H
- #define __BSP_SPI_FLASH_H
- /* Includes */
- #include "main.h"
- /* W25Q16 */
- #define W25Q16_FLASH_ID 0xEF4015
- #define W25Q16_FLASH_PAGE_SIZE 256
- #define W25Q16_FLASH_WRITE_ADDR 0x00000
- #define W25Q16_FLASH_READ_ADDR W25Q16_FLASH_WRITE_ADDR
- /* W25Q16 CMD */
- #define W25Q16_WRITE_ENABLE 0x06
- #define W25Q16_WRITE_DISABLE 0x04
- #define W25Q16_READ_STATUS_REG 0x05
- #define W25Q16_WRITE_STATUS_REG 0x01
- #define W25Q16_READ_DATA 0x03
- #define W25Q16_FAST_READ_DATA 0x0B
- #define W25Q16_FAST_RAED_DUAL 0x3B
- #define W25Q16_PAGE_PROGRAM 0x02
- #define W25Q16_BLOCK_ERASE 0xD8
- #define W25Q16_SECTOR_ERASE 0x20
- #define W25Q16_CHIP_ERASE 0xC7
- #define W25Q16_POWER_DOWN 0xB9
- #define W25Q16_RELEASE_POWER_DOWN 0xAB
- #define W25Q16_DEVICE_ID 0xAB
- #define W25Q16_MANUFACT_DEVICE_ID 0x90
- #define W25Q16_JEDEC_DEVICE_ID 0x9F
- #define W25Q16_WIP_FLAG 0x01
- #define W25Q16_DUMMY_BYTE 0xFF
- /* FLASH CS */
- #define FLASH_SPI_BUS SPI1
- #define FLASH_SPI_BUS_CLK RCM_APB2_PERIPH_SPI1
- #define FLASH_SPI_MOSI_PIN GPIO_PIN_7
- #define FLASH_SPI_MISO_PIN GPIO_PIN_6
- #define FLASH_SPI_SCK_PIN GPIO_PIN_5
- #define FLASH_SPI_GPIO_CLK RCM_APB2_PERIPH_GPIOA
- #define FLASH_SPI_GPIO_PORT GPIOA
- #define FLASH_SPI_CS_PIN GPIO_PIN_4
- #define FLASH_SPI_CS_GPIO_CLK RCM_APB2_PERIPH_GPIOA
- #define FLASH_SPI_CS_GPIO_PORT GPIOA
-
- //#define FLASH_SPI_MOSI_SOURCE GPIO_PIN_SOURCE_15
- //#define FLASH_SPI_MISO_SOURCE GPIO_PIN_SOURCE_14
- //#define FLASH_SPI_SCK_SOURCE GPIO_PIN_SOURCE_13
- //#define FLASH_SPI_CS_SOURCE GPIO_PIN_SOURCE_12
- //#define FLASH_SPI_GPIO_AF GPIO_AF_PIN1
-
- #define FLASH_SPI_MOSI_CLR() GPIO_ResetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_MOSI_PIN)
- #define FLASH_SPI_MOSI_SET() GPIO_SetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_MOSI_PIN)
-
- #define FLASH_SPI_MISO_CLR() GPIO_ResetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_MISO_PIN)
- #define FLASH_SPI_MISO_SET() GPIO_SetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_MISO_PIN)
-
- #define FLASH_SPI_SCK_CLR() GPIO_ResetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_SCK_PIN)
- #define FLASH_SPI_SCK_SET() GPIO_SetBit(FLASH_SPI_GPIO_PORT, FLASH_SPI_SCK_PIN)
-
- #define FLASH_SPI_CS_CLR() GPIO_ResetBit(FLASH_SPI_CS_GPIO_PORT, FLASH_SPI_CS_PIN)
- #define FLASH_SPI_CS_SET() GPIO_SetBit(FLASH_SPI_CS_GPIO_PORT, FLASH_SPI_CS_PIN)
- /**@} end of group APM32E103_EVAL_Macros*/
- /** @defgroup APM32E103_EVAL_Structures Structures
- @{
- */
- typedef struct {
- uint32_t deviceID;
- uint32_t flashID;
- } W25Q16_INFO_T;
- /**@} end of group APM32E103_EVAL_Structures*/
- /** @defgroup APM32E103_EVAL_Functions Functions
- @{
- */
- void W25Q16_IntoPowerDown(void);
- uint8_t W25Q16_SendByte(uint8_t byte);
- uint8_t W25Q16_ReadByte(void);
- void W25Q16_SPI_Init(void);
- void W25Q16_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumToWrite);
- void W25Q16_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumToWrite);
- void W25Q16_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumToRead);
- uint32_t W25Q16_ReadFlashID(void);
- uint32_t W25Q16_ReadFlashDeviceID(void);
- void W25Q16_EnableFlashWrite(void);
- void W25Q16_WaitFlashWriteEnd(void);
- void W25Q16_EraseSector(uint32_t SectorAddr);
- void SPI_FLASH_BulkErase(void);
- #endif /* __BSP_SPI_FLASH_H */