stm32基于HAL库驱动外部SPI flash制作虚拟U盘

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.cbsp_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片选引脚
STMicroelectronics的STM32F4系列微控制器是一款高性能、低功耗的MCU芯片。HAL(Hardware Abstraction Layer)库是STMicroelectronics提供的一种软件库,用于简化STM32系列微控制器的开发流程。 SPI(Serial Peripheral Interface)是一种通信协议,可以用于在微控制器和外设之间进行串行数据传输。LCD(Liquid Crystal Display)是一种常见的显示器件,用于显示图像和文本。使用STM32F4 HAL库驱动SPI LCD可以实现在STM32F4微控制器上控制LCD屏幕的功能。 首先,我们需要在STM32F4的硬件上连接SPI总线和LCD屏幕。通过阅读相关的硬件文档,我们可以了解到哪些引脚是SPI总线的主线和从线,以及如何正确连接LCD屏幕。 接下来,我们需要编写代码来初始化SPI总线和LCD屏幕。使用HAL库的相关函数,我们可以在代码中初始化SPI总线和配置相关的参数,如数据传输速率、时钟相位、数据位宽等。 在SPI总线初始化完成后,我们可以使用HAL库的函数来发送和接收数据。通过编写相应的代码,我们可以将需要显示的图像数据或文本发送到LCD屏幕上。 最后,我们需要编写代码来进行LCD屏幕的控制。这包括设置显示模式(如亮度、对比度等)、光标位置和显示字符等。HAL库提供了一系列函数,可以简化这些操作的实现。 总之,使用STM32F4 HAL库驱动SPI LCD可以方便地在STM32F4微控制器上控制LCD屏幕显示。我们只需要正确连接硬件,并编写相应的代码来初始化SPI总线和LCD屏幕,然后使用HAL库的函数进行数据传输和屏幕控制即可。这样可以大大简化LCD驱动的开发流程,节省开发时间和提高开发效率。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值