当前位置:网站首页>[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
边栏推荐
- Tableapi & SQL and Kafka message acquisition of Flink example
- [lock] redis lock handles concurrency atomicity
- Recommendation of data acquisition tools and detailed graphic process of data acquisition list
- opencv学习笔记六--图像特征[harris+SIFT]+特征匹配
- Qt+pcl Chapter 6 point cloud registration ICP series 3
- MySQL 服务正在启动 MySQL 服务无法启动解决途径
- Qt+pcl Chapter 6 point cloud registration ICP Series 5
- What is the relationship between network speed, broadband, bandwidth and traffic?
- 做空蔚来的灰熊,以“碰瓷”中概股为生?
- Task.Run(), Task.Factory.StartNew() 和 New Task() 的行为不一致分析
猜你喜欢
《性能之巅第2版》阅读笔记(五)--file-system监测
微信公众号订阅消息 wx-open-subscribe 的实现及闭坑指南
Opencv Learning Notes 6 -- image mosaic
厦门灌口镇田头村特色农产品 甜头村特色农产品蚂蚁新村7.1答案
Wechat applet 02 - Implementation of rotation map and picture click jump
Survey of intrusion detection systems:techniques, datasets and challenges
MySQL审计插件介绍
Junda technology indoor air environment monitoring terminal PM2.5, temperature and humidity TVOC and other multi parameter monitoring
Guide de conception matérielle du microcontrôleur s32k1xx
Junda technology - wechat cloud monitoring scheme for multiple precision air conditioners
随机推荐
TS报错 Don‘t use `object` as a type. The `object` type is currently hard to use
leetcode:329. Longest increasing path in matrix
Solid basic structure and array, private / public function, return value and modifier of function, event
【锁】Redis锁 处理并发 原子性
将ABAP On-Premises系统连接到中央检查系统以进行自定义代码迁移
Tableapi & SQL and MySQL grouping statistics of Flink
入侵检测模型(An Intrusion-Detection Model)
idea中新建的XML文件变成普通文件的解决方法.
Summary of point cloud reconstruction methods I (pcl-cgal)
Opencv Learning Notes 6 -- image feature [harris+sift]+ feature matching
【ROS进阶篇】第五讲 ROS中的TF坐标变换
The data in the database table recursively forms a closed-loop data. How can we get these data
竣达技术丨室内空气环境监测终端 pm2.5、温湿度TVOC等多参数监测
常见健身器材EN ISO 20957认证标准有哪些
重回榜首的大众,ID依然乏力
SAP S/4HANA: 一条代码线,许多种选择
Basic operations of SQL database
Wechat applet 01 bottom navigation bar settings
贝联珠贯加入龙蜥社区,共同促进碳中和
STM32F4-TFT-SPI时序逻辑分析仪调试记录