(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;          //  定义一个变量iHAL_FLASH_Unlock();  //  解锁FlashFLASH_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.rhkb.cn/news/5489.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

雷电9最新版安装Magisk+LSPosd(新手速通)

大家好啊&#xff01;我是NiJiMingCheng 我的博客&#xff1a;NiJiMingCheng 在安卓系统的定制与拓展过程中&#xff0c;获取 ROOT 权限以及安装各类框架是进阶玩家常用的操作&#xff0c;这可以帮助我们实现更多系统层面的个性化功能。今天&#xff0c;我将为大家详细介绍如何…

2025 OWASP十大智能合约漏洞

随着去中心化金融&#xff08;DeFi&#xff09;和区块链技术的不断发展&#xff0c;智能合约安全的重要性愈发凸显。在此背景下&#xff0c;开放网络应用安全项目&#xff08;OWASP&#xff09;发布了备受期待的《2025年智能合约十大漏洞》报告。 这份最新报告反映了不断演变的…

55.【5】BUUCTF WEB NCTF2019 sqli

进入靶场 输入admin 123 过滤的这么严格&#xff1f;&#xff1f;&#xff1f; 过滤很严格&#xff0c;此时要么爆破&#xff0c;要么扫描 直接扫描&#xff0c;得到robots.txt 访问后又得到hint.txt 继续访问 图片内容如下 $black_list "/limit|by|substr|mid|,|admi…

map和set的使用(一)详解

文章目录 序列式容器和关联式容器map和set的介绍set构造和迭代器遍历和insertfinderaseswapclearcountlower_bound和upper_boundmultiset和set的对比 set的二个题目题目解析算法原理代码介绍一个找差集的算法同步算法题目解析算法原理代码 map构造遍历initiaizer_list 序列式容…

初始SpringBoot:详解特性和结构

??JAVA码农探花&#xff1a; ?? 推荐专栏&#xff1a;《SSM笔记》《SpringBoot笔记》 ??学无止境&#xff0c;不骄不躁&#xff0c;知行合一 目录 前言 一、SpringBoot项目结构 1.启动类的位置 2.pom文件 start parent 打包 二、依赖管理特性 三、自动配置特性…

服务器日志自动上传到阿里云OSS备份

背景 公司服务器磁盘空间有限&#xff0c;只能存近15天日志&#xff0c;但是有时需要查看几个月前的日志&#xff0c;需要将服务器日志定时备份到某个地方&#xff0c;需要查询的时候有地方可查。 针对这个问题&#xff0c;想到3个解决方法&#xff1a; 1、买一个配置比较低…

【HarmonyOS NEXT】华为分享-碰一碰开发分享

关键词&#xff1a;鸿蒙、碰一碰、systemShare、harmonyShare、Share Kit 华为分享新推出碰一碰分享&#xff0c;支持用户通过手机碰一碰发起跨端分享&#xff0c;可实现传输图片、共享wifi等。我们只需调用系统 api 传入所需参数拉起对应分享卡片模板即可&#xff0c;无需对 U…

C语言——文件操作

目录 前言 一什么是文件 1程序文件 2数据文件 3文件名 二文件的打开与关闭 1文件指针 2fopen 3fclose 三文件的读与写 1文件的顺序读写 1.1fputc fgetc 1.2fputs fgets 1.3fprintf fscanf 1.4fwrite fread 1.5文本文件和二进制文件 2文件的任意读写 1fseek …

亚博microros小车-原生ubuntu支持系列:1 键盘控制

背景&#xff1a;电脑配置不太行&#xff0c;我在ubuntu再运行vmware&#xff0c;里面运行亚博官方的虚拟机镜像ubuntu&#xff0c;系统很卡。基本上8G内存给打满了。还是想把亚博官方的代码迁移出来&#xff0c;之前售后就说除了官方镜像虚拟机&#xff0c;需要自己摸索迁移。…

基于Redis实现短信验证码登录

目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …

Golang Gin系列-4:Gin Framework入门教程

在本章中&#xff0c;我们将深入研究Gin&#xff0c;一个强大的Go语言web框架。我们将揭示制作一个简单的Gin应用程序的过程&#xff0c;揭示处理路由和请求的复杂性。此外&#xff0c;我们将探索基本中间件的实现&#xff0c;揭示精确定义路由和路由参数的技术。此外&#xff…

Asp.Net Core 8.0 使用 Serilog 按日志级别写入日志文件的两种方式

1、所需的Nuget包 本文项目的版本是.NET 8.0&#xff0c;如果使用其它版本安装适配版本即可。 Serilog.AspNetCore(8.0.2) Serilog.Sinks.File(5.0.0) Serilog.Expressions(5.0.0) 2、两种配置方式 2.1 代码形式&#xff08;Program.cs&#xff09; 在Program.cs文件中&am…

STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态

STM32W5500以太网应用开发003_TCP服务器添加OLED&#xff08;u8g2&#xff09;显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…

【深度学习项目】语义分割-DeepLab网络(DeepLabV3介绍、基于Pytorch实现DeepLabV3网络)

文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 DeepLabDeepLab 的核心技术DeepLab 的发展历史DeepLab V3网络结构获取多尺度信息架构Cascade ModelASPP ModelMulti-GridPytorch官方实现的DeepLab V3该项目主要是来自pytorch官方torchvision模块中…

Golang Gin系列-5:数据模型和数据库

在这篇Gin教程的博客中&#xff0c;我们将探索如何将模型和数据库与Gin框架无缝集成&#xff0c;使你能够构建健壮且可扩展的web应用程序。通过利用流行的库并遵循最佳实践&#xff0c;你将学习如何定义模型、建立数据库连接、执行CRUD操作以及确保基于gin的项目中的数据完整性…

高并发内存池_各层级的框架设计及ThreadCache(线程缓存)申请内存设计

一、高并发内存池框架设计 高并发池框架设计&#xff0c;特别是针对内存池的设计&#xff0c;需要充分考虑多线程环境下&#xff1a; 性能问题锁竞争问题内存碎片问题 高并发内存池的整体框架设计旨在提高内存的申请和释放效率&#xff0c;减少锁竞争和内存碎片。 高并发内存…

如何在idea中搭建SpringBoot项目

如何在idea中快速搭建SpringBoot项目 目录 如何在idea中快速搭建SpringBoot项目前言一、环境准备&#xff1a;搭建前的精心布局 1.下载jdk &#xff08;1&#xff09;安装JDK&#xff1a;&#xff08;2&#xff09;运行安装程序&#xff1a;&#xff08;3&#xff09;设置安装…

elementUI Table组件实现表头吸顶效果

需求描述 当 table 内容过多的时候&#xff0c;页面上滑滚动&#xff0c;表头的信息也会随着被遮挡&#xff0c;无法将表头信息和表格内容对应起来&#xff0c;需要进行表头吸顶 开始编码&#x1f4aa; 环境&#xff1a;vue2.6、element UI step1&#xff1a; 给el-table__h…

[Qt]系统相关-多线程、线程安全问题以及线程的同步机制

目录 一、Qt多线程编程 1.介绍 2.多线程的操作 线程的创建 QThread的常用API 使用案例 3.Qt线程的使用场景 二、线程安全问题 1.互斥锁 介绍 使用案例 2.读写锁 三、线程的同步 1.条件变量 2.信号量 一、Qt多线程编程 1.介绍 Qt中的多线程的底层原理和注意事项…

Linux Bash 中使用重定向运算符的 5 种方法

注&#xff1a;机翻&#xff0c;未校。 Five ways to use redirect operators in Bash Posted: January 22, 2021 | by Damon Garn Redirect operators are a basic but essential part of working at the Bash command line. See how to safely redirect input and output t…