当前位置: 首页 > news >正文

STM32USB学习

STM32USB学习

  • 一、USB简介
    • 1.1 USB是什么?
    • 1.2 USB2.0拓扑结构
    • 1.3 USB2.0电气特性
    • 1.4USB学习资料
  • 二、STM32的USB介绍
    • 2.1 STM32的USB外设特性
    • 2.2 STM32USB外设框图
    • 2.3 开发板硬件连接
    • 2.4 STM32 ST USB驱动库简介
    • 2.5 SUB相关实验(探索者V3)
  • 三、USB读卡器(slave)实验
    • 步骤一 :查看ST官方的MSC例程
    • 步骤二:拷贝工程所需要的文件
    • 步骤三:SDK工程设置
    • 步骤四:修改usbd_storage.c文件
    • 步骤五:修改usbd_conf.c/h
    • 步骤6:修改usbd_msc.h文件
    • 步骤7:其它文件的scsi_blk_nbr变量改为数组。
    • 步骤8:修改main.c文件。
  • 四、USB声卡(slave)实验 1:37:11
  • 五、USB虚拟串口(slave)实验 提高篇下
  • 六、USBU盘(host)实验
    • 步骤1:查看ST官方的MSC例程
    • 步骤二:拷贝工程所需文件
    • 步骤三:MDK工程设置
    • 步骤四:修改usbh_conf.c/.h文件
    • 步骤五:修改usbh_diskio.c文件
    • 步骤六:修改diskio.c文件 以支持对U盘的访问
    • 步骤7:修改main.c文件
    • 测试:
  • 七、USB鼠标键盘(host)实验 1:07:33
  • 八、总结
  • 补充:文件系统FATFS
    • 基本概念与原理
      • FATFS基本入门详解
      • 什么是FATFS
      • 挂载文件系统
    • 文件操作接口的使用介绍
      • 打开与关闭文件
      • 文件的读取和写入
        • 读取
        • 写入文件
      • 以字符串的方式读文件 f_get函数
      • 以字符串的方式写文件 f_puts函数
      • 文件读写定位 f_lseek函数
      • 跳整写位置进行扩容
      • 获取文件信息
      • 判断是否以到达文件尾部
      • 截断文件
      • 为文件分配连续空间(FatFs的特有功能)
      • 读取转发数据
    • 目录与文件管理
      • 查询文件以及文件信息 f_stat函数
      • 遍历目录
      • 在目录中查找
      • 切换工作目录
      • 删除文件或目录
      • 创建目录
      • 更新文件属性
      • 更改当前驱动器
    • 卷管理与系统配置
      • 获取剩余空间
      • 设置和获取卷标

正点原子"手把手教你学STM32"教学视频,198-199讲学习记录。
视频地址:点这里

一、USB简介

1.1 USB是什么?

在这里插入图片描述

在这里插入图片描述

对外供电超过500ma时,需要外供电。
D+D-电压值应该为3V。
在这里插入图片描述
主控制器和根集线器的USB版本,决定总的带宽。加集线器之后,公用总的带宽。
在这里插入图片描述
一根线ID,决定本设备是主机还是从机。
电脑是主机。
手机是从机,但是也有主机的功能。
STM32可以是主机(读写U盘),也可以是从机(当作 电脑的鼠标)。

1.2 USB2.0拓扑结构

在这里插入图片描述
HUB也属于一个USB设备。
设备为1-127个。没有0。
一层之间的距离为5m,最大6层,所以最大支持30m。

1.3 USB2.0电气特性

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4USB学习资料

协议最麻烦。
正点原子开发板资料中有”USB学习资料“文件夹。
在这里插入图片描述
TI的DSPC2000中也提供了USB驱动库。
ST的USB库用于STM32。
在这里插入图片描述
探索者资料最全。

二、STM32的USB介绍

介绍STM32USB外设。

2.1 STM32的USB外设特性

具体特性需要看参考手册。
在这里插入图片描述

2.2 STM32USB外设框图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用内部的PHY芯片
在这里插入图片描述

在这里插入图片描述
使用内部的PHY芯片,外部ULPI PHY没接。

2.3 开发板硬件连接

在这里插入图片描述
TYPEC的从机接口。

2.4 STM32 ST USB驱动库简介

