使用python-can读取PCAN总线数据始终返回相同值的问题
解决PCAN总线Python读取数据不更新的问题
看起来你遇到的核心问题是总线接收缓存里的旧消息没有被清空,导致代码一直在重复读取首次获取的数据,而不是最新的总线消息。PCAN-View能看到数据变化,说明硬件和总线通信是正常的,问题出在代码的消息读取逻辑上。
问题原因分析
你当前使用bus.recv(None)时,None参数表示无限等待直到收到一条消息。但python-can的PCAN接口默认会缓存总线收到的消息——如果设备在启动时发送了初始数据(比如[00 03]),这条消息会被存在缓存里,后续即使总线有新的更新数据,只要缓存里还有未读取的旧消息,recv()就会先返回旧的,而不是等待新消息。这就是数据始终不更新的根本原因。
解决方案
下面提供两种可靠的解决方法,你可以根据需求选择:
方法1:主动清空缓存,只保留最新消息
在每次循环中,先快速读取缓存里所有的旧消息并丢弃,只保留最后一条最新的消息进行处理:
import can from time import sleep def main(): bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=500000) try: while True: latest_msg = None # 循环读取所有缓存中的消息,直到没有新消息(设置10ms超时) while True: msg = bus.recv(0.01) if msg is None: break latest_msg = msg # 处理最新消息 if latest_msg: arb_id = latest_msg.arbitration_id if arb_id in [0x1B2, 0x1B3, 0x1B4, 0x1B5]: print(latest_msg) else: print("Nothing received this time") sleep(0.2) except KeyboardInterrupt: print("Program Exited") except can.CanError: print("Message NOT sent") finally: bus.shutdown() if __name__ == '__main__': main()
方法2:使用AsyncBufferedReader监听最新消息
python-can提供了AsyncBufferedReader监听器,它会异步接收总线消息,确保你每次拿到的都是最新的消息,无需手动处理缓存:
import can from can import AsyncBufferedReader from time import sleep def main(): bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=500000) # 创建异步读取器 reader = AsyncBufferedReader() # 将读取器绑定到总线,自动接收消息 notifier = can.Notifier(bus, [reader]) try: while True: # 等待0.2秒获取最新消息(和你的原sleep时间一致) msg = reader.get_message(0.2) if msg: arb_id = msg.arbitration_id if arb_id in [0x1B2, 0x1B3, 0x1B4, 0x1B5]: print(msg) else: print("Nothing received this time") except KeyboardInterrupt: print("Program Exited") finally: # 停止监听器和总线 notifier.stop() bus.shutdown() if __name__ == '__main__': main()
为什么原代码无效?
你尝试过发送消息、调用can.Listener().stop(),但这些操作都没有触及核心问题:缓存里的旧消息没有被清理。原代码每次recv()都会优先读取缓存中最早的未处理消息,而不是等待新的总线数据,所以即使PCAN-View显示新数据,你的代码还是在重复读旧数据。
这两种方法都能确保你获取到总线的最新消息,测试一下应该就能解决你的问题了。
内容的提问来源于stack exchange,提问作者Swedgin
相关产品推荐
相关产品推荐

