STM32 CubeMX USB_MSC(U盘存储设备)配置指南

STM32 CubeMX


STM32 CubeMX USB_MSC(存储设备U盘)

  • STM32 CubeMX
  • 前言
  • 《使用内部Flash》——U盘
  • 一、STM32 CubeMX 设置
  • USB时钟设置
  • USB使能
  • UBS功能选择
  • FATFS功能
  • 二、代码部分
  • 修改代码"usbd_storage_if.c"
  • 修改代码"user_diskio.c"
  • main函数初始化
  • 插上USB实验效果
  • 《SPI_SD卡》——U盘


  • 前言

    STM32 CubeMX 配置USB将STM32设置可以作为存储设备或者IAP升级功能

    《使用内部Flash》——U盘

    一、STM32 CubeMX 设置

    USB时钟设置

    USB使能

    UBS功能选择

    要注意:stm32f103c8t6内部Flash的1页为1024(1kb)

    FATFS功能

    二、代码部分

    需要修改两个部分:usbd_storage_if.c文件和user_diskio.c文件

    修改代码"usbd_storage_if.c"

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : usbd_storage_if.c
      * @version        : v2.0_Cube
      * @brief          : Memory management layer.
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2023 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    
    /* Includes ------------------------------------------------------------------*/
    #include "usbd_storage_if.h"
    
    /* USER CODE BEGIN INCLUDE */
    
    /* 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     FLASH_SIZE                  128
    #define     FMC_SECTOR_SIZE             1024
    #define     FLASH_PAGE_NBR              64
    #define     FLASH_START_ADDR        	(0x08000000+((FLASH_SIZE-FLASH_PAGE_NBR)*1024))
    
    #define STORAGE_LUN_NBR                  1
    #define STORAGE_BLK_NBR                  0x10000
    #define STORAGE_BLK_SIZ                  0x200
    
    /* USER CODE BEGIN PRIVATE_DEFINES */
    
    /* 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 */
      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  = STORAGE_BLK_NBR;
    //  *block_size = STORAGE_BLK_SIZ;
    //  return (USBD_OK);
    //  /* USER CODE END 3 */
    //}
    //修改1
    int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
    {
      /* USER CODE BEGIN 3 */
      *block_num  = FLASH_PAGE_NBR;
      *block_size = FLASH_PAGE_SIZE;
      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 */
    //  return (USBD_OK);
    //  /* USER CODE END 6 */
    //}
    //修改2
    int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 6 */
    	if(lun == 0)
    	{
            memcpy(buf,(uint8_t *)(FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE),blk_len*FLASH_PAGE_SIZE);
            return USBD_OK;
        }
        return USBD_FAIL;
      /* 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 */
    //  return (USBD_OK);
    //  /* USER CODE END 7 */
    //}
    //修改3
    int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 7 */
        uint16_t i;
        uint32_t PageError = 0;
        FLASH_EraseInitTypeDef Flash;
        if(lun == 0)
        {
    		HAL_FLASH_Unlock();
    		Flash.TypeErase = FLASH_TYPEERASE_PAGES;
    		Flash.PageAddress = FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE ;
    		Flash.NbPages = blk_len;
    		HAL_FLASHEx_Erase(&Flash, &PageError);
    		for(i=0;i<blk_len*FLASH_PAGE_SIZE;i+=4)
    		{
                HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE + i , *(uint32_t *)(&buf[i]));
            }
    		HAL_FLASH_Lock();
    		return USBD_OK;
        }
        return USBD_FAIL;
      /* USER CODE END 7 */
    }
    
    /**
      * @brief  .
      * @param  None
      * @retval .
      */
    int8_t STORAGE_GetMaxLun_FS(void)
    {
      /* USER CODE BEGIN 8 */
      return (STORAGE_LUN_NBR - 1);
      /* USER CODE END 8 */
    }
    
    /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
    
    /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    
    
    

    修改代码"user_diskio.c"

    /* USER CODE BEGIN Header */
    /**
     ******************************************************************************
      * @file    user_diskio.c
      * @brief   This file includes a diskio driver skeleton to be completed by the user.
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2023 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
     /* USER CODE END Header */
    
    #ifdef USE_OBSOLETE_USER_CODE_SECTION_0
    /*
     * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
     * To be suppressed in the future.
     * Kept to ensure backward compatibility with previous CubeMx versions when
     * migrating projects.
     * User code previously added there should be copied in the new user sections before
     * the section contents can be deleted.
     */
    /* USER CODE BEGIN 0 */
    /* USER CODE END 0 */
    #endif
    
    /* USER CODE BEGIN DECL */
    
    /* Includes ------------------------------------------------------------------*/
    #include <string.h>
    #include "ff_gen_drv.h"
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    
    /* Private variables ---------------------------------------------------------*/
    /* Disk status */
    static volatile DSTATUS Stat = STA_NOINIT;
    #define     FLASH_SIZE                  128
    #define     FMC_SECTOR_SIZE             1024
    #define     FLASH_PAGE_NBR              64
    #define     FLASH_START_ADDR        	(0x08000000+((FLASH_SIZE-FLASH_PAGE_NBR)*1024))
    /* USER CODE END DECL */
    
    /* Private function prototypes -----------------------------------------------*/
    DSTATUS USER_initialize (BYTE pdrv);
    DSTATUS USER_status (BYTE pdrv);
    DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
    #if _USE_WRITE == 1
      DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
    #endif /* _USE_WRITE == 1 */
    #if _USE_IOCTL == 1
      DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
    #endif /* _USE_IOCTL == 1 */
    
    Diskio_drvTypeDef  USER_Driver =
    {
      USER_initialize,
      USER_status,
      USER_read,
    #if  _USE_WRITE
      USER_write,
    #endif  /* _USE_WRITE == 1 */
    #if  _USE_IOCTL == 1
      USER_ioctl,
    #endif /* _USE_IOCTL == 1 */
    };
    
    /* Private functions ---------------------------------------------------------*/
    
    /**
      * @brief  Initializes a Drive
      * @param  pdrv: Physical drive number (0..)
      * @retval DSTATUS: Operation status
      */
    DSTATUS USER_initialize (
    	BYTE pdrv           /* Physical drive nmuber to identify the drive */
    )
    {
      /* USER CODE BEGIN INIT */
        Stat = STA_NOINIT;
        return Stat;
      /* USER CODE END INIT */
    }
    
    /**
      * @brief  Gets Disk Status
      * @param  pdrv: Physical drive number (0..)
      * @retval DSTATUS: Operation status
      */
    //DSTATUS USER_status (
    //	BYTE pdrv       /* Physical drive number to identify the drive */
    //)
    //{
    //  /* USER CODE BEGIN STATUS */
    //    Stat = STA_NOINIT;
    //    return Stat;
    //  /* USER CODE END STATUS */
    //}
    // 修改1
    DSTATUS USER_status (
    	BYTE pdrv       /* Physical drive number to identify the drive */
    )
    {
      /* USER CODE BEGIN STATUS */
        Stat = STA_NOINIT;
        Stat &= ~STA_NOINIT;
        return Stat;
      /* USER CODE END STATUS */
    }
    /**
      * @brief  Reads Sector(s)
      * @param  pdrv: Physical drive number (0..)
      * @param  *buff: Data buffer to store read data
      * @param  sector: Sector address (LBA)
      * @param  count: Number of sectors to read (1..128)
      * @retval DRESULT: Operation result
      */
    //DRESULT USER_read (
    //	BYTE pdrv,      /* Physical drive nmuber to identify the drive */
    //	BYTE *buff,     /* Data buffer to store read data */
    //	DWORD sector,   /* Sector address in LBA */
    //	UINT count      /* Number of sectors to read */
    //)
    //{
    //  /* USER CODE BEGIN READ */
    //    return RES_OK;
    //  /* USER CODE END READ */
    //}
    //修改2
    DRESULT USER_read (
    	BYTE pdrv,      /* Physical drive nmuber to identify the drive */
    	BYTE *buff,     /* Data buffer to store read data */
    	DWORD sector,   /* Sector address in LBA */
    	UINT count      /* Number of sectors to read */
    )
    {
      /* USER CODE BEGIN READ */
    	uint8_t *s = (uint8_t *)(FLASH_START_ADDR);  
    	s+=(sector*FMC_SECTOR_SIZE);
    	for(int i=0; i<count*FMC_SECTOR_SIZE ;i++)
    	{
    		*(buff++) = *(s++ );
    	}
        return RES_OK;
      /* USER CODE END READ */
    }
    /**
      * @brief  Writes Sector(s)
      * @param  pdrv: Physical drive number (0..)
      * @param  *buff: Data to be written
      * @param  sector: Sector address (LBA)
      * @param  count: Number of sectors to write (1..128)
      * @retval DRESULT: Operation result
      */
    #if _USE_WRITE == 1
    //DRESULT USER_write (
    //	BYTE pdrv,          /* Physical drive nmuber to identify the drive */
    //	const BYTE *buff,   /* Data to be written */
    //	DWORD sector,       /* Sector address in LBA */
    //	UINT count          /* Number of sectors to write */
    //)
    //{
    //  /* USER CODE BEGIN WRITE */
    //  /* USER CODE HERE */
    //    return RES_OK;
    //  /* USER CODE END WRITE */
    //}
    //修改3
    DRESULT USER_write (
    	BYTE pdrv,          /* Physical drive nmuber to identify the drive */
    	const BYTE *buff,   /* Data to be written */
    	DWORD sector,       /* Sector address in LBA */
    	UINT count          /* Number of sectors to write */
    )
    {
      /* USER CODE BEGIN WRITE */
      /* USER CODE HERE */
        uint16_t i;	
        HAL_FLASH_Unlock();
    	 
        FLASH_EraseInitTypeDef f;
        f.TypeErase = FLASH_TYPEERASE_PAGES;
        f.PageAddress = FLASH_START_ADDR + sector*FLASH_PAGE_SIZE ;
        f.NbPages = count;
        uint32_t PageError = 0;
        HAL_FLASHEx_Erase(&f, &PageError);
     
        for(i=0;i<count*FLASH_PAGE_SIZE;i+=4)
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,FLASH_START_ADDR + sector*FLASH_PAGE_SIZE + i , *(uint32_t *)(&buff[i]));
     
        HAL_FLASH_Lock();
        return RES_OK;
      /* USER CODE END WRITE */
    }
    #endif /* _USE_WRITE == 1 */
    
    /**
      * @brief  I/O control operation
      * @param  pdrv: Physical drive number (0..)
      * @param  cmd: Control code
      * @param  *buff: Buffer to send/receive control data
      * @retval DRESULT: Operation result
      */
    #if _USE_IOCTL == 1
    //DRESULT USER_ioctl (
    //	BYTE pdrv,      /* Physical drive nmuber (0..) */
    //	BYTE cmd,       /* Control code */
    //	void *buff      /* Buffer to send/receive control data */
    //)
    //{
    //  /* USER CODE BEGIN IOCTL */
    //    DRESULT res = RES_ERROR;
    //    return res;
    //  /* USER CODE END IOCTL */
    //}
    //修改4
    DRESULT USER_ioctl (
    	BYTE pdrv,      /* Physical drive nmuber (0..) */
    	BYTE cmd,       /* Control code */
    	void *buff      /* Buffer to send/receive control data */
    )
    {
      /* USER CODE BEGIN IOCTL */
        DRESULT res = RES_ERROR;
      switch(cmd)
      {
        case CTRL_SYNC :
    			res = RES_OK;
            break;	
     
        case CTRL_TRIM:
    			res = RES_OK;
            break;
    		
        case GET_BLOCK_SIZE:
    	*(DWORD*)buff = 1; 
    	break;
    		
        case GET_SECTOR_SIZE:
    	*(DWORD*)buff = FMC_SECTOR_SIZE;
            break;
    		
        case GET_SECTOR_COUNT:
    	*(DWORD*)buff =  FLASH_PAGE_NBR;
    	break;
    			
        default:
    	res = RES_PARERR;
    	break;
        }
        return res;
      /* USER CODE END IOCTL */
    }
    #endif /* _USE_IOCTL == 1 */
    
    
    

    main函数初始化

    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
        char path[4]= {"0:"};
        FRESULT FATFS_Status;	
      /* 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_FATFS_Init();
      MX_USB_DEVICE_Init();
      /* USER CODE BEGIN 2 */
        FATFS_Status = f_mount(&USERFatFS, path, 1);
        f_mkdir("0:/FW");
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    

    插上USB实验效果



    新建一个TXT文档:

    《SPI_SD卡》——U盘

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 CubeMX USB_MSC(U盘存储设备)配置指南

    发表评论