当前位置:网站首页>[stm32-usb-msc problem help] stm32f411ceu6 (Weact) +w25q64+usb-msc flash uses SPI2 to read out only 520kb
[stm32-usb-msc problem help] stm32f411ceu6 (Weact) +w25q64+usb-msc flash uses SPI2 to read out only 520kb
2022-07-01 15:24:00 【Please call me Chang Sicong】
Problem description
STM32CubeMX Generate F411CEUx USB MSC engineering use SPI2 And w25qxx Combine to do 8MB The capacity of Flash when
Can't read Or the reading capacity is not matched
Hardware :STM32F411CEU6
w25q64
Pin configuration :
Reference material :
1、"Fyra-BH" Of 【STM32 Study 】 be based on STM32F411CEU6 Of USB Storage equipment @Fyra-BH
2、“zhe_boy_is_z” Of F411-WeAct( One )SPi Drive external Flash(W25Q64)@zhe_boy_is_z
Refer to the posts of the above two bloggers MSC Of Flash But it was found in SPI2 The computer displays the same settings under the channel FLASH The size is only 520KB
usbd_storage_if.c The file set capacity is :8MB
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x10000
#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
#define USER_STORAGE_LUN_NBR 1
#define USER_STORAGE_BLK_NBR 2048
#define USER_STORAGE_BLK_SIZ 4096 // Definitions actually used
But in SPI1 perhaps SPI3 It can be completely displayed on the channel 8MB Besides, it can be arbitrary “ Capacity expansion ”
Modify the parameter display 16MB Capacity
Problem exploration process
1、 The suspicion is w25qxx The library problem
Reference resources Pzkkkkkk :STM32Cube MX USB fictitious U disc +FATFS+W25Q128
Copy and paste it directly with ready-made code to read it 520KB
And during debugging, it is found that the following parameters affect the capacity display on the computer
#define STORAGE_BLK_SIZ 0x200
The law is :
STORAGE_BLK_SIZ | Display capacity | Format capacity |
---|---|---|
512 | 48.5kB | 68.5KB |
1024 | 117kB | 137kB |
2048 | 250kB | 274kB |
4096 | 520kB | 548kB |
When the storage block size changes The total capacity displayed during formatting is 137 Multiple
I didn't find this later 137 Where did it come from
Now the suspicion may be CubeMx There was a problem generating the Library , How to adjust I'm also new and not very skilled . Open the post after it is solved later
2、 Doubt the circuit design
Change one F411CEU6 The same problem of the board has not been solved , And there are pop ups that cannot be formatted :
Look at the chip manual
Look in the manual SPI Some of the instructions did not find the key information
DMA Channel problem
Get rid of DMA After that, I still can't
Problem recurrence process
usbd_storage_if.c
/* USER CODE BEGIN Header */
/** ****************************************************************************** * @file : usbd_storage_if.c * @version : v1.0_Cube * @brief : Memory management layer. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2021 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
#include "w25qxx.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @brief Usb device. * @{ */
/** @defgroup USBD_STORAGE * @brief Usb mass storage device module * @{ */
/** @defgroup USBD_STORAGE_Private_TypesDefinitions * @brief Private types. * @{ */
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/** * @} */
/** @defgroup USBD_STORAGE_Private_Defines * @brief Private defines. * @{ */
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x10000
#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
#define USER_STORAGE_LUN_NBR 1
#define USER_STORAGE_BLK_NBR 2048
#define USER_STORAGE_BLK_SIZ 4096
//#define USER_STORAGE_BLK_SIZ 2048
/* USER CODE END PRIVATE_DEFINES */
/** * @} */
/** @defgroup USBD_STORAGE_Private_Macros * @brief Private macros. * @{ */
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/** * @} */
/** @defgroup USBD_STORAGE_Private_Variables * @brief Private variables. * @{ */
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {
/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1' /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/** * @} */
/** @defgroup USBD_STORAGE_Exported_Variables * @brief Public variables. * @{ */
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/** * @} */
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes * @brief Private functions declaration. * @{ */
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/** * @} */
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
/* Private functions ---------------------------------------------------------*/
/** * @brief Initializes over USB FS IP * @param lun: * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
W25QXX_Init();
return (USBD_OK);
/* USER CODE END 2 */
}
/** * @brief . * @param lun: . * @param block_num: . * @param block_size: . * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
*block_num = USER_STORAGE_BLK_NBR;
*block_size = USER_STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
}
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
/* USER CODE BEGIN 5 */
return (USBD_OK);
/* USER CODE END 5 */
}
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
W25QXX_Read(buf, blk_addr * USER_STORAGE_BLK_SIZ, blk_len * USER_STORAGE_BLK_SIZ);
return (USBD_OK);
/* USER CODE END 6 */
}
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
W25QXX_Write(buf, blk_addr * USER_STORAGE_BLK_SIZ, blk_len * USER_STORAGE_BLK_SIZ);
return (USBD_OK);
/* USER CODE END 7 */
}
/** * @brief . * @param None * @retval . */
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (USER_STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/** * @} */
/** * @} */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
w25qxx.c
#include "w25qxx.h"
/
// This program is only for learning , Without the permission of the author , It shall not be used for any other purpose
//ALIENTEK STM32F103 Development board
//W25QXX Driver code
// The punctual atoms @ALIENTEK
// Technology Forum :www.openedv.com
// Date of creation :2017/5/30
// edition :V1.0
// copyright , Piracy must be investigated .
//Copyright(C) Guangzhou Xingyi Electronic Technology Co., Ltd 2014-2024
//All rights reserved
//
uint16_t W25QXX_TYPE = W25Q64; // The default is W25Q128
//4Kbytes For one Sector
//16 Sectors are 1 individual Block
//W25Q256
// Capacity of 32M byte , share 512 individual Block,8192 individual Sector
// initialization SPI FLASH Of IO mouth
void W25QXX_Init(void)
{
uint8_t temp;
W25QXX_CS(1); //SPI FLASH Unchecked
// SPI1_Init(); // Already in main.c In the initialization
W25QXX_TYPE = W25QXX_ReadID(); // Read FLASH ID.
if (W25QXX_TYPE == W25Q128) //SPI FLASH by W25Q256
{
temp = W25QXX_ReadSR(3); // Read status register 3, Determine the address pattern
if ((temp & 0X01) == 0) // If not 4 Byte address mode , entering 4 Byte address mode
{
W25QXX_CS(0); // Choose
SPIx_ReadWriteByte(W25X_Enable4ByteAddr); // Send into 4 Byte address mode instruction
uint8_t data = W25X_Enable4ByteAddr;
SPIx_WriteByte(&data, 1);
W25QXX_CS(1); // Cancel the selection
}
}
}
// Read W25QXX The status register of ,W25QXX Altogether 3 Status registers
// Status register 1:
//BIT7 6 5 4 3 2 1 0
//SPR RV TB BP2 BP1 BP0 WEL BUSY
//SPR: Default 0, Status register protection bit , coordination WP Use
//TB,BP2,BP1,BP0:FLASH Zone write protection settings
//WEL: Write enable lock
//BUSY: Busy flag bit (1, busy ;0, Free )
// Default :0x00
// Status register 2:
//BIT7 6 5 4 3 2 1 0
//SUS CMP LB3 LB2 LB1 (R) QE SRP1
// Status register 3:
//BIT7 6 5 4 3 2 1 0
//HOLD/RST DRV1 DRV0 (R) (R) WPS ADP ADS
//regno: Status register number , Fan :1~3
// Return value : Status register value
uint8_t W25QXX_ReadSR(uint8_t regno)
{
uint8_t byte = 0, command = 0;
switch (regno)
{
case 1:
command = W25X_ReadStatusReg1; // Read status register 1 Instructions
break;
case 2:
command = W25X_ReadStatusReg2; // Read status register 2 Instructions
break;
case 3:
command = W25X_ReadStatusReg3; // Read status register 3 Instructions
break;
default:
command = W25X_ReadStatusReg1;
break;
}
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(command); // Send read status register command
SPIx_ReadByte(&byte, 1);
W25QXX_CS(1); // Cancel the selection
return byte;
}
// Write W25QXX Status register
void W25QXX_Write_SR(uint8_t regno, uint8_t sr)
{
uint8_t command = 0;
switch (regno)
{
case 1:
command = W25X_WriteStatusReg1; // Write status register 1 Instructions
break;
case 2:
command = W25X_WriteStatusReg2; // Write status register 2 Instructions
break;
case 3:
command = W25X_WriteStatusReg3; // Write status register 3 Instructions
break;
default:
command = W25X_WriteStatusReg1;
break;
}
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(command); // Send write status register command
SPIx_ReadWriteByte(sr); // Write a byte
W25QXX_CS(1); // Cancel the selection
}
//W25QXX Write enable
// take WEL Set up
void W25QXX_Write_Enable(void)
{
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_WriteEnable); // Send write enable
W25QXX_CS(1); // Cancel the selection
}
//W25QXX Write No
// take WEL Zero clearing
void W25QXX_Write_Disable(void)
{
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_WriteDisable); // Send a write disable command
W25QXX_CS(1); // Cancel the selection
}
// Read chip ID
// The return value is as follows :
//0XEF13, Indicates that the chip model is W25Q80
//0XEF14, Indicates that the chip model is W25Q16
//0XEF15, Indicates that the chip model is W25Q32
//0XEF16, Indicates that the chip model is W25Q64
//0XEF17, Indicates that the chip model is W25Q128
//0XEF18, Indicates that the chip model is W25Q256
uint16_t W25QXX_ReadID(void)
{
uint16_t Temp = 0;
uint8_t byte = 0;
W25QXX_CS(0);
SPIx_ReadWriteByte(0x90); // Send read ID command
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadByte(&byte, 1);
Temp |= byte;
SPIx_ReadByte(&byte, 1);
Temp |= byte;
W25QXX_CS(1);
return Temp;
}
// Read SPI FLASH
// Start reading data of specified length at the specified address
//pBuffer: Data storage area
//ReadAddr: Address to start reading (24bit)
//NumByteToRead: The number of bytes to read ( Maximum 65535)
void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_ReadData); // Send the read command
if (W25QXX_TYPE == W25Q256) // If it is W25Q256 The address is 4 Bytes of , To send the highest 8 position
{
SPIx_ReadWriteByte((uint8_t)((ReadAddr) >> 24));
}
SPIx_ReadWriteByte((uint8_t)((ReadAddr) >> 16)); // send out 24bit Address
SPIx_ReadWriteByte((uint8_t)((ReadAddr) >> 8));
SPIx_ReadWriteByte((uint8_t)ReadAddr);
SPIx_ReadByte(pBuffer, NumByteToRead);
uint16_t count = 10000;
while ((HAL_SPI_GetState(&SPI_CH) == HAL_SPI_STATE_BUSY_RX)&&count)
{
count --;
}
W25QXX_CS(1);
}
//SPI On one page (0~65535) Less than 256 Bytes of data
// Write maximum at the specified address 256 Bytes of data
//pBuffer: Data storage area
//WriteAddr: The address to start writing (24bit)
//NumByteToWrite: Number of bytes to write ( Maximum 256), The number should not exceed the number of bytes left on the page !!!
void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
// uint16_t i;
W25QXX_Write_Enable(); //SET WEL
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_PageProgram); // Send a page write command
if (W25QXX_TYPE == W25Q256) // If it is W25Q256 The address is 4 Bytes of , To send the highest 8 position
{
SPIx_ReadWriteByte((uint8_t)((WriteAddr) >> 24));
}
SPIx_ReadWriteByte((uint8_t)((WriteAddr) >> 16)); // send out 24bit Address
SPIx_ReadWriteByte((uint8_t)((WriteAddr) >> 8));
SPIx_ReadWriteByte((uint8_t)WriteAddr);
SPIx_WriteByte(pBuffer, NumByteToWrite);
uint16_t count = 10000;
while ((HAL_SPI_GetState(&SPI_CH) == HAL_SPI_STATE_BUSY_TX)&&count)
{
count --;
}
// for (i = 0; i < NumByteToWrite; i++)
// SPIx_ReadWriteByte(pBuffer[i]); // Cycle numbers
W25QXX_CS(1); // Cancel the selection
W25QXX_Wait_Busy(); // Wait for the end of the write
}
// Write without test SPI FLASH
// You must make sure that the data in the address range you write is 0XFF, Otherwise, in Africa 0XFF Data written at will fail !
// It has the function of automatic page change
// Write data at the specified length , But make sure the address doesn't cross the line !
//pBuffer: Data storage area
//WriteAddr: The address to start writing (24bit)
//NumByteToWrite: Number of bytes to write ( Maximum 65535)
//CHECK OK
void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t pageremain;
pageremain = 256 - WriteAddr % 256; // The number of bytes left in a single page
if (NumByteToWrite <= pageremain)
pageremain = NumByteToWrite; // No more than 256 Bytes
while (1)
{
W25QXX_Write_Page(pBuffer, WriteAddr, pageremain);
if (NumByteToWrite == pageremain)
break; // The writing is over
else //NumByteToWrite>pageremain
{
pBuffer += pageremain;
WriteAddr += pageremain;
NumByteToWrite -= pageremain; // Subtract the number of bytes that have been written
if (NumByteToWrite > 256)
pageremain = 256; // You can write... At one time 256 Bytes
else
pageremain = NumByteToWrite; // Not enough 256 The bytes
}
};
}
// Write SPI FLASH
// Write data at the specified length
// This function has erase operation !
//pBuffer: Data storage area
//WriteAddr: The address to start writing (24bit)
//NumByteToWrite: Number of bytes to write ( Maximum 65535)
uint8_t W25QXX_BUFFER[4096];
void W25QXX_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t *W25QXX_BUF;
W25QXX_BUF = W25QXX_BUFFER;
secpos = WriteAddr / 4096; // Sector address
secoff = WriteAddr % 4096; // Offset within a sector
secremain = 4096 - secoff; // The size of the remaining space in the sector
//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);// Test use
// HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
if (NumByteToWrite <= secremain)
secremain = NumByteToWrite; // No more than 4096 Bytes
while (1)
{
W25QXX_Read(W25QXX_BUF, secpos * 4096, 4096); // Read the entire sector
for (i = 0; i < secremain; i++) // Check the data
{
if (W25QXX_BUF[secoff + i] != 0XFF)
break; // Need to erase
}
if (i < secremain) // Need to erase
{
W25QXX_Erase_Sector(secpos); // Erase this sector
for (i = 0; i < secremain; i++) // Copy
{
W25QXX_BUF[i + secoff] = pBuffer[i];
}
W25QXX_Write_NoCheck(W25QXX_BUF, secpos * 4096, 4096); // Write the entire sector
}
else
W25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain); // Write what has been erased , Write directly to the rest of the sector .
if (NumByteToWrite == secremain)
break; // The writing is over
else // Writing is not finished
{
secpos++; // Sector address increase 1
secoff = 0; // The offset is 0
pBuffer += secremain; // Pointer offset
WriteAddr += secremain; // Write address offset
NumByteToWrite -= secremain; // Bytes decrement
if (NumByteToWrite > 4096)
secremain = 4096; // I can't finish writing the next sector
else
secremain = NumByteToWrite; // The next sector can be written
}
};
}
// Erase the whole chip
// The waiting time is too long ...
void W25QXX_Erase_Chip(void)
{
W25QXX_Write_Enable(); //SET WEL
W25QXX_Wait_Busy();
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_ChipErase); // Send chip erase command
W25QXX_CS(1); // Cancel the selection
W25QXX_Wait_Busy(); // Wait for the chip erase to finish
}
// Erase a sector
//Dst_Addr: Sector address Set according to the actual capacity
// Minimum time to erase a sector :150ms
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{
// monitor falsh Erasure , Test use
//printf("fe:%x\r\n",Dst_Addr);
Dst_Addr *= 4096;
W25QXX_Write_Enable(); //SET WEL
W25QXX_Wait_Busy();
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_SectorErase); // Send sector erase command
if (W25QXX_TYPE == W25Q256) // If it is W25Q256 The address is 4 Bytes of , To send the highest 8 position
{
SPIx_ReadWriteByte((uint8_t)((Dst_Addr) >> 24));
}
SPIx_ReadWriteByte((uint8_t)((Dst_Addr) >> 16)); // send out 24bit Address
SPIx_ReadWriteByte((uint8_t)((Dst_Addr) >> 8));
SPIx_ReadWriteByte((uint8_t)Dst_Addr);
W25QXX_CS(1); // Cancel the selection
W25QXX_Wait_Busy(); // Wait for erasure to complete
}
// Waiting for leisure
void W25QXX_Wait_Busy(void)
{
while ((W25QXX_ReadSR(1) & 0x01) == 0x01)
; // wait for BUSY Bit empty
}
// Enter power down mode
void W25QXX_PowerDown(void)
{
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_PowerDown); // Send a power down command
W25QXX_CS(1); // Cancel the selection
HAL_Delay(3); // wait for TPD
}
// Wake up the
void W25QXX_WAKEUP(void)
{
W25QXX_CS(0); // Enabling devices
SPIx_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB
W25QXX_CS(1); // Cancel the selection
HAL_Delay(3); // wait for TRES1
}
uint8_t SPIx_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
#if (USE_DMA)
HAL_SPI_TransmitReceive_DMA(&SPI_CH,&TxData,&Rxdata,1);
#else
HAL_SPI_TransmitReceive(&SPI_CH,&TxData,&Rxdata,1, 1000);
#endif
return Rxdata; // Return the received data
}
void SPIx_WriteByte(uint8_t *pBuffer, uint16_t NumByteToWrite)
{
#if (USE_DMA)
HAL_SPI_Transmit_DMA(&SPI_CH, pBuffer, NumByteToWrite);
#else
HAL_SPI_Transmit(&SPI_CH, pBuffer, NumByteToWrite, 1000);
#endif
}
void SPIx_ReadByte(uint8_t *pBuffer, uint16_t NumByteToRead)
{
#if (USE_DMA)
HAL_SPI_Receive_DMA(&SPI_CH, pBuffer, NumByteToRead); // DMA channel
#else
HAL_SPI_Receive(&SPI_CH, pBuffer, NumByteToRead, 1000); //
#endif
}
w25qxx.h
//
//Usage:
//1.config SPI channel:
// #define SPI_CH hspix
//2.if USE SPI DMA chanel set:
// #define USE_DMA 1
//3.config w25qxx CS pin:
// #define W25QXX_CS_GPIO_Port F_CS_GPIO_Port
// #define W25QXX_CS_Pin F_CS_Pin
//
#ifndef __W25QXX_H
#define __W25QXX_H
#include <stdint.h>
#include "stm32f4xx_hal.h"
#include "main.h"
#define SPI_CH hspi2
#define USE_DMA 0 //read or write SPI use DMA:1 else:0;
#define W25QXX_CS_GPIO_Port F_CS_GPIO_Port
#define W25QXX_CS_Pin F_CS_Pin
extern SPI_HandleTypeDef SPI_CH;
//W25X series /Q List of serial chips
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25Q256 0XEF18
extern uint16_t W25QXX_TYPE; // Definition W25QXX Chip model
#define W25QXX_CS(state) HAL_GPIO_WritePin(W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, (GPIO_PinState)state)
//
// Instruction list
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg1 0x05
#define W25X_ReadStatusReg2 0x35
#define W25X_ReadStatusReg3 0x15
#define W25X_WriteStatusReg1 0x01
#define W25X_WriteStatusReg2 0x31
#define W25X_WriteStatusReg3 0x11
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_BlockErase 0xD8
#define W25X_SectorErase 0x20
#define W25X_ChipErase 0xC7
#define W25X_PowerDown 0xB9
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
#define W25X_Enable4ByteAddr 0xB7
#define W25X_Exit4ByteAddr 0xE9
uint8_t SPIx_ReadWriteByte(uint8_t TxData);
void SPIx_WriteByte(uint8_t *pBuffer, uint16_t NumByteToWrite);
void SPIx_ReadByte(uint8_t *pBuffer, uint16_t NumByteToRead);
void W25QXX_Init(void);
uint16_t W25QXX_ReadID(void); // Read FLASH ID
uint8_t W25QXX_ReadSR(uint8_t regno); // Read status register
void W25QXX_4ByteAddr_Enable(void); // Can make 4 Byte address mode
void W25QXX_Write_SR(uint8_t regno,uint8_t sr); // Write status register
void W25QXX_Write_Enable(void); // Write enable
void W25QXX_Write_Disable(void); // Write protect
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead); // Read flash
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);// write in flash
void W25QXX_Erase_Chip(void); // Erase the whole piece
void W25QXX_Erase_Sector(uint32_t Dst_Addr); // Sector erase
void W25QXX_Wait_Busy(void); // Waiting for leisure
void W25QXX_PowerDown(void); // Enter power down mode
void W25QXX_WAKEUP(void);
#endif
Problem analysis and resolution log
2022.6.12 Find the problem
2022.6.18 Bug It's not settled yet Write this blog
边栏推荐
- 《性能之巅第2版》阅读笔记(五)--file-system监测
- Tableapi & SQL and MySQL grouping statistics of Flink
- Recommendation of data acquisition tools and detailed graphic process of data acquisition list
- 使用 csv 导入的方式在 SAP S/4HANA 里创建 employee 数据
- What data capabilities do data product managers need to master?
- 项目中字符串判空总结
- 《QT+PCL第六章》点云配准icp系列2
- k8s部署redis哨兵的实现
- opencv学习笔记四--银行卡号识别
- Storage form of in-depth analysis data in memory
猜你喜欢
入侵检测模型(An Intrusion-Detection Model)
Recommendation of data acquisition tools and detailed graphic process of data acquisition list
[advanced ROS] lesson 5 TF coordinate transformation in ROS
张驰咨询:锂电池导入六西格玛咨询降低电池容量衰减
MySQL 服务正在启动 MySQL 服务无法启动解决途径
Fix the failure of idea global search shortcut (ctrl+shift+f)
Survey of intrusion detection systems:techniques, datasets and challenges
【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(三)
Wechat applet 01 bottom navigation bar settings
Official announcement: Apache Doris graduated successfully and became the top project of ASF!
随机推荐
[advanced ROS] lesson 5 TF coordinate transformation in ROS
TS报错 Don‘t use `object` as a type. The `object` type is currently hard to use
Junda technology indoor air environment monitoring terminal PM2.5, temperature and humidity TVOC and other multi parameter monitoring
Flink 系例 之 TableAPI & SQL 与 MYSQL 数据查询
phpcms后台上传图片按钮无法点击
摩根大通期货开户安全吗?摩根大通期货公司开户方法是什么?
Build MySQL master-slave server under Ubuntu 14.04
Wechat applet 01 bottom navigation bar settings
MySQL审计插件介绍
《QT+PCL第六章》点云配准icp系列3
The difference between arrow function and ordinary function in JS
It's settled! 2022 Hainan secondary cost engineer examination time is determined! The registration channel has been opened!
贝联珠贯加入龙蜥社区,共同促进碳中和
Wechat applet 03 - text is displayed from left to right, and the block elements in the line are centered
Wechat applet 02 - Implementation of rotation map and picture click jump
使用 csv 导入的方式在 SAP S/4HANA 里创建 employee 数据
SAP s/4hana: one code line, many choices
TypeScript: let
Description | Huawei cloud store "commodity recommendation list"
雷神科技冲刺北交所,拟募集资金5.4亿元