当前位置: 首页 > article >正文

告别CAN总线数据乱码:手把手教你用Python实现ISO15765协议拆包(附完整代码)

告别CAN总线数据乱码手把手教你用Python实现ISO15765协议拆包附完整代码在汽车电子和物联网开发领域CAN总线通信是核心技术之一。当我们需要从CAN分析仪或硬件接口获取原始数据时经常会遇到数据包被分割成多个帧的情况这时候ISO15765协议就派上了用场。本文将带你深入理解这个协议并用Python实现一个完整的拆包解决方案。1. ISO15765协议基础解析ISO15765是基于CAN2.0A/B协议的应用层通信协议专门用于车辆诊断服务。它解决了CAN帧最大只能传输8字节数据的限制允许传输更长的数据包。协议定义了四种帧类型单帧(Single Frame): 用于传输不超过7字节的数据首帧(First Frame): 多帧传输的第一个帧包含总数据长度连续帧(Consecutive Frame): 多帧传输的后续数据帧流控帧(Flow Control Frame): 控制数据传输速率帧类型通过数据首字节的高4位来标识SINGLE_FRAME 0x0 FIRST_FRAME 0x1 CONSECUTIVE_FRAME 0x2 FLOW_CONTROL_FRAME 0x32. 开发环境准备在开始编码前我们需要准备以下环境硬件设备:CAN分析仪(如PCAN、Kvaser等)或带有CAN接口的开发板Python库:python-can: 用于CAN总线通信struct: 处理字节序转换time: 处理超时逻辑安装python-can库pip install python-canCAN总线配置:波特率: 通常为500Kbps或1Mbps通道: 根据硬件选择帧格式: 标准帧(11位ID)或扩展帧(29位ID)3. 协议拆包核心实现3.1 帧类型识别与处理首先我们需要实现帧类型识别功能def get_frame_type(data): 识别帧类型 first_byte data[0] frame_type (first_byte 0xF0) 4 return frame_type3.2 单帧处理单帧处理相对简单直接从数据中提取有效内容def process_single_frame(data): 处理单帧数据 length data[0] 0x0F # 低4位表示长度 payload data[1:1length] return payload3.3 多帧处理多帧处理需要维护状态包括接收缓冲区、当前帧序号等class MultiFrameReceiver: def __init__(self): self.buffer bytearray() self.expected_length 0 self.expected_seq 1 self.last_received 0 def process_first_frame(self, data): 处理首帧 # 提取总长度(首字节低4位和第二个字节组成12位长度) self.expected_length ((data[0] 0x0F) 8) data[1] # 保存首帧中的数据部分 self.buffer bytearray(data[2:8]) self.expected_seq 1 self.last_received time.time() def process_consecutive_frame(self, data): 处理连续帧 current_seq data[0] 0x0F if current_seq ! self.expected_seq: raise ValueError(f序列号错误期望{self.expected_seq}收到{current_seq}) # 添加数据到缓冲区 self.buffer.extend(data[1:8]) self.expected_seq (self.expected_seq 1) % 16 self.last_received time.time() def is_complete(self): 检查是否接收完成 return len(self.buffer) self.expected_length def get_payload(self): 获取完整数据 if not self.is_complete(): raise ValueError(数据接收未完成) return bytes(self.buffer[:self.expected_length])3.4 流控处理流控帧用于控制数据传输速率def process_flow_control(data): 处理流控帧 flow_status data[0] 0x0F block_size data[1] # 连续发送的最大帧数 separation_time data[2] # 帧间最小间隔(ms) return { status: flow_status, block_size: block_size, separation_time: separation_time }4. 完整拆包实现结合上述组件我们可以实现完整的拆包逻辑class ISO15765Decoder: def __init__(self): self.receiver MultiFrameReceiver() self.state IDLE # IDLE, WAITING_FLOW_CONTROL, RECEIVING def process_frame(self, data): frame_type get_frame_type(data) if frame_type SINGLE_FRAME: return process_single_frame(data) elif frame_type FIRST_FRAME: if self.state ! IDLE: self._reset() self.receiver.process_first_frame(data) self.state WAITING_FLOW_CONTROL return None elif frame_type CONSECUTIVE_FRAME: if self.state ! RECEIVING: raise ValueError(意外的连续帧) self.receiver.process_consecutive_frame(data) if self.receiver.is_complete(): payload self.receiver.get_payload() self._reset() return payload return None elif frame_type FLOW_CONTROL_FRAME: if self.state ! WAITING_FLOW_CONTROL: raise ValueError(意外的流控帧) flow_info process_flow_control(data) if flow_info[status] ! 0: self._reset() raise ValueError(流控状态异常) self.state RECEIVING return None def _reset(self): self.receiver MultiFrameReceiver() self.state IDLE def check_timeout(self, timeout1000): 检查是否超时 if self.state ! IDLE and (time.time() - self.receiver.last_received) * 1000 timeout: self._reset() return True return False5. 实际应用与测试5.1 测试用例让我们编写一些测试用例来验证我们的实现import unittest class TestISO15765Decoder(unittest.TestCase): def setUp(self): self.decoder ISO15765Decoder() def test_single_frame(self): # 单帧: 长度2数据0x3E, 0x00 data bytes([0x02, 0x3E, 0x00]) result self.decoder.process_frame(data) self.assertEqual(result, bytes([0x3E, 0x00])) def test_multi_frame(self): # 首帧: 长度8 first_frame bytes([0x10, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]) # 流控帧: 允许继续发送 flow_control bytes([0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) # 连续帧1: 序号1数据0x07, 0x08 con_frame1 bytes([0x21, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00]) # 处理首帧 self.assertIsNone(self.decoder.process_frame(first_frame)) # 处理流控帧 self.assertIsNone(self.decoder.process_frame(flow_control)) # 处理连续帧 result self.decoder.process_frame(con_frame1) self.assertEqual(result, bytes([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]))5.2 与CAN总线集成将解码器与python-can库集成import can def can_receive_loop(): bus can.interface.Bus(channelcan0, bustypesocketcan) decoder ISO15765Decoder() while True: msg bus.recv(timeout1.0) if msg is None: if decoder.check_timeout(): print(接收超时重置解码器) continue try: result decoder.process_frame(msg.data) if result is not None: print(f接收到完整数据: {result.hex()}) # 在这里处理完整数据 except ValueError as e: print(f处理错误: {e}) decoder._reset()6. 常见问题与优化建议在实际开发中你可能会遇到以下问题字节序问题:CAN总线数据通常是小端序使用struct模块处理多字节数据超时处理:设置合理的超时时间(通常1000ms)超时后应重置解码器状态内存管理:对于大容量数据考虑使用内存视图或分块处理避免不必要的内存拷贝错误恢复:实现错误计数器超过阈值后重置连接记录错误日志以便调试性能优化:使用字节数组代替列表存储数据避免在关键路径上进行不必要的对象创建7. 扩展应用J1939协议虽然本文聚焦于ISO15765但类似的思路也适用于J1939协议。J1939是商用车常用的协议与15765的主要区别包括固定250Kbps波特率使用29位扩展帧ID更复杂的寻址机制基于广播的通信模式如果你需要处理J1939协议可以考虑扩展本文的解码器实现添加PGN(参数组编号)解析等功能。

