0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

USB之STM32基础(6)

电子设计 来源:电子设计 作者:电子设计 2020-10-30 10:31 次阅读

本篇笔记主要介绍 STM32 相关的知识点,毕竟之后的 CDC 教程是用 STM32 开发的。

为了写这一篇,鱼鹰把 STM32 中文参考手册 USB 相关的从头到尾看了一遍,虽然以前就已经看过了,但这次看,收获又是不同。

不过限于篇幅,鱼鹰不会面面俱到,只介绍和 CDC 相关的一些东西。

要完成 USB 模拟串口(CDC)的实验,STM32 手册是必须细细阅读的,不然代码里面很多操作你是无法看懂的。

其实理解了前面的一些东西,你会发现 STM32 中的 USB 知识和前面的大同小异,毕竟开发芯片的厂家也是按照 USB 标准来实现的,不会差到哪里去。

硬件基础

首先,STM32F103 使用 PA11(USBDM,D-)和 PA12(USBDP,D+)完成数据的收发。但看过前面章节的道友应该知道,全速 USB 在 D+ 引脚是需要有一个上拉电阻的,同时两根数据线需要各自串联一个 22 Ω的电阻。

这就是你需要的硬件基础,如果说你的开发板有 USB 接口,但是没有这些条件,那么你的 USB 接口只能用于供电,无法进行数据传输。

当然,STM32F103 的速度为全速 12 Mbit,换算成字节为 1.5 MB,除去 USB 协议的开销(令牌、打包等),大概能达到 1 MB/s 速度。

鱼鹰在测试给各位道友的 CDC 例程发现只能达到 100 KB 左右,原以为是主机没有及时发送令牌包导致带宽很低,后来发现 USB 设备发出的数据包只有几个字节,而不是最大包 64B,才知道是发送的数据太少了,后来增加发送的数据量(一次往缓冲多写几百个字节),带宽达到了 400~700KB,但离 1MB 还差了点。

通过逻辑分析仪查看才知道,主机发送 IN 令牌包时,设备有可能还没准备好,浪费了带宽,不过在看 STM32 资料中发现,对于批量传输(CDC 使用批量传输),可以使用双缓冲提高传输量,估计用了双缓冲,传输速率能达到 1MB/s,比串口的 115200 Bit/s 快的多,也稳定的多,毕竟人家可是自带了 CRC 校验和数据重传功能的。

软件基础

现在看一看 STM32F103 的 USB 有哪些功能

第一点,支持 USB2.0 全速,而不是 2.0 高速 480Mbit/s。

有 1~8 个(双向)端点,这是能完成组合设备的基础,按照 CDC + DAP 组合设备来说,一共需要 1(控制传输)+ 2(CDC)+1(HID) = 4 个端点的,更不要说再模拟一个 U 盘了。

CRC、NRZI 编解码,这个可以让你不必关心每一位是什么情况,你只需要处理底层给你的字节数据即可。

支持双缓冲,最大程度的利用 USB 的带宽。

支持 USB 挂起和恢复操作,其实还支持设备远程唤醒操作,即由设备发起唤醒请求(比如鼠标移动后唤醒设备)。

后面有一个注意点,就是 USB 和 CAN 共用 512 字节的缓存,也就是说同一时刻只能有一个外设可以工作,当然你可以通过软件在不同时刻使用不同的外设。

可以看看 USB 设备框图,了解一下 USB 是由哪些结构组成的。

为了实现 USB 通信,有以下基础步骤需要完成:

1、打开 Port A 的外设时钟(PA11 和 PA12)

2、打开 USB 时钟(其实还需要设置 USB 时钟频率,一般 SystemInit 会替你完成,当 USB 时钟打开后, PA11 和 PA12 引脚由 USB 接管,不归 GPIO 控制)。

3、打开相应中断(一共有三个中断)

低优先级中断是我们主要关注的,因为 USB 枚举过程就在这个中断完成,所以这个中断必须开启,其他两个就看需求了。

4、配置 USB 寄存器,使 USB 可以正常工作。

5、之后所有的操作都在低优先级中断进行(包括复位、枚举、SOF 检测等)。

以上步骤具体可以看鱼鹰提供的例程实现,不再多说。

USB 寄存器

USB 中有三类寄存器:端点寄存器、通用寄存器、缓冲区描述表,再加上和描述表对应的缓冲区(数据收发缓存区,USB 所有的数据传输都首先要经过这里),我们要做的就是在合适的时候对这些寄存器进行相应的操作即可。

