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

news2025/1/24 4:12:58

例程: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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2281200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

细说STM32F407单片机电源低功耗StopMode模式及应用示例

目录 一、停止模式基础知识 1、进入停止模式 2、停止模式的状态 3、退出停止模式 4、SysTick定时器的影响 二、停止模式应用示例 1、示例功能和CubeMX项目配置 &#xff08;1&#xff09;时钟 &#xff08;2&#xff09;RTC &#xff08;3&#xff09;ADC1 &#xf…

Blazor-Blazor WebAssmbly项目结构(上)

创建项目 今天我们来创建一个BlazorWebAssmbly项目&#xff0c;来看看项目结构是如何得&#xff0c;我们创建带模板得项目&#xff0c;会创建出一个demo&#xff0c;来看看项目结构。 创建的项目可以直接启动运行&#xff0c;首次启动会看见加载的过程&#xff0c;这个过程…

【2024年终总结】我与CSDN的一年

&#x1f449;作者主页&#xff1a;心疼你的一切 &#x1f449;作者简介&#xff1a;大家好,我是心疼你的一切。Unity3D领域新星创作者&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6; &#x1f449;记得点赞 &#x1f44d; 收藏 ⭐爱你们&#xff0c;么么哒 文章目录 …

开篇:吴恩达《机器学习》课程及免费旁听方法

课程地址&#xff1a; Machine Learning | Coursera 共包含三个子课程 Supervised Machine Learning: Regression and Classification | Coursera Advanced Learning Algorithms | Coursera Unsupervised Learning, Recommenders, Reinforcement Learning | Coursera 免费…

推荐一个开源的轻量级任务调度器!TaskScheduler!

大家好&#xff0c;我是麦鸽。 这次推荐一款轻量级的嵌入式任务调度器&#xff0c;目前已经有1.4K的star&#xff0c;这个项目比较轻量化&#xff0c;只有5个源文件&#xff0c;可以作为学习的一个开源项目。 核心文件 项目概述&#xff1a; 这是一个轻量级的协作式多任务处理&…

暑期实习准备:C语言(持续更新)

1.局部变量和全局变量 局部变量的作用域是在变量所在的局部范围&#xff0c;全局变量的作用域是整个工程&#xff1b;局部变量的生命周期是作用域内&#xff0c;全局变量的生命周期是整个程序的生命周期&#xff0c;当两者命名冲突时&#xff0c;优先使用的是局部变量。 2.C语言…

Harmony Next 支持创建分身

应用分身能实现在一个设备上安装多个相同的应用&#xff0c;实现多个账号同时登录使用和运行并且互不影响。主要应用场景有社交账号双开、游戏大小号双开等&#xff0c;无需账号切换&#xff0c;从而省去频繁登录的繁琐。 Harmony Next 很容易就能让 App 支持创建分身。 官方文…

java ,springboot 对接支付宝支付,实现生成付款二维码,退款,查询订单状态等接口

查看文档 支付宝文档地址&#xff1a; 小程序文档 - 支付宝文档中心 使用沙箱环境 沙箱登录地址 登录 - 支付宝 点击查看 才能看钥匙截图写错了。。 问号可以看默认加密方式 点击沙箱帐号 这里我们就具备所有条件了 实战开始 pom文件增加依赖 <dependency> <gro…

深入内核讲明白Android Binder【三】

深入内核讲明白Android Binder【三】 前言一、服务的获取过程内核源码解析1. 客户端获取服务的用户态源码回顾2. 客户端获取服务的内核源码分析2.1 客户端向service_manager发送数据1. binder_ioctl2. binder_ioctl_write_read3. binder_thread_write4. binder_transaction4.1 …

chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确

问题描述 chrome游览器又一款JSON插件叫JSON Formatter&#xff0c;游览器GET请求调用接口时&#xff0c;如果返回的数据是json格式&#xff0c;则会自动格式化展示&#xff0c;类似这样&#xff1a; 但是今天突然发现怎么也格式化不了&#xff0c;打开一个json文件倒是可以格…