相关文章:

告别CAN总线数据乱码:手把手教你用Python实现ISO15765协议拆包(附完整代码)

告别CAN总线数据乱码:手把手教你用Python实现ISO15765协议拆包(附完整代码) 在汽车电子和物联网开发领域,CAN总线通信是核心技术之一。当我们需要从CAN分析仪或硬件接口获取原始数据时,经常会遇到数据包被分割成多个帧…...

麒麟天御安全域管平台加域后,域账户登录不上?从加域到登录的全链路排查指南

麒麟天御安全域管平台加域后域账户登录故障全链路排查指南 当终端成功加入麒麟天御安全域管平台后,域账户却无法正常登录,这种看似矛盾的情况在实际运维中并不罕见。本文将带您深入加域后的"黑盒"阶段,系统梳理从客户端到服务端的全…...

API2Cursor:将Swagger文档转为AI友好格式,提升Cursor开发效率

1. 项目概述与核心价值最近在折腾一个挺有意思的项目,叫Frostbound-northsea978/api2cursor。光看这个名字,可能有点摸不着头脑,但如果你也经常在前后端联调、API文档维护或者自动化测试这些场景里打转,那这个项目绝对值得你花点时…...

手机拍照背后的秘密:一文看懂ISP图像处理流水线(从RAW到JPEG全流程拆解)

手机拍照背后的秘密:一文看懂ISP图像处理流水线(从RAW到JPEG全流程拆解) 每次按下手机快门时,你是否好奇过那张瞬间生成的精美照片背后究竟发生了什么?从传感器捕捉的光信号到朋友圈里点赞无数的成片,中间隐…...

C# Winform项目实战:手把手教你用SqlHelper类打造安全的登录模块(防SQL注入版)

C# Winform安全登录实战:基于SqlHelper的参数化防注入方案 登录功能作为系统安全的第一道防线,其重要性不言而喻。许多初级开发者在实现Winform登录模块时,往往直接拼接SQL字符串进行验证,这无异于为黑客敞开了大门。本文将带你重…...

基于Hermes模型的现代化Web仪表盘部署与深度使用指南

1. 项目概述与核心价值最近在折腾大语言模型(LLM)应用时,我一直在寻找一个既美观又实用的Web界面来管理和交互。市面上的方案要么过于简陋,要么配置复杂,要么就是功能单一。直到我发现了monaleesa77/hermes-dashboard这…...

