(3)STM32 USB设备开发-USB存储设备

例程:STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com

本篇为使用芯片内部flash作为USB存储设备的例程,没有知识,全是实操,按照步骤就能获得一个STM32的U盘。本例子是在野火F103MINI开发板上验证的,如果代码中出现一些外设的配置,可以参考野火F103MINI开发板原理图对照。

设置外部晶振,必须要使用外部晶振,因为USB控制器需要48M的系统时钟,内部晶振无法倍频出48M。

配置外部时钟

配置调试口和系统基准源

开启USB设备

中间件中设备USB设备类型

标蓝色的部分需要根据你之前有没有使用过这两VID和PID,如果使用过最好换一下,避免使用之前的驱动引起一些奇奇怪怪的问题。

STM32扇区大小如下

Flash大小为64KB ,单个扇区大小:1KB=0x400;Flash大小为128KB,单个扇区大小:1KB=0x400;

Flash大小为256KB,单个扇区大小:2KB=0x800;Flash大小为512KB,单个扇区大小:2KB=0x800;

STM32容量划分

大容量:256-512k的Flash,主要为:STM32F103xC, STM32F103xD,STM32F103xE

中容量:64-128k的Flash,主要为:STM32F103x8 STM32F103xB

小容量:16-32k的Flash,主要为:STM32F103x4 STM32F103x6

如果你使用的是大容量,MSC_MEDIA_PACKET需要配置为2048,如果不是大容量设备这里需要配置为1024

我使用了freertos v2

配置外部系统时钟

分配较大的堆栈空间,使U盘读写转存更快

配置独立C和H文件

代码需要修改如下:

首先我们需要知道代码使用了多大,我们需要使用没有被使用的那部分flash

我们把我们代码编译后会看到编译信息,

text 代码和常量

data 初始化的全局变量

bss 未初始化的变量

dec 就是前面三个的加和

我们可以使用Build Analyzer查看已经使用的flash

其实就是text+data=48,832=47.6875KB

所以我们需要使用48KB之后的flash,我们这里使用60KB之后的flash

/* USER CODE BEGIN PRIVATE_DEFINES */
//这里定义读写的FLASH起始地址和大小
#define FLASH_START_NBR 0x0800F000 // 从60K地址开始
#define FLASH_PAGE_NBR 100  // 100k
/* USER CODE END PRIVATE_DEFINES */

其中F000就是60KB,0x08000000是flash起始地址。

简单讲解几个重要函数

static int8_t STORAGE_Init_FS(uint8_t lun);

存储的初始化函数,如果有SD卡或者片外FLASH初始化可以放在这里。

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);

设备是否是写保护,类似于大的SD卡边上的小卡扣,如果是写保护则没有写权限;

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);

存储写函数;

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; //  块数量为100
  *block_size = FLASH_PAGE_SIZE; //  块大小为2048字节
  return (USBD_OK);
  /* USER CODE END 3 */
}

FLASH_PAGE_SIZE宏是STM32固件库提供的,如果是大容量就是2k

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) { //  如果lun为0,则将FLASH_BLK_NBR + blk_addr * FLASH_BLK_SIZ地址处的数据复制到buf中,长度为blk_len * FLASH_BLK_SIZ字节
    memcpy(buf, (uint8_t*) (FLASH_START_NBR + blk_addr * FLASH_PAGE_SIZE), blk_len * FLASH_PAGE_SIZE);
    return USBD_OK;
  }
  return (USBD_FAIL);
  /* 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 */
  if (lun == 0) {          //  如果lun为0,则执行以下操作
    uint16_t i;          //  定义一个变量i
    HAL_FLASH_Unlock();  //  解锁Flash

    FLASH_EraseInitTypeDef f;                                  //  定义一个结构体f,用于存储擦除Flash的参数
    f.TypeErase = FLASH_TYPEERASE_PAGES;                       //  设置擦除类型为页擦除
    f.PageAddress = FLASH_START_NBR + blk_addr * FLASH_PAGE_SIZE;  //  设置要擦除的页地址
    f.NbPages = blk_len;                                       //  设置要擦除的页数
    uint32_t PageError = 0;                                    //  定义一个变量PageError,用于存储擦除错误信息
    HAL_FLASHEx_Erase(&f, &PageError);                         //  执行擦除操作

    for (i = 0; i < blk_len * FLASH_PAGE_SIZE; i += 4)  //  循环写入数据到Flash中
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_START_NBR + blk_addr * FLASH_PAGE_SIZE + i,
                          *(uint32_t *)(&buf[i])); //  将buf中的数据写入到Flash中

    HAL_FLASH_Lock();  //  锁定Flash
  }
  return (USBD_OK);  //  返回USBD_OK
  /* USER CODE END 7 */
}

至此可以下载程序了,下载好后第一次接入电脑需要格式化U盘,格式化之后就可以正常使用了。

因为我这里还有200多KB的空闲,所以我可以分配200KB的flash。

相关推荐
为也科技26 分钟前
PID 控制算法(二):C 语言实现与应用
c语言·开发语言·单片机
mucheni33 分钟前
迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-接口函数
嵌入式硬件
Kisorge3 小时前
【电机控制器】FM33LF015芯片——IO口模拟串口
stm32·单片机·嵌入式硬件
隼玉4 小时前
【STM32-学习笔记-15-】MAX7219点阵屏模块
c语言·笔记·stm32·学习
番茄老夫子4 小时前
stm32 L051 adc配置及代码实例解析
stm32·单片机·嵌入式硬件
7yewh5 小时前
MCU、MPU、SOC、ECU、CPU、GPU的区别到底是什么
linux·arm开发·驱动开发·单片机·嵌入式硬件·物联网
7yewh7 小时前
嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础
arm开发·stm32·单片机·嵌入式硬件·mcu·物联网
exp_add311 小时前
三、SysTick系统节拍定时器
单片机·嵌入式硬件·lpc1114
Uitwaaien5414 小时前
51单片机之矩阵键盘
单片机·嵌入式硬件·51单片机