ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CANoe实战:ISO15765多帧传输原理与VIN读取报文解析

CANoe实战:ISO15765多帧传输原理与VIN读取报文解析 干过几年车载总线测试的人都知道只要跟UDS诊断打交道CANoe基本是绕不开的家伙。ISO15765这几个字听起来挺唬人但它本质上解决一个问题CAN总线一帧只能塞8个字节诊断数据动不动就是几十个字节怎么传ISO15765规定了一套“拆包-打包”的规则业内常叫它ISO-TP。很多人第一次在Trace里看到一堆以 10、21、30 开头的帧直接懵掉——明明我发的是个读VIN的请求怎么总线上回了一大串这篇文章就专门把这层窗户纸捅破。我会用CANoe作为分析工具从ISO15765多帧传输的帧结构讲起再到如何配置CANoe的传输层最后用一次读取VIN17字节数据的真实报文逐字节拆给你看。无论你是刚接触ECU测试的应届生还是被诊断报文折磨过的老同志照着走一遍下次再看到带多帧传输的Trace心里会踏实很多。1. 多帧传输到底在解决什么问题1.1 为什么会有ISO15765CAN总线最早是给控制信号设计的像转速、油门、刹车这类量一帧8字节绰绰有余。但后来车厂开始做诊断和刷写要把“读取故障码”“写入配置”“更新固件”这种动辄几十上百字节的数据塞进CAN8字节显然不够用。总不能为了一次诊断就前前后后发十几帧原始数据吧接收方怎么知道哪些帧属于同一个消息哪一帧在前、哪一帧在后中间断了怎么办于是ISO 15765-2成了事实标准它定义了一种传输协议也就是我们常说的ISO-TP。它把上层的数据拆成多帧加上标识信息按顺序发出去接收方再把这些帧拼成完整数据。CANoe里很多诊断报文显示成一条“Diagnostic”消息底层其实是ISO-TP在背后自动拆装。1.2 四种帧类型的“角色分工”ISO-TP用四种帧类型完成整个多帧流程单帧SF数据长度不超过7字节经典CAN直接用一帧传完。首帧FF数据长度超过7字节时第一帧先发出去里面带着总长度和首段数据。流控帧FC接收方收到首帧后返回一个“允许发送”的指令里面携带BS、STmin等参数。连续帧CF发送方按流控帧的指示一帧一帧把剩余数据发完。这四种帧靠第一个字节的PCI协议控制信息区分。PCI高四位是帧类型标识例如0x0代表单帧0x1代表首帧0x2代表连续帧0x3代表流控帧。在CANoe的Trace窗口里你往往会看到“SF/FF/FC/CF”的缩写要能一眼认出来。1.3 物理寻址与功能寻址ISO15765的寻址通常分两种物理寻址点对点比如测试仪发给某个ECU请求ID一般是0x7E0响应ID是0x7E8。这种最常用。功能寻址广播一个请求发给多个ECU常用ID是0x7DF。功能寻址一般只用于请求不用于响应。CANoe里配置传输层的时候要分清这两种寻址对应的CAN ID。很多人配置错误导致收不到响应多半是物理寻址ID没配对。2. 实战前必须搞定的CANoe环境配置2.1 我推荐的CANoe配置方式先说一下环境。我用的是CANoe 16/17系列接口有VN1640和虚拟CAN通道。如果你只是想学多帧报文分析不一定非要真实硬件CANoe自带的虚拟CAN总线也能跑通整个流程。安装的时候务必确认装了“Diagnostics”相关组件部分功能需要授权没授权的话诊断窗口会用不了。新建工程时选择CAN总线配置两条虚拟通道Channel1和Channel2。用CANoe的“Simulation Setup”把通道连接起来再加上一个DBC文件定义好节点和报文。没有DBC也可以先裸发CAN帧但解析不出ISO-TP消息所以建议老老实实建一个基础DBC。DBC我用CANdbVector自带的数据库编辑器创建。典型配置是定义两个节点Tester测试仪和ECU然后定义物理请求报文ID0x7E0物理响应报文ID0x7E8。ISO-TP本身不强制这些ID具体是什么值但UDS诊断领域约定俗成大部分OEM都沿用这套逻辑。2.2 配置传输层的关键步骤DBC建好后在CANoe的“Diagnostics/ISO TP”区域右键添加一个ISO TP传输对象。这里要设置发送ID和接收ID请求ID 0x7E0响应ID 0x7E8。寻址类型物理寻址。协议类型ISO 15765-2CAN。处理模式可以把“对完整帧进行重组”打开这样在Diagnostic窗口里看到的是一条完整诊断响应而不是一堆拆分后的裸CAN帧。这一步最容易踩的坑是“诊断描述文件CDD”。CANoe诊断控制台加载CDD后可以直接用服务名发诊断请求非常方便。但如果手头没有CDD也可以手动发送CAN帧靠CANoe的TP层去拆包。两种方式我都会在实战里覆盖到。2.3 Trace窗口和过滤技巧ISO-TP报文在Trace里非常刷屏尤其是发送几十个字节的多帧响应一秒钟可能几十条CF帧。我的习惯是先把Trace窗口的默认列配置好查看CAN ID、数据场、帧类型、绝对时间、相对时间这几列再打开设置里的“右键过滤”功能。点击Trace窗口工具栏上的“Display Filter”图标可以只显示请求ID和响应ID或者只显示ISO-TP相关报文。不要在一堆其他网络管理、应用报文里找诊断帧效率太低。还可以在“Write Window”里用CAPL脚本打印关键信息比如打印收到的完整多帧数据分析速度更快。3. 手把手实战用VIN读取把多帧报文拆明白3.1 一个真实的读取VIN全过程我以一个ECU返回VIN码的场景为例。UDS服务是22读数据DID是F190VIN。请求数据是22 F1 90只有3个字节CAN单帧完全能装下所以请求帧只发一个单帧方向帧类型CAN IDData请求SF0x7E002 22 F1 9002是单帧PCI代表单帧且数据长度为2字节后边跟22 F1 90。这个请求没有任何悬念一帧就完事了。重点在响应。假设ECU返回的VIN是ABC123XYZ45678901ASCII码一共17个字节。UDS响应数据为62 F1 902字节DID 1字节服务响应再加上17字节VIN总共20字节。20字节超过了7字节所以必须走ISO-TP多帧。3.2 首帧FF怎么解析ECU发送的第一帧如下方向帧类型CAN IDData响应FF0x7E810 14 62 F1 90 41 42 43首帧PCI的格式是第一个字节高四位为1表示首帧低四位是完整数据长度的bit11~bit8第二个字节是完整数据长度的bit7~bit0。所以10 14拼接得到长度0x014也就是20字节正好是将来重组后的完整响应长度。首帧数据区只有6字节放的是完整响应最前面的6个字节62响应服务ID与请求的22服务对应。F1 90DID字段。41、42、43就是VIN里最前面的三个字符A B C。所以这条首帧的完整含义就是我要传20字节数据前6字节我已经发给你了下面是后面14字节等我收到流控帧再安排节奏。3.3 流控帧FC怎么解析ECU发完首帧后正常不会立刻继续发连续帧。它必须先等测试仪Tester回一个流控帧告诉它“你按这个节奏来发”。测试仪收到首帧后回一个流控帧方向帧类型CAN IDData请求FC0x7E030 00 00流控帧PCI的第一个字节高四位是3代表流控帧。低四位叫FSFlow Status0Continue继续发。1Wait先等着。2Overflow接收缓冲区溢出丢弃本次传输。示例里的FS0表示可以继续。第二个字节是BSBlock Size表示允许发送方连续发送的连续帧数量。BS0是个特殊值表示“不限帧数一口气发完”。第三个字节是STminSeparation Time min表示两个连续帧之间的最小时间间隔。STmin0x00代表不强制额外延时但很多工具还是会留一点间隔避免CAN发送缓冲溢出。3.4 连续帧CF的序号和数据拼接收到FC后ECU开始连发剩余的连续帧。完整响应的20字节中首帧已经带了6个还剩14个字节刚好分成两个连续帧每个7字节第一帧CF方向帧类型CAN IDData响应CF0x7E821 31 32 33 58 59 5A 34PCI第一个字节高四位是2表示连续帧低四位是序列号SN。第一个连续帧的SN通常是1部分协议栈也有从0开始的后续会聊到。数据区放的是后续7个字节31 32 33 58 59 5A 34也就是ASCII字符1 2 3 X Y Z 4。第二帧CF方向帧类型CAN IDData响应CF0x7E822 35 36 37 38 39 30 31SN2数据区是剩余7个字节35 36 37 38 39 30 31也就是5 6 7 8 9 0 1。接收方拿到FFCF1CF2后按顺序把数据区拼接起来FF数据6字节62 F1 90 41 42 43CF1数据7字节31 32 33 58 59 5A 34CF2数据7字节35 36 37 38 39 30 31拼起来就是62 F1 90 41 42 43 31 32 33 58 59 5A 34 35 36 37 38 39 30 31转成ASCII就是ABC123XYZ45678901。到这里一次完整的多帧响应就解析完了。3.5 传输参数的计算逻辑有人会问BS和STmin怎么选简单说BS决定“发几帧停一下”。BSN表示发送方每发N个连续帧后必须等接收方重新发一个FC才继续。STmin决定“帧与帧之间的最小时间”。如果ECU接收处理速度慢STmin就要给大一点如果太快又会造成总线负载升高。STmin的具体含义还要注意单位。0x00到0x7F表示0到127ms0x80到0xF0时单位变成100us比如0xFA其实不是标准值。常见的10是1ms32是5ms64是10ms。实际项目中STmin会根据ECU底层驱动能力来确定。CANoe的诊断传输层配置里可以直接选配置完它会自动生成对应的FC参数。4. 多帧传输常见的坑现象与排查做过几轮诊断测试后你会发现多帧传输的问题翻来覆去就那么几个。我整理了一份在CANoe环境下的避坑经验按出现频率排序。4.1 看不见首帧或连续帧Trace里全是裸CAN帧很多时候明明发了20字节的响应Trace窗口里却看不到带有10、21、30的报文反而看到一串完整的原始数据被拆成8字节一条的CAN帧。这是CANoe把ISO-TP层“帮助”了它默认重组了完整消息并且在Diagnostics窗口和Trace里只展示重组后的结果。解决方法是到Trace窗口的“Display”里打开ISO-TP的详细模式或者直接在报文列表里看“CAN TP”列。如果你希望看到传输层的裸帧可以右键“ISO TP”选项选择“show transport protocol frames”。不要误以为ECU没发多帧其实数据早就到了。4.2 发完FF后一直没有FC响应典型的故障是ECU发完首帧后测试仪不回复流控帧。排查顺序如下检查故障注入是不是CAPL脚本或者DBC里把流控帧屏蔽了。检查地址ID确认请求ID和响应ID配对是否正确。检查诊断协议配置CANoe的ISO TP传输层如果发送ID和接收ID设置反了收到的FF会被当成无效帧丢弃。检查超时时间CANoe默认的N_As/N_Bs超时是1秒如果测试仪没来得及解析也会出现超时。这个坑最隐蔽的地方在于很多新手用CDD和诊断窗口发送请求时CANoe会自动帮你回FC但如果你直接用“CAN IG”面板手动发送帧CANoe不会自动回流控帧此时ECU发完FF就一直等最终超时报N_Bs超时。所以我建议纯学习阶段就用诊断窗口或CAPL来走完整流程别用手动CAN发送去模拟测试仪。4.3 CF序号为什么不是从0开始我在拿到首帧之后见过很多人在Trace里盯着第一个连续帧的SN看。有人收到21开头的帧就会问为什么不是20ISO15765标准里SN是一个4位循环计数器从0到15循环。但在标准实现中首帧之后第一个连续帧的SN通常从1开始后续依次递增。部分工具或协议栈会从0开始这个在判断时会有歧义。我的经验是不要纠结起始值重点检查连续帧的SN是否连续。如果中间出现跳号比如前面是SN3后面直接SN5那基本可以判定丢帧需要做重传处理。CANoe在重组时如果发现SN不连续会在Trace里显示错误或者直接超时。你可以在诊断窗口的“Trace Filter”里勾选“Protocol errors”快速定位这类问题。4.4 BlockSize与STmin搭配出问题有时候首帧发完流控帧也回得很快但连续帧发了几帧就停了。这时候排查BS和STmin的取值。BS3代表每发3个CF就要等接收方再发一次FC。如果接收方迟迟不发第二个FC传输就卡住。BS0虽然不限次数但工程上不建议在复杂的CAN网络中无脑设0因为一旦总线拥堵要么出错误帧要么接收方缓冲区溢出。STmin设置太小时比如0x00连续帧之间几乎没有间隔。如果ECU底层写Flash或者做校验可能来不及处理导致后续CF被丢弃。一般项目里STmin至少设到0x0A10ms。在CANoe里可以通过“CAN Statistics”窗口看到总线负载和错误帧情况如果错误帧多先怀疑STmin。4.5 常见问题速查表现象可能原因解决方向Trace只显示重组后的诊断消息CANoe默认合并TP层开启“show transport protocol frames”发完FF后无FC手动发送帧导致无流控响应改用诊断窗口或CAPL报文接收超时N_BsFC未返回或超时参数过短检查ID、协议配置和超时时间连续帧SN跳变丢帧或总线错误检查STmin和BS查看错误帧响应长度与实际不符FF中的长度计数错对照FF的12位长度字段重新计算功能寻址收不到响应功能寻址不能用于响应请求用0x7DF响应必须物理寻址0x7E85. 进阶玩法与个人心得5.1 用CAPL脚本自动发送并校验多帧手动发一次UDS请求没有问题但做压力测试和自动化回归时就要用CAPL来跑。我常用的套路是用diagSetP2Parameter设置超时。用diagSendRequest发送CDD里定义好的诊断请求。通过on diagResponse回调接收完整响应。在回调里用diagGetParameter解析响应中的VIN字节并比对预期值。用CAPL的好处是你不需要关心底层拆包拼包逻辑CANoe的协议栈已经把FF/CF/FC全部处理好了。它会给你一个完整响应的字节数组直接用MemCmp做结果校验。批量刷写、反复读写DID的自动化脚本基本都是这个思路。5.2 与Python联合测试的扩展有些团队习惯用Python控制CANoe做集成测试。可以用CANoe的COM接口启动工程、发送诊断请求、读取响应。比如调用CANoe.Application对象再通过Diagnostic对象触发请求这样就能在Python测试框架里跑诊断自动化。不过这种方案对CANoe版本依赖较强COM接口偶尔会因为版本不匹配出幺蛾子。如果是学习阶段先用CAPL把逻辑调通再考虑Python封装。5.3 一个调试小技巧最后分享一个我压箱底的小技巧。排查多帧传输问题时我习惯在Trace窗口添加两列Ack和Error。当某个CF帧出现CRC或ACK错误时这两列会标红立刻能定位到物理层干扰。很多时候你以为ISO-TP配置不对其实是总线上丢帧。另外CANoe的“Graphics Window”配合ISO-TP层可以把BS和STmin的时序可视化。调了几次参数后你会对“STmin1ms和5ms的实际总线效果”有直观感觉。这些参数的变化用肉眼很难看出来但图形曲线骗不了人。根据我个人经验ISO15765多帧传输真正难的不是协议本身而是你第一次面对一堆看似杂乱帧时的心态。记住每类帧的角色FF是报幕员FC是交通指挥CF是跑腿的SF是一句话能说完的事。用CANoe多看几次真实报文多拆几轮字节这个坎很快就能迈过去。
返回列表