STM32下USB的使用

作者:@登云上人间

目录

一、介绍
USB 系统组成
USB 通讯
USB主机
端点
二、STM32F407下USB介绍
时钟
三、 demo移植
demo移植步骤
usb核心代码刨析
1. USB 驱动代码
2. main.c 代码

一、介绍

  • USB,即通用串行总线(Universal Serial Bus),包括 USB 协议和 USB 硬件两个方面,支持热插拔功能

  • USB2.0 使用四根线:VCC(5V)、GND、D+(3.3V)和 D-(3.3V) (注:五线模式多了一个DI 脚用于支持 OTG 模式,OTG 为 USB 主机+USB 设备双重角色)

  • USB 主机上,D-和 D+都接 15K 的电阻到地,在没有设备接入的时候,D+、D-均是低电平。在 USB 设备中,如果是高速设备,则在D+上接一个1.5K的电阻到 3.3V,如果是低速设备,则在 D-上接一2023-07-06 18:05:27 星期四个1.5K 的电阻到 3.3V。当设备接入主机时,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。

  • USB 规范四种速度模式:低速(Low-Speed)、全速(Full-Speed)、高速(Hi-Speed)和超高(SuperSpeedUSB)。

USB 系统组成

  • USB 系统主要包括三个部分:控制器(Host Controller)、集线器 (Hub) 和 USB 设备

  • 控制器(Host Controller), USB主机有一个或多个控制器,负责执行由控制器驱动程序发出的命令

  • 控制器驱动程序(Host Controller Driver)在控制器与 USB 设备之间建立通信信道。

  • 集线器(Hub)连接到 USB 主机的根集线器,用于拓展主机可访问的 USB 设备的数量。

  • USB 设备(USB Device)是受主机控制的设备。常用的如 U 盘,USB 鼠标这类

USB 通讯

USB 系统通过“管道”进行通讯,有“控制管道”和“数据管道”两种,“控制管道”是双向的,“数据管道”则是单向的

USB主机

  • 检测和断开总是由主机发起

  • USB 主机与设备进行连接时交换信息的过程“USB 枚举”

  • 枚举过程主机需要分配设备地址、读取描述符(作为提供有关设备信息的数据结构),并分配和加载设备驱动程序(主机操作)

  • 从机提供相应的描述符使主机知悉如何操作此设备(从机操作)

  • 枚举过程需要数秒时间,枚举过程完成后才可以进行数据传输。

  • 数据传输规定的三种类型IN/读取/上行数据传输、OUT/写入/下行数据传输、控制数据传输。

    • IN = 读取 = 上行
    • OUT = 写入 = 下行

端点

  • USB 通过设备 端点 寻址,在主机和设备间实现信息交流

  • 控制端点或端点 0: 枚举发生前专用于与设备进行通信的端点。有端点 0 IN 和端点 0 OUT 两个不同的端点,每一个 USB 设备都需要支持端点 0。端点 0 不需要使用独立的描述符。

  • 特定设备所支持的端点数量将由各自的设计要求决定。简单的设计(如鼠标)可能仅要一个 IN 端点。复杂的设计可能需要多个数据端点。

  • USB 规定数据 4 种传输方式:控制传输(Control Transfer)、中断传输(Interrupt Transfer)、批量传输或叫块传输(Bulk Transfer)、实时传输或叫同步传输(Isochronous Transfer ),都是通过管道进行传输。

二、STM32F407下USB介绍

  • STM32F407 系列芯片有 2 个 USB OTG,高速 USB(USB OTG HS);全速 USB(USB OTG FS),高速 USB(HS)需要外扩高速 PHY 芯片实现

  • STM32F407 的 USB OTG FS 主要特性:通用特性、主机模式特性和从机模式特性

  • STM32F407 的 USB OTG FS 是双角色设备 (DRD) 控制器,同时支持从机功能和主机功能,或为“仅主机”模式或“仅从机” 模式

  • 主机模式下,支持全速(FS,12 Mb/s)和低速(LS,1.5 Mb/s)收发器。从机模式下,仅支持全速(FS,12 Mb/s)收发器