为Hermes智能体集成Brave Search实时搜索插件:本地大模型联网实践

1. 项目概述与核心价值 最近在折腾本地大模型应用,特别是想让它们能“联网”获取实时信息,而不是只依赖训练时那个“陈旧的知识库”。试过不少方案,比如让模型自己写代码去爬取,或者集成一些通用的搜索API,但总感觉要…...

【国家级AI治理新标竿】:AISMM如何替代NIST AI RMF成为下一代合规刚需?工信部信通院专家亲授迁移路线图

更多请点击: https://intelliparadigm.com 第一章:2026奇点智能技术大会:AISMM评估工具 在2026奇点智能技术大会上,AISMM(Artificial Intelligence System Maturity Model)评估工具正式开源,成…...

Intelli框架:统一多模型AI智能体编排与工作流开发实践

1. 项目概述:一个面向开发者的AI智能体编排框架如果你正在寻找一个能让你快速构建、测试和部署复杂AI应用,同时又不想被某个特定厂商的API绑定死的Python框架,那么Intelli值得你花时间深入了解。我最初接触它,是因为手头一个项目需…...

OpenClaw插件实战:基于Pub/Sub与Events API实现Google Chat AI智能体集成

1. 项目概述 最近在折腾一个挺有意思的东西,叫 teyou/openclaw-googlechatpubsub-plugin 。简单来说,这是一个为 OpenClaw 这个 AI 智能体平台开发的插件,它的核心功能是让 AI 智能体能够无缝接入 Google Chat(谷歌聊天&#x…...

告别点灯Demo:用STM32+WS2812B制作一个桌面氛围灯(支持手机App调色)

从零打造智能氛围灯:STM32WS2812B全栈开发指南 深夜伏案工作时,一盏能随心情变换色彩的智能氛围灯,或许能为你带来别样的灵感。这不是商场里千篇一律的RGB灯带,而是一个完全由你掌控的创意作品——通过STM32单片机驱动WS2812B灯珠…...

Arkloop框架解析:异步任务流编排与复杂状态循环管理实战

1. 项目概述:Arkloop是什么,以及它为何值得关注最近在开源社区里,一个名为“Arkloop”的项目引起了我的注意。这个由开发者“qqqqqf-q”创建的项目,名字听起来就很有意思,结合了“Ark”(方舟/架构&#xff…...

3D机械设计与物理测试集成技术解析

1. 3D机械设计与物理测试的集成分析技术概述在现代机械工程领域,3D设计与物理测试的集成已经成为提升产品开发效率的关键突破口。作为一名长期从事CAE分析的工程师,我深刻体会到传统"设计-分析-测试"串行流程的局限性——设计团队完成CAD建模和…...

保姆级教程:用EMQX 5.0在Windows上快速搭建MQTT服务器(附MQTTX客户端连接测试)

10分钟极速部署:Windows平台EMQX 5.0与MQTTX全链路实战指南 刚接触物联网开发时,最令人头疼的往往不是代码编写,而是基础环境的搭建。MQTT作为物联网领域的事实标准协议,其服务器部署过程却常常让新手望而却步。本文将带你用最短…...

云原生时代的基础设施可观测性:构建服务拓扑与依赖关系图谱

1. 项目概述:照亮基础设施的“技能”在云原生和微服务架构成为主流的今天,一个典型的中大型互联网应用背后,往往运行着数十甚至上百个独立的服务。这些服务分布在不同的容器、虚拟机、集群和云区域中,通过复杂的网络相互连接。对于…...

异步扩散模型在3D视频生成中的创新应用

1. 项目概述:当3D视频生成遇上异步扩散模型去年在为一个影视特效项目调试渲染管线时,我首次尝试将异步扩散模型引入3D视频生成流程。原本需要8小时渲染的动画序列,通过新的技术方案压缩到了47分钟,且画面质量反而提升了23%的细节保…...

AI日报神器:程序员告别流水账,Gemini3.1Pro自动生成日报

不少程序员对日报的态度很一致:不是不愿意工作,而是觉得日报写起来“重复、耗时、还容易写得不对劲”。你明明今天做了不少事,最后却花时间把它整理成流水账——然后还得应付格式、补充说明、以及“为什么要做这个”的解释。久而久之&#xf…...

MCP 2026低代码平台集成:为什么87%的POC失败源于这6个元数据映射盲区?

更多请点击: https://intelliparadigm.com 第一章:MCP 2026低代码平台集成的元数据治理共识 在 MCP 2026 低代码平台中,元数据治理不再仅是后台管理任务,而是贯穿模型设计、组件复用、跨环境部署与合规审计的核心契约机制。平台通…...

别再只会用OpenCV的CLAHE了!手把手教你调clipLimit和tileGridSize,让车牌识别率翻倍

CLAHE参数调优实战:从默认配置到精准控制的车牌识别增强 车牌识别系统在复杂光照条件下的表现,往往决定了整个项目的成败。当你在深夜的高速公路收费站,或是昏暗的地下停车场调试系统时,是否遇到过这样的困境:明明使用…...

超越木甲换皮:《饥荒》Mod进阶——如何为自定义衣服添加保暖、回san、加速等实用属性

超越木甲换皮:《饥荒》Mod进阶——如何为自定义衣服添加保暖、回san、加速等实用属性 在《饥荒》Mod开发的世界里,单纯的外观替换已经无法满足追求深度玩法的玩家需求。当一件自定义服装不仅能改变角色形象,还能在严寒中提供温暖、在黑暗中守…...

低查重AI教材编写捷径:AI写教材工具,3天完成20万字教材!

利用AI工具编写教材:高效与创新的结合 编写教材离不开资料的支持,但传统的资料整合方法早已无法满足现代需求。以前,从教育标准到学术论文,再到教学实例,这些信息通常分散在知网、教研平台等多个地方,要想…...

STM32 FOC电机控制:手把手教你用CubeMX配置TIM1中心对齐PWM(附代码)

STM32 FOC电机控制实战:TIM1中心对齐PWM配置全解析与避坑指南 在电机控制领域,场定向控制(FOC)因其优异的动态性能和效率已成为无刷电机驱动的主流方案。而作为FOC实现的硬件基础,PWM波形的生成质量直接决定了整个系统…...

别再凭感觉了!手把手教你用KEIL MDK-ARM监控MCU栈空间使用率(附源码)

嵌入式开发实战:KEIL MDK-ARM环境下精准监控MCU栈空间使用率 在嵌入式系统开发中,栈空间管理一直是个令人头疼的问题。许多开发者习惯性地采用"凭感觉配置,出问题再调整"的被动策略,这种看似简单的方法往往导致系统在关…...

【鸿蒙深度】HarmonyOS 6.0 底层架构全景解析:从微内核到分布式软总线,为什么它能同时跑在手机和PC上?

【鸿蒙深度】HarmonyOS 6.0 底层架构全景解析:从微内核到分布式软总线,为什么它能同时跑在手机和PC上? 摘要:HarmonyOS 6.0(API 23)的发布标志着鸿蒙正式进入"全场景统一OS"阶段。本文将深入微内…...

瑞芯微RKNN开发板连不上?手把手教你排查rknn_server启动问题(附日志调试技巧)

瑞芯微RKNN开发板连接故障全攻略:从日志分析到稳定运行的深度解决方案 当你在瑞芯微RKNN开发板上部署AI模型时,是否遇到过这样的场景:所有步骤都按官方文档操作,却在最后一步收到冰冷的server connect fail错误提示?这…...

别再被btoa坑了!手把手教你用JavaScript正确处理中文Base64编码(附完整代码)

JavaScript中文Base64编码全攻略:从报错到完美解决方案 最近在调试一个用户上传功能时,遇到了一个令人头疼的问题——当用户输入中文文件名时,前端使用btoa进行Base64编码后,控制台突然抛出错误。相信不少开发者都踩过这个坑&…...

看不懂李沐,不是你笨,是路线走反了。

搞深度学习也有几年了,见过太多人踩同一个坑:看完吴恩达、学完小土堆PyTorch,兴冲冲打开李沐的《动手学深度学习》,结果第三章就开始怀疑人生。 昨天有个大一的本科生找我,说他已经把吴恩达的机器学习刷完了&#xff…...

别再踩坑了!Windows下用Conda安装PyTorch GPU版,保姆级版本对照表与避坑指南

Windows下Conda安装PyTorch GPU版终极避坑手册 刚接触深度学习的开发者,十有八九会在PyTorch GPU版本安装上栽跟头。明明按照教程一步步操作,最后torch.cuda.is_available()却返回False,这种挫败感我深有体会。本文将带你直击问题核心——版…...

2026年大模型托管平台全景图:四大平台如何重塑AI开发生态

随着大模型技术从实验室走向产业化,模型托管平台正在成为AI基础设施领域的新基建。2026年,国内大模型托管市场已经形成了以模力方舟、阿里云百炼、百度千帆和火山方舟为代表的四大主力阵营,它们各自以独特的技术路线和市场定位,共…...

OpenClaw消息镜像插件:零侵入实现消息队列监控与审计

1. 项目概述:一个消息镜像插件的诞生在构建现代分布式应用或微服务架构时,消息队列和事件驱动是解耦服务、提升系统弹性的核心手段。然而,随着系统复杂度的提升,一个常见且棘手的问题浮出水面:如何在不侵入业务逻辑、不…...