canvas基础

今天我们简单的来认识学习一下canvas的基础概念和使用方法。 1. 认识canvas 1.1 什么是canvas 在网页开发中&#xff0c;canvas是html5中的一个元素&#xff0c;用于通过JavaScript绘制图形。它可以用来制作简单的图表、动画和游戏等。 1.2. 使用场景 游戏开发&#xff1a…

OneData体系架构详解

阿里巴巴的 OneData 体系架构方法论&#xff0c;主要分为三个阶段&#xff1a;业务板块、规范定义 和 模型设计。每个阶段的核心目标是确保数据的高效管理、共享与分析能力。 一. 业务板块&#xff08;Business Segment&#xff09; 业务板块是OneData体系架构中的第一步&…

【C++】哈希表的使用

unordered_map/unordered_set 这是C11才新增的两个容器 原本觉得avl树和红黑树效率已经够了。 后来探索和觉得哈希还是有必要加进来的。 JAVA里面是这样取名的&#xff1a; unordered_set unordered_map/set与map/set的功能基本一致&#xff0c;但细节上有所不同&#x…

微信小程序1.1 微信小程序介绍

1.1 微信小程序介绍 内容提要 什么是微信小程序 微信小程序的功能 微信小程序使用场景 微信小程序能取代App吗 微信小程序的发展历程 微信小程序带来的机会

前端Vue2项目使用md编辑器

项目中有一个需求&#xff0c;要在前端给用户展示内容&#xff0c;内容有 AI 生成的&#xff0c;返回来的是 md 格式&#xff0c;所以需要给用户展示 md 格式&#xff0c;并且管理端也可以编辑这个 md 格式的文档。 使用组件库 v-md-editor。 https://code-farmer-i.github.i…

26、正则表达式

目录 一. 匹配字符 .&#xff1a;匹配除换行符外的任意单个字符。 二. 位置锚点 ^&#xff1a;匹配输入字符串的开始位置。 $&#xff1a;匹配输入字符串的结束位置。 \b&#xff1a;匹配单词边界。 \B&#xff1a;匹配非单词边界。 三. 重复限定符 *&#xff1a;匹配…

K8S中Service详解(一)

Service介绍 在Kubernetes中&#xff0c;Service资源解决了Pod IP地址不固定的问题&#xff0c;提供了一种更稳定和可靠的服务访问方式。以下是Service的一些关键特性和工作原理&#xff1a; Service的稳定性&#xff1a;由于Pod可能会因为故障、重启或扩容而获得新的IP地址&a…

【真机调试】前端开发:移动端特殊手机型号有问题,如何在电脑上进行调试?

目录 前言一、怎么设置成开发者模式&#xff1f;二、真机调试基本步骤&#xff1f; &#x1f680;写在最后 前言 edge浏览器 edge://inspect/#devices 谷歌浏览器&#xff08;开tizi&#xff09; chrome://inspect 一、怎么设置成开发者模式&#xff1f; Android 设备 打开设…

初探大数据流式处理

文章目录 初探大数据流式处理批式处理系统特点流式处理系统特点大批次计算微批次计算适用场景 流式计算的应用场景流式大数据的特征流式计算的关键技术流式处理框架的特征三大流式数据处理框架 初探大数据流式处理 大数据处理系统主要分为批式处理和流式处理两类。批式处理将大…

快速搭建深度学习环境(Linux:miniconda+pytorch+jupyter notebook)

本文基于服务器端环境展开&#xff0c;使用的虚拟终端为Xshell。 miniconda miniconda是Anaconda的轻量版&#xff0c;仅包含Conda和Python&#xff0c;如果只做深度学习&#xff0c;可使用miniconda。 [注]&#xff1a;Anaconda、Conda与Miniconda Conda&#xff1a;创建和管…