1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本篇笔记主要介绍 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 位置(即USB_ADDR0_TX值为 0x18 而不是上图的0x30呢),而不是 0x40006060 呢,这样就不会浪费那些空间了。 因为这个改动会较大,感兴趣的可以尝试一下。 当USB 模块写入端点 0 的数据时,首先根据 USB_BTABLE 的值找到描述表的位置,然后再根据描述表第一个表项的 USB_ADDR0_RX 找到接收缓冲区的地址,最后写入数据(写入过程中会判断是否超出限制,防止破坏其他缓冲区,这个通过 USB_COUNT0_Rx 判断), 当应用程序进行读取上述地址的数据时,因为采用了 32 位访问,所以对USB_BTABLE 和 USB_ADDR0_RX偏移地址x2,这样就可以找到我们需要的缓存地址,从而读取到主机发给设备的数据,然后进行相应的处理。 设备发送同理。 具体实现可参考鱼鹰给出的源代码。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1817 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1631 浏览 1 评论
1103 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
739 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1692 浏览 2 评论
1951浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
756浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
586浏览 3评论
605浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
568浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-30 20:38 , Processed in 0.873668 second(s), Total 76, Slave 60 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号