使用PyUSB读取STM32F103C8T6 Flash时接收空列表问题排查
问题分析与解决方案
核心问题定位
交替空接收+数据错误,本质是USB CDC传输的同步逻辑缺陷,结合STM32端发送时序不严谨、PyUSB接收逻辑无等待机制共同导致。
一、STM32从机侧修复
强制等待CDC发送完成
CDC_Transmit_FS是非阻塞函数,直接连续调用会导致数据丢包。必须等待上一次发送完成后再触发下一包发送:uint8_t CDC_TxComplete = 1; // 发送完成回调函数(需在USB CDC回调中实现) void USBD_CDC_TransmitCpltCallback(USBD_HandleTypeDef *hUsbDeviceFS) { CDC_TxComplete = 1; } // 封装可靠的发送函数 void Send_Flash_Block(uint8_t *buf, uint32_t len) { while(!CDC_TxComplete); // 等待上一包发送完成 CDC_TxComplete = 0; CDC_Transmit_FS(buf, len); }调用此函数发送两包8192字节的Flash数据,确保时序同步。
Flash读取边界校验
确保读取的Flash地址在STM32F103C8T6的有效范围(0x08000000~0x0800FFFF),避免越界读取垃圾数据:// 示例:读取指定地址的Flash数据 void Read_Flash_Data(uint32_t start_addr, uint8_t *buf, uint32_t len) { if(start_addr + len > 0x08010000) return; // 超过64KB Flash上限直接返回 for(uint32_t i=0; i<len; i++) { buf[i] = *(uint8_t*)(start_addr + i); } }命令触发的可靠性校验
原中断仅判断字节数就触发发送,易受干扰误触发。建议给9字节命令加校验位(比如最后1字节为前8字节的异或和),中断中先验证校验再设置Flash_Data_Transmission_Flag。
二、PC主机侧PyUSB代码修复
加入等待与超时机制
原循环无等待直接读取,从机还未准备好数据就会返回空列表。发送命令后给从机预留处理时间,读取时设置合理超时:import usb.core import usb.util import time # 匹配Blue Pill CDC设备(默认VID/PID) dev = usb.core.find(idVendor=0x0483, idProduct=0x5740) if not dev: raise ValueError("设备未找到") dev.set_configuration() # 直接使用端点地址(通常OUT为0x01,IN为0x81) EP_OUT = 0x01 EP_IN = 0x81 Main_List = [] trigger_cmd = b'\x01\x00\x00\x00\x00\x00\x00\x00\x01' # 示例9字节命令(含校验) # 发送触发命令 dev.write(EP_OUT, trigger_cmd) time.sleep(0.02) # 给从机20ms处理时间 for _ in range(2): try: # 读取8192字节,超时1秒 data = dev.read(EP_IN, 8192, timeout=1000) Main_List.append(list(data)) except usb.core.USBError as e: # 读取失败时重试一次 dev.write(EP_OUT, trigger_cmd) time.sleep(0.02) data = dev.read(EP_IN, 8192, timeout=1000) Main_List.append(list(data)) print(f"接收结果长度: {[len(lst) for lst in Main_List]}")处理USB端点缓存
若仍有空读,可在每次读取前尝试清空端点缓存:# 读取前清空缓存 try: dev.read(EP_IN, 0, timeout=100) except usb.core.USBError: pass增加数据校验
在从机每包数据末尾加入CRC16或字节和校验,PC端接收后验证,若校验失败则请求从机重发对应包,确保数据正确性。
三、额外稳定性优化
- STM32中断优先级配置:将USB_LP_CAN1_RX0_IRQn的中断优先级设为较高级别(比如0或1),避免USB传输被其他低优先级中断打断。
- PC端权限处理:Linux/macOS下需配置udev规则或用sudo运行脚本,避免USB权限不足导致传输异常。
- 拆分数据包:若8192字节传输不稳定,可拆分为1024字节小包多次发送,PC端拼接后得到完整16KB数据。
内容的提问来源于stack exchange,提问作者Diracx
相关产品推荐
相关产品推荐

