当前位置:网站首页>[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
边栏推荐
- [lock] redis lock handles concurrency atomicity
- 微信小程序03-文字一左一右显示,行内块元素居中
- Wechat applet 03 - text is displayed from left to right, and the block elements in the line are centered
- Qt+pcl Chapter 9 point cloud reconstruction Series 2
- Description | Huawei cloud store "commodity recommendation list"
- 选择在长城证券上炒股开户可以吗?安全吗?
- Returning to the top of the list, the ID is still weak
- Flink 系例 之 TableAPI & SQL 与 MYSQL 分组统计
- idea中新建的XML文件变成普通文件的解决方法.
- 《QT+PCL第六章》点云配准icp系列2
猜你喜欢
openssl客户端编程:一个不起眼的函数导致的SSL会话失败问题
The data in the database table recursively forms a closed-loop data. How can we get these data
Hardware design guide for s32k1xx microcontroller
Opencv Learning Notes 6 -- image feature [harris+sift]+ feature matching
idea中新建的XML文件变成普通文件的解决方法.
【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(三)
Implementation of deploying redis sentry in k8s
《QT+PCL第六章》点云配准icp系列6
Introduction to MySQL audit plug-in
Basic operations of SQL database
随机推荐
Flink 系例 之 TableAPI & SQL 与 MYSQL 分组统计
opencv学习笔记四--银行卡号识别
[antenna] [3] some shortcut keys of CST
Intelligent operation and maintenance practice: banking business process and single transaction tracking
项目中字符串判空总结
如何实现时钟信号分频?
雷神科技冲刺北交所,拟募集资金5.4亿元
Tableapi & SQL and Kafka message acquisition of Flink example
选择在长城证券上炒股开户可以吗?安全吗?
Solid smart contract development - easy to get started
opencv学习笔记六--图像拼接
[Cloudera][ImpalaJDBCDriver](500164)Error initialized or created transport for authentication
Implementation of wechat web page subscription message
Is JPMorgan futures safe to open an account? What is the account opening method of JPMorgan futures company?
Markdown编辑器使用基本语法
Summary of point cloud reconstruction methods I (pcl-cgal)
《QT+PCL第九章》点云重建系列2
购物商城6.27待完成
点云重建方法汇总一(PCL-CGAL)
Detailed explanation of ArrayList expansion, expansion principle [easy to understand]