地址 0x 0x4000 5C00 开始为端点寄存器,因为有 8 个(双向)端点,所以有 8 个寄存器管理。
之后的寄存器为通用寄存器,用于管理整个 USB 模块的,具体可查看参考手册。

以上寄存器有些位很特殊,比如可能写 0 有效,写 1 无效,所以有如下要求:

所以以往的读 - 改 - 写不能在这里使用,不然你这边读回了 0,但是硬件修改了变成 1,如果往回写 0 ,那么就把硬件设置的 1 清除了,肯定会有影响,所以针对这种位,需要对不操作的位设置为 1 ,这样就不会意外修改了。

还有可能写 1 翻转,写 0 无效,这时你会发现代码中使用异或(^)来设置需要的位,非常巧妙。
总之,在学习 USB 过程中,可以锻炼你的位操作能力。

上述两类寄存器在参考手册其实是比较详尽的,但缓冲区描述表(描述表的作用就是描述端点发送和接收缓存区的地址和大小)就显得晦涩难懂了,所以这里详细说一下缓冲区描述表(以下表述可能有问题,需要各位自行验证)。

首先,描述表的地址在 0x4000 6000,也就是说前面所说的 512 Byte 的基地址。但是按照参考手册中的描述来看,这个空间大小应该是 512 Byte * 2,这是因为 USB 模块寻址采用 16 位寻址的,而应用程序使用 32 位寻址,也就是说,按照我们的软件角度,空间分布应该是这样的:

低地址的两个字节可以被我们访问(有颜色部分),高地址的两个字节不可访问(但是按照双缓冲描述来看,好像可以访问到,以后在验证一下)。

所以地址范围应该有 1 KB 的空间,但只有一半是可以使用的。

还有一点就是这块空间不仅用于存放 USB 传输的数据,还用来存放缓存区描述表,这个缓冲区描述表可以在这块空间的任何一个位置,只要满足 8 字节对齐即可,毕竟一个端点需要 16 字节记录(这里可能会感到疑惑,为什么一个端点 16 字节,但却是 8 字节对齐,这就是 16 位 和 32 访问的区别,在 USB 寄存器中,USB 模块通过 16 位访问,所以寄存器里面的值都是按照 16 位来保存偏移的)。

这个表的基地址存放在 USB_BTABLE 寄存器中,一般设置为 0,表示这个表放在上述空间的开始处。

根据需要,依次安排描述表。比如 CDC 有三个端点,前 16 个字节安排端点 0,负责描述发送缓存区的地址和大小,接收缓存区的地址和大小(防止接收时溢出)

端点 1 和端点 2 供 CDC 使用,占用 32 字节。所以前 48 字节被描述表占用了,剩下的(1024 – 48)/ 2 就是数据缓冲区了。比如将端点 0 的发送缓冲区地址指向 0x18(相对地址 0x4000 6000 偏移,16 位访问),大小为 64 字节,端点 0 的接收缓存区指向 0x58(寄存器 USB_ADDR0_RX 写入的值,16 位访问),大小为 64 字节(注意这里的值为 16 位寻址,即 USB 模块的寻址,和应用层 32 位寻址不同,两者之间需要转化)。

按理应该像上面分布空间的,但实际上你会发现分布如下:

那么是否可以将端点 0 的缓存地址安排在 0x40006030 位置,而不是 0x40006060 呢,这样就不会浪费那些空间了。

因为这个改动会较大,感兴趣的可以尝试一下。

当 USB 模块写入端点 0 的数据时,首先根据 USB_BTABLE 的值找到描述表的位置,然后再根据描述表第一个表项的 USB_ADDR0_RX 找到接收缓冲区的地址,最后写入数据(写入过程中会判断是否超出限制,防止破坏其他缓冲区,这个通过 USB_COUNT0_Rx 判断),当应用程序进行读取上述地址的数据时,因为采用了 32 位访问,所以对 USB_BTABLE 和 USB_ADDR0_RX 偏移地址 x2,这样就可以找到我们需要的缓存地址,从而读取到主机发给设备的数据,然后进行相应的处理。
设备发送同理。

具体实现可参考鱼鹰给出的源代码。

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • usb
    usb
    +关注

    关注

    60

    文章

    7768

    浏览量

    262313
  • STM32
    +关注

    关注

    2256

    文章

    10822

    浏览量

    352377