在这里插入图片描述
分device库和host库,里面有Class和core库。设备分类和核心代码。
在这里插入图片描述
在这里插入图片描述
看一下USB设备库的架构。

2.5 SUB相关实验(探索者V3)

在这里插入图片描述

三、USB读卡器(slave)实验

STM32USB外设作为从机。
以探索者V3 HAL库为例。
在这里插入图片描述
STM32USB外设作为从机连接电脑,当作读卡器,SD卡作为卡。
在这里插入图片描述

步骤一 :查看ST官方的MSC例程


注意:使用的是全速的FS,而不是HS。

步骤二:拷贝工程所需要的文件

将SD卡工程复制,粘贴,命名为读卡器实验。
、:”
一个磁盘是SD卡,另一个磁盘是SPI FLASH,所以还需要再拷贝SPI文件夹和NorFlash文件夹。

步骤三:SDK工程设置

工程结构
在这里插入图片描述
在这里插入图片描述

步骤四:修改usbd_storage.c文件

都是对usbd_storage.c文件进行修改的。
在这里插入图片描述第8步,最大逻辑单元个数为2个,一个SD卡,一个NORFLASH。看一下ST官方例程 和 读卡器例程,这个文件的区别。对比一下。关键修改1:
在这里插入图片描述
添加一个宏。
在这里插入图片描述

关键修改2:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关键修改3:
在这里插入图片描述
在这里插入图片描述
函数修改后。
在这里插入图片描述

关键修改4:
在这里插入图片描述
在这里插入图片描述
block_size扇区大小
block_num扇区数

关键修改5:
在这里插入图片描述
在这里插入图片描述

关键修改6:

在这里插入图片描述
在这里插入图片描述
关键修改7:
在这里插入图片描述
错误处理
在这里插入图片描述

关键修改8:
在这里插入图片描述
按需修改即可。
STORAGE_LUN_NBR为宏 标志最大支持设备数。
在这里插入图片描述

步骤五:修改usbd_conf.c/h

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面是修改各种回调函数,在usbd_conf.c文件中。

步骤6:修改usbd_msc.h文件

完成步骤5,读卡器功能就可以实现了。
完成步骤6,使功能更全面。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

步骤7:其它文件的scsi_blk_nbr变量改为数组。

完成步骤6之后,调用相关变量的地方,也需要做相应修改。
在这里插入图片描述
在这里插入图片描述
其余函数位置做类似修改。

步骤8:修改main.c文件。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、USB声卡(slave)实验 1:37:11

STM32USB外设作为从机。
以探索者V3 HAL库为例。

五、USB虚拟串口(slave)实验 提高篇下

STM32USB外设作为从机。
以探索者V3 HAL库为例。

六、USBU盘(host)实验

STM32USB外设作为主机。
以探索者V3 HAL库为例。
在这里插入图片描述

步骤1:查看ST官方的MSC例程

在这里插入图片描述

步骤二:拷贝工程所需文件

在这里插入图片描述

步骤三:MDK工程设置

在这里插入图片描述

步骤四:修改usbh_conf.c/.h文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
就是一个IO控制三级管/MOS管,从而控制给U盘供电。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
之前USB作为从机,没有供电选择这一步。

在这里插入图片描述
正点没有修改许多子回调函数,只是在ST官方例程中添加了printf的提示信息。
在这里插入图片描述
下面这里不需要控制VBUS所以未实现。
在这里插入图片描述

步骤五:修改usbh_diskio.c文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这些读写U盘的函数,可以去查看前面提到的"主机库""设备库"的两个文件。
在这里插入图片描述

步骤六:修改diskio.c文件 以支持对U盘的访问

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

步骤7:修改main.c文件

在这里插入图片描述
看一下main.c的文件。

没讲FATFS文件系统。

测试:

借助USMART进行测试。
USMART 是由 ALIENTEK 开发的一个灵巧的串口调试互交组件,通过它你可以通过串口助手调用程序里面的任何函数,并执行。
具体说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开文件测试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、USB鼠标键盘(host)实验 1:07:33

STM32USB外设作为主机。
以探索者V3 HAL库为例。

八、总结

补充:文件系统FATFS

视频地址:
层次化结构、目录和文件、文件属性、数据组织。
嵌入式常用的文件系统有:FAT16、FAT32。

