stm32基于HAL库驱动外部SPI flash制作虚拟U盘
- 🎞实现效果演示:

- 🔖上图中的读到的
FLASH_ID所指的是针对不同容量,所对应的ID。
//W25X/Q不同容量对应不同ID关系
W25Q80 ID 0XEF13
W25Q16 ID 0XEF14
W25Q32 ID 0XEF15
W25Q64 ID 0XEF16
W25Q128 ID 0XEF17
W25Q256 ID 0XEF18

- 🔖在电脑端,支持对虚拟出来的存储器进行读写操作。

- ✨如果设计成一块PCB,可以制作成一个微小容量的移动U盘。
- 🌿基于STM32F103,HAL库生成的代码,可以移植到任意支持USB接口的STM32单片机上使用。
- 🌿程序烧录后,通过PA11/PA12 USB初次连接电脑,会弹出提示格式化窗口。之后就可以使用,包括拷贝和创建文件到盘符内,保存数据后,拔插设备,数据不丢失。
stm32cumx配置
-
🌿stm32cumx使能对应的SPI接口

-
✨串口非必须,只是方便调试时查看读取是否支持。
-
🌿使能SPI接口:(尽量将SPI速度配置低一点,防止访问和写入出错)

-
🌿配置SPI CS(片选)引脚:

-
🌿使能USB外设:

-
🌿时钟配置为48MHz:


- 🌿使能调试接口

- 🌿勾选中间件:

- 🌿调整堆栈区大小:

🛠Keil工程修改
- 🌿导入驱动文件:
bsp_spi_flash.c和bsp_spi_flash.h到工程对应文件夹下:

- 🌿修改
usbd_storage_if.c文件内容:
/* USER CODE BEGIN INCLUDE */
#include "bsp_spi_flash.h" //将驱动头文件包含进来
/* USER CODE END INCLUDE */
//注释掉自动生成的以下3个宏定义
//#define STORAGE_LUN_NBR 1
//#define STORAGE_BLK_NBR 0x10000
//#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
//重新定义以下3个宏
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 2048 //块数量:256*8扇区=8MByte
#define STORAGE_BLK_SIZ 4096 //每个扇区4096Byte
/* USER CODE END PRIVATE_DEFINES */
- ✨这里的
STORAGE_BLK_NBR宏代表,外部SPI FLASH 容量大小,2048代表为8MB,如果spi flash容量为16MB,那么这里就是4096.以此类推,4MB spi flash就是1024
- 📑补充以下函数内容:(
usbd_storage_if.c文件内)
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
W25QXX_Init();
return (USBD_OK);
/* USER CODE END 2 */
}
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
}
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
u16 flash_ID;
flash_ID =W25QXX_ReadID();
printf("flash_ID:%d \r\n",flash_ID);//非必须,如需要调试,包含stdio.h头文件,启用串口
return (USBD_OK);
/* USER CODE END 4 */
}
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
blk_addr += SPI_FLASH_START_SECTOR;
SPI_FLASH_BufferRead(buf, blk_addr * SPI_FLASH_SECTOR_SIZE, blk_len * SPI_FLASH_SECTOR_SIZE);
return (USBD_OK);
/* USER CODE END 6 */
}
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
uint32_t write_addr;
blk_addr +=SPI_FLASH_START_SECTOR;
write_addr = blk_addr * SPI_FLASH_SECTOR_SIZE;
SPI_FLASH_SectorErase(write_addr);
SPI_FLASH_BufferWrite((uint8_t*)buf, write_addr, blk_len * SPI_FLASH_SECTOR_SIZE);
return (USBD_OK);
/* USER CODE END 7 */
}
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
- main.c文件
/* USER CODE BEGIN Includes */
#include "bsp_spi_flash.h"
#include "stdio.h"//用于调试串口输出
/* USER CODE END Includes */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_USB_DEVICE_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
W25QXX_Init();//初始化
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
📝驱动文件
- 📗
bsp_spi_flash.h内容
#ifndef __SPI_FLASH_H
#define __SPI_FLASH_H
#include "stm32f1xx.h"
#include "stm32f1xx_hal_spi.h"
/* ???????? ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
typedef uint32_t u32;
typedef uint8_t u8;//
typedef uint16_t u16;
#define SPI_FLASH_REBUILD 0 //1:???????????Flash??0??????????????Flash
#define SPI_FLASH_SECTOR_SIZE 4096 // ????Flash????????
#define SPI_FLASH_START_SECTOR 256*4 // ????Flash?????FatFS?????
#define SPI_FLASH_SECTOR_COUNT 256 // ????Flash?????FatFS???????????
//W25X/Q不同容量对应不同ID关系
//W25Q80 ID 0XEF13
//W25Q16 ID 0XEF14
//W25Q32 ID 0XEF15
//W25Q64 ID 0XEF16
//W25Q128 ID 0XEF17
//W25Q256 ID 0XEF18
//#define W25Q80 0XEF13
//#define W25Q16 0XEF14
//#define W25Q32 0XEF15
#define W25Q64 0XEF16
//#define W25Q128 0XEF17
//#define W25Q256 0XEF18
//#define sFLASH_ID 0XEF4017 //W25Q64
#define sFLASH_ID 0XEF16
extern SPI_HandleTypeDef hspi1;
extern u16 W25QXX_TYPE; //????W25QXX??????
//#define W25QXX_CS PBout(12) //W25QXX片选引脚

最低0.47元/天 解锁文章
2745

被折叠的 条评论
为什么被折叠?



