[STM32F7] CDC 传输完成的通知方式

[复制链接]
211|28
内核558 发表于 2026-8-29 22:01 | 显示全部楼层 |阅读模式
我发现在所有基于 STM32Cube 库的 USB‑CDC 示例里,传输缓冲区都依靠定时器轮询 USB 状态:先查询 USB 是否处于忙状态,之后再填充下一段发送缓冲区并调用`USBD_CDC_TransmitPacket`。

有没有办法不用轮询?

是否存在对应的中断,可以在传输完成时给出通知,然后发送下一包数据?还是说只能采用轮询?
如果必须轮询,对于全速 USB,采用多大的轮询间隔可以实现最优性能?

亚瑟 发表于 2026-9-1 16:11 | 显示全部楼层
中断通知是更好的选择,STM32Cube库支持中断驱动模式,设置好相关中断处理函数即可。轮询间隔一般设置为10-20ms即可。
幻境之眼 发表于 2026-9-2 13:35 | 显示全部楼层
中断通知确实方便,设置好中断处理函数,STM32Cube库会自动处理。轮询间隔10-20ms挺合适,但记得检查USB状态寄存器,别让数据溢出。
CarterERO 发表于 2026-9-3 16:47 | 显示全部楼层
中断通知确实高效,记得配置好USBD_CDC_ReceiveIT()和USBD_CDC_TransmitIT(),这样传输完成会有通知。轮询间隔10-20ms是平衡性能和功耗的好选择。
MessageRing 发表于 2026-9-4 14:37 | 显示全部楼层
中断通知确实高效,记得配置好USBD_CDC_ReceiveIT()和USBD_CDC_TransmitIT(),我在项目中也是这么做的。
在海边聆听 发表于 2026-9-4 15:03 | 显示全部楼层
CDC_TransmitCplt_FS这个回调函数就是用来通知发送完成的,你只需要在usbd_cdc_if.c里实现它,不用自己轮询。
classroom 发表于 2026-9-4 16:45 | 显示全部楼层
调用USBD_CDC_TransmitPacket之后,USB硬件在发送完数据时会产生TX完成中断,该中断会回调CDC_TransmitCplt_FS,你可以在这个回调里触发下一包发送。
cr315 发表于 2026-9-4 18:12 | 显示全部楼层
轮询方式是你自己加的,官方的CDC示例里用定时器轮询只是为了演示和兼容老版本,并不是唯一方式,中断回调是标准做法。
duo点 发表于 2026-9-4 19:42 | 显示全部楼层
如果你用了DMA发送数据到USB端点,那么DMA传输完成中断也可以作为发送完成的触发信号,比轮询更高效。
onlycook 发表于 2026-9-4 22:42 | 显示全部楼层
如果你的应用层发送频率很高,中断回调里直接调用下一次USBD_CDC_TransmitPacket可能会递归过深,建议用队列或状态机来缓冲突发。
flycamelaaa 发表于 2026-9-4 22:55 | 显示全部楼层
检查一下你的工程里是否定义了USE_USB_CDC_INTERRUPT或类似宏,如果没开启中断使能,那CDC_TransmitCplt_FS就不会被调用。
jcky001 发表于 2026-9-5 10:05 | 显示全部楼层
全速USB的最大包大小是64字节,发送完成中断会在每一包(64字节)传完后触发一次,你可以利用这个节奏控制发送队列。
ForgottenRealm 发表于 2026-9-5 12:00 | 显示全部楼层
中断通知确实高效,记得配置好USBD_CDC_ReceiveIT()和USBD_CDC_TransmitIT(),我在项目中也是这么做的。如果使用DMA,传输完成中断更佳。
powerantone 发表于 2026-9-5 12:19 | 显示全部楼层
如果必须用轮询方式,全速USB每帧间隔1ms,轮询周期设为1ms可以保证最快响应,但CPU占用率会明显升高。
probedog 发表于 2026-9-5 13:58 | 显示全部楼层
轮询间隔小于1ms没有任何收益,因为全速USB的帧同步周期就是1ms,更频繁的查询只会空转CPU。
solty 发表于 2026-9-5 15:47 | 显示全部楼层
用轮询方式时查询USBD_CDC_GetTxState或检查端点发送标志位,状态变化发生在1ms边界内,所以1ms间隔是最优的。
spicy 发表于 2026-9-5 17:28 | 显示全部楼层
如果你的数据包大于64字节,CDC会分包发送,每个分包完成后都会触发一次中断回调,所以回调里不要假设整个大包已经发完。
七毛钱 发表于 2026-9-6 11:08 | 显示全部楼层
有些Cube库版本中CDC_TransmitCplt_FS默认是__weak空函数,你需要自己重写它,否则即使有中断也不会执行任何动作。
xiyaoko2365 发表于 2026-9-6 13:18 | 显示全部楼层
轮询确实太浪费CPU资源了,特别是F7这种高性能芯片。其实USB底层是有传输完成中断的,只是CubeMX生成的CDC代码把它封装得太深了。你可以去usbd_cdc.c里找TX完成的中断回调,那个地方就是发送完毕的标志,直接在那里置个标志位或者发信号量比轮询强多了
今天会画卧蚕吗 发表于 2026-9-6 13:24 | 显示全部楼层
如果你同时使用了USB主机和从机模式,发送完成回调的上下文和中断优先级可能不同,要确认回调执行时USB内核已经退出忙状态。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

212

主题

213

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0