image

  • ST 提供了一个完整的 USB OTG 驱动库(包括主机和设备),全部是以 HAL 库的形式提供,相关参考例程在 en.stm32cubef4_v1-26-0_v1.26.0.zip 可以找到

时钟

image

  • STM32F407通过AHB总线访问(AHB频率必须大14.2Mhz),USB OTG 的内核时钟必须是 48Mhz来自时钟树里面的 PLL48CK(和 SDIO 共用)。

三、 demo移植

  • USB OTG 库
    image
  • USB OTG 例程
    image
  • USB OTG 库的使用和例程说明,参考 ST 官方提供的:UM1734(从机)和 UM1720(主机)两个文档,详细介绍USB OTG库的各个组成部分以及所提供的例程使用方法

demo移植步骤

  • 相关代码
    image

  • 步骤如下:

    • 拷贝官方 USB 驱动库相关代码到自建的工程文件夹下。STM32Cube_FW_F4_V1.26.0→Middlewares→ST 文件夹下的: STM32_USB_Device_Library、STM32_USB_HOST_Library 两个文件夹及源码拷贝到该文夹下面

    • 新建 USB_APP 文件夹用于存放 MSC 实现相关代码。STM32Cube_FW_F4_V1.26.0→Projects→STM324xG_EVAL→Applications→USB_Device→MSC_Standalone→Src 下的部分代码:usbd_conf.c、usbd_storage.c 和 usbd_desc.c 等 3 个.c 文件

    • 继续:STM32Cube_FW_F4_V1.26.0 → Projects → STM324xG_EVAL → Applications → USB_Device→MSC_Standalone→Inc 下面的:usbd_conf.h、usbd_storage.h 和 usbd_desc.h 等三个文件到 USB_APP 文件夹下
      image

    • 在Keil工程的基础上新建分组添加相关代码到工程中
      image

  • 代码修改

  • Keil配置修改

    • 使用 USB OTG FS,必须在 MDK 编译器的全局宏定义里面,添加宏定义:USE_USB_FS
    • 通过修改 usbd_conf.h 里面的 MSC_MEDIA_PACKET 定义值大小,可以一定程度提高USB 读写速度(越大越快)。通过修改:STORAGE_LUN_NBR 宏定义的值为 2,可以支持 3 个磁盘
    • 官方例程在 2 个或以上磁盘支持的时候,存在 bug,需要修改 usbd_msc.h 里面USBD_MSC_BOT_HandleTypeDef 结构体的 scsi_blk_nbr 参数,将其改为数组形式:uint32_t scsi_blk_nbr[STORAGE_LUN_NBR];数组大小由 STORAGE_LUN_NBR 指定,修改该参数后,相应的有一些函数要做修改,参考本例程源码。
    • 修改 usbd_msc_bot.c 里面修改 MSC_BOT_CBW_Decode 函数,将 hmsc->cbw.bLUN > 1 改为:hmsc->cbw.bLUN > STORAGE_LUN_NBR,以支持多个磁盘
  • USB 相关源码解释,参考:UM1734(STM32Cube USB device library).pdf

usb核心代码刨析

1. USB 驱动代码

1.1 usbd_conf.c

  • usbd_conf.c 提供 USB 设备库的回调及 MSP 初始化函数,当 USB 状态机处理完不同事务的时候,会调用此回调函数,通过回调函数,可以知道 USB当前状态。根据这些状态,用户应用程序可以执行不同操作

  • usbd_conf.c 3 个重点函数:HAL_PCD_MspInit 和 OTG_FS_IRQHandler、USBD_LL_Init函数

  • HAL_PCD_MspInit 函数,使能 USB 时钟,初始化 IO 口,设置中断等。该函数在HAL_PCD_Init 函数里面被调用。

  • OTG_FS_IRQHandler 函数,是 USB 的中断服务函数,通过调用 HAL_PCD_IRQHandler 函数,实现对 USB 各种事务的处理。

  • USBD_LL_Init 函数,初始化 USB 底层设置,因为定义的是:USE_USB_FS,因此会设置 USB OTG 使用 USB_OTG_FS,完成各种设置,比如,使用内部 PHY,使用全速模式,不使能 VBUS 检测等。该函数在 USBD_Init 函数里面被调用