收藏 人收藏

    评论

    相关推荐

    stm32h743iit6使用usb怎么配置dma搬运?

    目前用的是stm32h743iit6。在配置usb的界面看到了 但是生成的代码里面没有看到类似dma的字眼。是我配错了吗?
    发表于 07-02 07:52

    STM32042F6P6 USB接口被静电损坏了怎么解决?

    STM32042F6P6 USB接口被静电损坏,USB DP 和DM 已经接了 ESD器件USBLC6-2SC6,而且DP 和DM不能串接电阻,请问有更好的方法吗?谢谢
    发表于 03-28 06:24

    使用STM32F103RCT6开发USB设备,STM32CubeMx生成代码遇到的问题求解

    大家好,最近在使用STM32F103RCT6开发USB设备,使用的是STM32CubeMx生成的代码,但查看代码发现一个问题,HAL_PCD_MspInit函数中开启了USB外设时钟,
    发表于 03-21 08:30

    USB转TTL线怎么把程序烧写到stm32f103C8T6

    USB转TTL线怎么把程序烧写到stm32f103C8T6中  将程序烧写到STM32F103C8T6芯片中需要使用USB转TTL线连接计算机和开发板,并使用适当的软件来进行编程和烧
    的头像 发表于 01-31 15:46 6155次阅读

    stm32 usb 主机发送 pid in的原理和实现方法

    STM32是一款常用的微控制器系列,它具有广泛的应用领域,包括工业控制、汽车电子、消费电子等。其中,STM32同时支持USB主机和设备功能,使得它在与其他USB设备的通信中具有很大的优
    的头像 发表于 12-20 15:56 1059次阅读

    STM32CubeIDE实用技巧配置Heap空间

    STM32CubeIDE实用技巧配置Heap空间
    的头像 发表于 10-31 17:30 973次阅读
    <b class='flag-5'>STM32</b>CubeIDE实用技巧<b class='flag-5'>之</b>配置Heap空间

    巧用 STM32CubeIDE 编译警告

    巧用 STM32CubeIDE 编译警告
    的头像 发表于 10-25 16:33 818次阅读
    巧用 <b class='flag-5'>STM32</b>CubeIDE <b class='flag-5'>之</b>编译警告

    浅谈STM32SD卡

    STM32SD卡
    的头像 发表于 10-19 18:28 1475次阅读
    浅谈<b class='flag-5'>STM32</b><b class='flag-5'>之</b>SD卡

    STM32 USB虚拟串口驱动

    电子发烧友网站提供《STM32 USB虚拟串口驱动.rar》资料免费下载
    发表于 10-09 15:25 92次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>USB</b>虚拟串口驱动

    STM32F103x4/STM32F103x6单片机数据手册

    本文档是关于ARM® Cortex®-M3内核的低等容量增强型单片机STM32F103x4,STM32F103x6的数据手册, 介绍了它的主要外设资源和电特性参数,外设资源包括:16/32 KB Flash, USB, CAN,
    发表于 09-22 17:55 12次下载
    <b class='flag-5'>STM32</b>F103x4/<b class='flag-5'>STM32F103x6</b>单片机数据手册

    STM32Cube USB主机库

    电子发烧友网站提供《STM32Cube USB主机库 .pdf》资料免费下载
    发表于 09-21 14:40 0次下载
    <b class='flag-5'>STM32</b>Cube <b class='flag-5'>USB</b>主机库

    STM32Cube USB设备库

    电子发烧友网站提供《STM32Cube USB设备库.pdf》资料免费下载
    发表于 09-21 11:06 8次下载
    <b class='flag-5'>STM32</b>Cube <b class='flag-5'>USB</b>设备库

    STM32CubeIDE实用技巧ld链接文件

    电子发烧友网站提供《STM32CubeIDE实用技巧ld链接文件.pdf》资料免费下载
    发表于 09-20 10:31 1次下载
    <b class='flag-5'>STM32</b>CubeIDE实用技巧<b class='flag-5'>之</b>ld链接文件

    STM32CubeIDE实用技巧配置堆空间

    电子发烧友网站提供《STM32CubeIDE实用技巧配置堆空间.pdf》资料免费下载
    发表于 09-19 15:07 5次下载
    <b class='flag-5'>STM32</b>CubeIDE实用技巧<b class='flag-5'>之</b>配置堆空间

    STM32进阶串口环形缓冲区实现

    STM32进阶串口环形缓冲区实现
    的头像 发表于 09-19 09:20 2004次阅读
    <b class='flag-5'>STM32</b>进阶<b class='flag-5'>之</b>串口环形缓冲区实现