STM32多CDC复合设备的端口断开检测问题
针对STM32复合CDC设备检测终端断开的解决方案
1. 主动轮询控制线路状态
虽然cdc-acm内核模块在终端close()时不会主动发送控制请求,但你可以主动向主机发起GET_CONTROL_LINE_STATE请求,轮询每个接口的DTR/RTS状态:
- 终端断开后,主机通常会清除对应接口的DTR(Data Terminal Ready)位
- 在STM32的USB中断服务函数或定时任务中,定期给目标接口(通过wIndex指定)发送该请求,解析返回的状态位判断是否断开
- 轮询周期建议设为1-5秒,避免占用过多USB带宽
2. 监控端点发送失败状态
终端断开后,主机会停止接收对应CDC接口的数据,此时STM32向该接口的OUT端点发送数据时会持续收到NAK或STALL响应:
- 在USB发送回调函数中,为每个CDC接口单独维护发送失败计数器,若连续多次(比如3次以上)发送失败,即可判定该接口对应的终端已断开
- 注意区分临时带宽不足导致的单次NAK和终端断开的持续失败
3. 模拟PL2303的断开通知逻辑
如果需要实现合规的断开触发,可参考PL2303的硬件逻辑适配固件:
- PL2303在终端断开时,会主动向主机发送
SERIAL_STATE通知包(CDC类0x20请求),告知设备状态变化 - 在STM32固件中,当检测到DTR清零或持续发送失败时,主动构造并发送该通知包,触发主机的状态更新
- 若需要更彻底的触发,可短暂切换USB设备状态(如临时挂起再恢复),让主机重新枚举对应接口,但此方法可能影响其他CDC接口的正常工作
关于cdc-acm内核模块的补充说明
你提到的cdc-acm模块close()无回调并非bug,而是CDC类规范的设计特性:
- CDC类标准未强制要求主机在终端断开时发送控制请求,不同操作系统的cdc-acm实现行为存在差异
- Linux的cdc-acm模块仅在终端打开时发送
SET_CONTROL_LINE_STATE和SET_LINE_CODING,关闭时不会主动通知设备
内容的提问来源于stack exchange,提问作者Eddy_Em
相关产品推荐
相关产品推荐