1.2 usbd_desc.c

  • 提供 USB 设备类的描述符,决定 USB 设备的类型、端点、接口、字符串、制造商等重要信息
  • 一般不修改
  • usbd 即 device 类,usbh 即 host 类。只有 usb 字样的那就是 device 和 host 可以共用的,通过文件名区分该文件是用在 device 还是 host

1.3 usbd_storage.c

  • 提供磁盘操作函数,包括支持的磁盘个数,以及每个磁盘的初始化和读写等函数。
  • STORAGE_Init_FS函数: 初始化存储设备。根据输入参数(lun),执行不同存储设备的初始化
  • STORAGE_Read_FS 函数: 从存储设备读取数据,根据存储设备(lun)的不同,调用不同的读取函数,完成数据读取。
  • STORAGE_Write_FS 函数: 往存储设备写入数据,根据存储设备(lun)的不同,调用不同的写入函数,完成数据写入

2. main.c 代码

  • USBD_HandleTypeDef 是用于处理 USB 设备类通信处理的结构体类型,包含了 USB 设备类通信的各种变量、结构体参数、传输状态和端点信息等
  • USB 初始化
    1, 调用 USBD_Init 函数,初始化 USB 从机内核;
    2, 调用 USBD_RegisterClass 函数,链接 MSC 设备类驱动程序到设备内核;
    3, 调用 USBD_MSC_RegisterStorage 函数,为 MSC 设备类驱动添加回调函数;
    4, 调用 USBD_Start 函数,启动 USB 通信;
    经过以上四步处理,USB 启动,所有 USB 事务,都是通过 USB 中断触发,并由 USB驱动库自动处理。USB 中断服务函数在 usbd_conf.c 里
/**
* @brief USB OTG 中断服务函数
* @note 处理所有 USB 中断
* @param 无
* @retval 无
*/
void OTG_FS_IRQHandler(void)
{
 HAL_PCD_IRQHandler(&g_pcd_usb_otg_fs);
}
USBD_HandleTypeDef USBD_Device; /* USB Device 处理结构体 */
。
。
。
USBD_Init(&USBD_Device, &FS_Desc, DEVICE_FS); /* 初始化 USB */
 USBD_RegisterClass(&USBD_Device, &USBD_MSC); /* 添加类 */
/* 为 MSC 类添加回调函数 */
USBD_MSC_RegisterStorage(&USBD_Device, &USBD_Storage_Interface_fops_FS);
USBD_Start(&USBD_Device); /* 开启 USB */


  • HAL_PCD_IRQHandler 函数处理各种 USB 中断请求。
posted @   登云上人间  阅读(2978)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 易语言 —— 开山篇
· Trae初体验
  1. 1 原来你也在这里 周笔畅
  2. 2 世间美好与你环环相扣 柏松
  3. 3 起风了 吴青峰
  4. 4 极恶都市 夏日入侵企划
  5. 5 パレード ヨルシカ
极恶都市 - 夏日入侵企划
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 王星

作曲 : 灰鸿啊/皮皮

编曲 : 夏日入侵企画

制作人 : 邢硕

节奏吉他 : 肯尼

主音吉他 : 张伟楠

贝斯 : 皮皮

鼓 : 海鑫

和声 : 邢硕

音效制作 : 邢硕

录音 : 邢硕/夏国兴

混音 : 于昊

特别鸣谢 : 张伟楠

这城市的车流和这地表的颤抖

像一颗石子落入地心之后泛起的温柔

暗涌

河水流过转角她的楼

被梦魇

轻声呓语唤醒身后的幼兽

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都

已忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去陈旧的还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池已失守

最终无法占有

无眠辗转

伴着人间破碎的旧梦

像繁星

退却后只剩下混沌的夜空

炙热

掩盖风声鹤唳的担忧

把所有失落无助反手推入

无尽的白昼

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都已经忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池早已失守

惶恐难以接受

缠绵往复不肯放手

最终无法占有

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁 灭 即 拯 救

谁掠夺春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

明知城池已失守

缠绵往复不肯放手

最终无法占有

点击右上角即可分享
微信分享提示