基本概念与原理

FATFS基本入门详解

在这里插入图片描述

FAT16、FAT32在簇方面有差异

在这里插入图片描述
SD卡,U盘等存储介质最小存储介质为块/扇区,英文为block。

在这里插入图片描述
在这里插入图片描述
加载文件系统时,会从保留区获取文件系统的一些信息,包括整个存储介质扇区的数量和大小。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

什么是FATFS

FatFs来源于"文件分配表(File Allocation Table)",以ANSI C(C89)规范编写,并且完全独立于磁盘IO层,具备跨平台移植性。
可以集成在资源有限的小型嵌入式微控制器中,如8051、ARM等。
还提供了适用于微小型微控制器的Petit FatFs,裁剪后的FatFs。
在这里插入图片描述
在这里插入图片描述
使用宏,裁剪文件系统的空间占用大小。
在这里插入图片描述
在这里插入图片描述

挂载文件系统

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如何使用这个接口???
这个教程在电脑磁盘中虚拟创建一个磁盘,然后使用Vs,写挂载虚拟磁盘的程序。并不是嵌入式应用的。简单学习一下移植方法。
再对比正点的源码看看。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述## 取消挂载文件系统
在这里插入图片描述
在这里插入图片描述
一个数组存了虚拟磁盘的路径,0对应数组的第一个元素,也就是第一个磁盘,1对应数组的第二个元素。
感兴趣可以看一下f_mount的内部实现。
先挂载文件系统,才能对SPI FLASH等存储介质进行文件操作。

文件操作接口的使用介绍

打开与关闭文件

标准C语言中使用f_Open函数打开文件。
Fatfs也是类似,使用f_Open函数,两者函数名字相同。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
关闭文件使用f_close函数,直接传入参数即可。
在这里插入图片描述

看了一部分视频,发现大多是对一些函数的解释和操作,所以减少记录。
只记录重点内容。

文件的读取和写入

读取

在这里插入图片描述
在这里插入图片描述
读文件测试:

在标准C语言中,f_open打开文件时,会有记录文件位置的指针offset,刚打开时offset为0,指向文件的最开始位置。
f_write写10个字节,offset变为10.
在fatfs文件系统中,也有该指针记录文件的位置。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写入文件

有时,数据会先存在RAM中,需要的时候再写入到驱动器,此时如果出现断电(或程序崩溃)的情况,就会产生数据丢失的现象。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
模拟程序运行中崩溃,导致数据丢失的现象。
在这里插入图片描述
在这里插入图片描述
查看生成的文件。
文件大小为0,没有任何数据,但是i已经是5000,f_write已经执行了5000次,所以期望结果是有0-4999行的数据。这些数据在程序崩溃的时候,都丢了。
实际,f_wriite在写入的时候,会将一些信息缓存到FIL,FATFS类型的结构体变量中,实际在RAM中,易丢失。
在这里插入图片描述
因为程序提前崩溃,所以没有正确执行f_close文件,导致关于文件占用空间大小的一些信息,没有写入到驱动器。
所以显示文件大小为零。

实际可能5000次的内容已经写入到了驱动器,每次执行f_write就已经把内容写到了磁盘,但是没有执行f_close,导致没有将文件属性(大小 日期等)相关的信息写入到驱动器,即文件不完整,所以文件的大小为0.。
FIL,FATFS类型的结构体变量有一部分缓存,这部分在突然停机、掉电等情况下,数据会丢掉。

在这里插入图片描述
使用f_sync。

O代表打开文件
W代表写入文件
C代表关闭文件
S代表SYNC
下面的图片中有介绍

在这里插入图片描述
崩溃前使用f_syns函数执行同步。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

标准C语言中,fflush函数与f_close函数作用类似。
在这里插入图片描述

以字符串的方式读文件 f_get函数

前面都是以二进制(字节)的方式进行文件操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Tchar类型,根据不同情况,为char 或者 wchar。具体需要查一下。
在这里插入图片描述
在这里插入图片描述
f_gets一次读一行 效率低一些(不应该高一些吗?) 但使用方便
f_read一次读一个字节

在这里插入图片描述
在这里插入图片描述
不同系统下对回车换行操作的具体区别

f_gets的配置项
在这里插入图片描述

以字符串的方式写文件 f_puts函数


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

f_puts函数添加字符串,没有在最后添加换行符
C标准f_puts函数,在控制台打印字符串会添加换行符。
所以
在这里插入图片描述

同样的,f_puts函数写入时,也有宏开关,控制\n是否转换为\r\n。
与f_gets函数的转换相反。

查看c文件内部的字节 情况
这里是引用
在这里插入图片描述
在这里插入图片描述

文件读写定位 f_lseek函数

在这里插入图片描述
移动指针到任意文件位置
在这里插入图片描述
移动指针到任意文件开头
在这里插入图片描述
在这里插入图片描述

跳整写位置进行扩容

在这里插入图片描述
在这里插入图片描述
使用f_lseek函数对文件指针进行偏移,使文件大小得到扩充。
相当于划分了一部分存储器/磁盘的空间,给了这个文件。
内容不确定,原来磁盘位置上是什么内容,扩充后的内容就是什么。

获取文件信息

分两类:获取文件的大小和位置;获取文件的名称和属性等。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

判断是否以到达文件尾部

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

截断文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
想要将文件内容清空时,
方式1:删除文件 重新创建新的文件。
方式2:可以将文件指针定位到0,然后截断。

为文件分配连续空间(FatFs的特有功能)

对文件读写性能有要求,可以使用。
一个文件存在于数据区的不同簇中,如果簇在存储空间中不连续,则读写效率较低。
如果一个文件的簇,在存储空间中连续,则读写效率高。

下图不连续时,写的步骤为:先写,查找下一个簇,再写,再查找下一个簇。

在这里插入图片描述
FatFs可以在创建文件时,可以设定文件的大小,同时要求文件在一段连续的簇中存储。

在这里插入图片描述
在这里插入图片描述

这里是引用
在这里插入图片描述

在这里插入图片描述
代码示例
在这里插入图片描述
在这里插入图片描述

注:字节数 / 扇区大小 = 扇区的数量 作为形参传进去。
磁盘所在的驱动器号(一个驱动器 可以控制多个磁盘)。

前面用f_write执行写数据,内部的底层实现也是调用了disk_write函数(内部调用多次disk_write函数)。
f_write内部可以执行查扇区号、写数据、查扇区号、写数据。。。
如果文件连续存储,可以直接调用底层的disk_write函数,连续写,只调用一次。更高效。
disk_write函数在diskio.c文件中。

在这里插入图片描述

使用disk_write函数的缺点:
需要使用一些变量计算驱动器号参数,文件所在扇区号。(计算过程较难理解,涉及FatFs的存储原理)
这些变量在不同版本的FatFs中,可能变化,从而需要修改计算的代码。
即FatFs版本升级,导致代码用不了了。

连续读用disk_read函数。

使用f_expand函数的注意事项:
1 使用f_expand扩充文件时,原文件必须无内容。(一般对刚打开的文件进行扩充)
如果有内容,无法使原来内容的存储位置,与扩充的存储位置连续起来。
2 使用f_expand扩充文件为100kb的连续空间,再用f_write函数在文件的末尾写10kb的内容。
这时文件大小为100kb + 10kb。这10kb的内容与100kb的内容,可能连续,也可能不连续。
需要注意这个问题。
在这里插入图片描述
不一定成功,20MB空闲空间,但不一定是连续的,f_expand函数必须找连续的空间扩充。

读取转发数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

f_read函数要求传入RAM缓存,而使用FIL结构体类型的内部缓存区,可以不需要使用f_read函数先将文件内容读到RAM数组缓冲区,再f_write将缓冲区内容写到其它存储介质。
使用f_forward函数,直接将一个存储介质中的文件内容,通过串口/SPI/IIC等接口发送数据(十六进制的数据)。

在这里插入图片描述

函数实现框架
在这里插入图片描述

在这里插入图片描述

目录与文件管理

查询文件以及文件信息 f_stat函数

f_stat函数不要求打开文件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

遍历目录

有一个目录,将目录下的子目录/子文件逐条打印出来。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

上图 最后一行 时间应右移11 少了>

在上面的图片上补充,添加遍历目录完成的代码。
在这里插入图片描述
在这里插入图片描述

在window中,在目录中,可以按大小、名称、修改时间等设置不同的文件展示顺序。
但是在Fatfs中,f_readdir函数读到的目录/文件属性,排列顺序是固定的。
即上图中运行结果的排列顺序,与文件名、大小、日期、时间没有任何关系。
应该是按文件在存储介质中实际的存储地址顺序有关。

在这里插入图片描述
在这里插入图片描述

在目录中查找

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

切换工作目录

在这里插入图片描述
在这里插入图片描述
前面是绝对路径,后面是相对路径。

删除文件或目录

删除文件
在这里插入图片描述

在这里插入图片描述
删除目录 有注意事项
f_unlink函数仅支持删除空的目录。
f_unlink函数无法删除当前目录。
如果目录下有子目录,或者目录下有文件,则f_unlink无法删除。
如果想删除非空的目录,需要自己写函数实现,递归删除目录下的所有目录/文件,再删除该目录。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建目录

只能单层创建目录。
在这里插入图片描述
在这里插入图片描述
执行自然会创建成功。
在这里插入图片描述

更新文件属性

更改文件名、属性(只读、隐藏等)等。
本节三个内容
修改属性
修改名称
修改最后修改时间

修改属性:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

修改名称:
f_rename函数可以实现:
1 重命名
2 移动文件 并改名
3 移动目录 并改名
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改时间戳:
在这里插入图片描述

更改当前驱动器

类似盘符。前面用到的0: 1:。
只挂载一个磁盘时,使用函数时,则不需要0:。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

卷管理与系统配置

获取剩余空间

在这里插入图片描述
在这里插入图片描述
注:上面printf应该是%f
在这里插入图片描述

f_getfree函数内部是循环扫描 FAT表,获取当前剩余簇的数量。效率较低。

可以优化:
FATFS有一段数据区,专门记录空闲的簇,直接读取,效率最高。
FSinfo 扇区结构体(FAT英文白皮书)
在这里插入图片描述
有时使用FSinfo 函数扫描耗时,但是准确率高。

在这里插入图片描述

设置和获取卷标

嵌入式开发中,用的少,基本用不上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DiskGenius软件,查看磁盘的文件。
在这里插入图片描述

设置为小写,但是显示大写。原因?
看下FatFs文件结构体简介,
DISK AA存在磁盘的一部分存储区.
大小写不需要关心.
应该是在代码中存的时候,以大写方式存的.

http://www.dtcms.com/a/515396.html

相关文章:

  • coze使用记录
  • java面试-0220-HashSet、LinkedHashSet、TreeSet实现?和ArrayList区别?
  • 2、WordPress使用--安装gutenverse插件
  • 南和县建设局黄页网站设计之窗
  • NetworkX 最短路径算法选型图
  • 互联网公司软件开发全流程规范文档
  • springboot基于JAVA的二手书籍交易系统的设计与实现(代码+数据库+LW)
  • STM32产品程序测试完整指南
  • AWS Data Exchange:概述、功能与安全性
  • 掌控制造脉络:电子元器件行业常用ERP系统概览与参考指南
  • 个人网站静态网页模板海淀区网站建设
  • 低代码开发的约束性及ABP框架的实践解析
  • centos7部署jenkins
  • 软文街官方网站如何提升做网站的效率
  • 【论文精读】GenTron:基于 Transformer 的扩散模型革新图像与视频生成
  • 【RabbitMQ】简介
  • (done) 自学 MPI (4) Environment Management Routines
  • webrtc弱网-RembThrottler类源码分析及算法原理
  • 鸿蒙的声明式 UI转换为 JSView
  • 【MySQL】从零开始了解数据库开发 --- 如何理解事务隔离性
  • BugKu Web渗透之 never_give_up
  • Cangjie语言核心技术深度解析测评:迈进鸿蒙原生开发的安全新时代!
  • 长乐市住房和城乡建设局网站网站开发公司的推广费用
  • 绵阳住房和城乡建设部网站网站页面优化怎么做
  • 关于git的使用(在gitee和gitcode上部署自己的项目流程)
  • PHP 字符串操作详解
  • 3合一网站怎么做免费数据统计网站
  • 17.基础IO_3
  • Ubuntu 系统掉电导致分区损坏无法启动修复方案
  • 相机模组,模组是什么意思?