4. XCP协议入门

CCP,全称CAN Calibration Protocol,是标定领域的老兵了。我入行那会儿,它和KWP2000还在争地盘,后来CCP凭借简洁的指令集和稳定的性能,成了绝大多数ECU标定的事实标准。今天咱们就把它拆开看看,到底怎么工作的。

核心要点:CCP基于CAN 2.0A(11位ID),采用主从架构。标定工具是主设备(Master),ECU是从设备(Slave)。所有通信都围绕两种报文:CRO和DTO。

4.1 CRO与DTO:一问一答的通信基

CCP的通信模型其实很简单。主设备发一个命令,从设备回一个应答。这个请求报文叫CRO(Command Receive Object),应答报文叫DTO(Data Transmission Object)。

CRO(Command Receive Object):主设备发给ECU的命令帧。CAN ID通常是0x100(可配置)。

  • 字节0:命令码(CMD),比如0x01代表CONNECT
  • 字节1:命令计数器(CTR),每次递增,用于匹配请求和应答
  • 字节2-7:命令参数,不同命令含义不同

DTO(Data Transmission Object):ECU返回给主设备的应答帧。CAN ID通常是0x101(可配置)。

  • 字节0:数据包ID(PID),0xFF表示命令返回,0x00-0xFE表示DAQ数据
  • 字节1:错误码(ERR),0x00表示成功
  • 字节2-7:返回数据

实战小技巧:我个人习惯把CRO的CAN ID设成偶数,DTO设成奇数,这样在CANalyzer里一眼就能区分请求和应答。调试时特别方便。

4.2 CCP命令集:核心指令实战

CCP定义了大约20条命令,但日常标定常用的也就七八条。我挑几个最关键的讲。

4.2.1 CONNECT:建立连接

这是第一条命令,没有它什么都干不了。主设备发送CONNECT命令,ECU返回一个包含协议版本和站址的应答。

// CONNECT命令格式
CRO: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
     CMD  CTR  STATION_ADDRESS(4字节)

// 成功应答
DTO: 0xFF 0x00 0x01 0x10 0x00 0x00 0x00 0x00
     PID  ERR  PROT_VER  RESOURCE

这里有个坑。我曾经遇到过一台ECU,CONNECT命令发出去死活没反应。查了半天,发现是站址(Station Address)没对上。ECU出厂默认站址是0x00,但有些供应商会改成0xFF。所以第一次连接时,我建议你从0x00开始,不行就换0xFF试试。

4.2.2 GET_DAQ_SIZE:查询DAQ内存大小

在配置DAQ模式之前,必须先知道ECU能分配多少ODT(Object Descriptor Table)条目。这个命令就是干这个的。

// 查询DAQ大小
CRO: 0x14 0x01 0x00 0x00 0x00 0x00 0x00 0x00
     CMD  CTR  DAQ_LIST_NUMBER

// 应答
DTO: 0xFF 0x00 0x20 0x00 0x00 0x00 0x00 0x00
     PID  ERR  ODT_SIZE  ODT_ENTRIES

ODT_SIZE表示每个ODT能放几个信号,ODT_ENTRIES表示总共有几个ODT。两者相乘就是最大可标定信号数。嗯,这里要注意,有些ECU的ODT_ENTRIES是0,说明它不支持DAQ模式,只能用POLLING。

4.2.3 SET_DAQ_LIST_MODE:启动DAQ采集

这是DAQ模式的核心命令。配置好ODT后,用这个命令启动数据采集。

// 启动DAQ列表
CRO: 0x1C 0x02 0x00 0x01 0x00 0x00 0x00 0x00
     CMD  CTR  LIST_NUM  MODE  EVENT_CHANNEL

// MODE参数:
// 0x00 - STOP
// 0x01 - START
// 0x02 - PREPARE

我踩过的一个坑:MODE参数用0x01直接启动,结果ECU没准备好ODT配置,直接报错。正确的做法是先发PREPARE(0x02),等ECU确认后再发START(0x01)。

4.3 DAQ模式 vs POLLING模式

这两种模式是CCP最核心的设计。说白了,就是数据怎么从ECU里拿出来的问题。

特性 DAQ模式 POLLING模式
触发方式 事件驱动(周期/角度/状态) 命令驱动(主设备主动请求)
数据速率 高,ECU主动发送 低,一问一答
总线负载 固定,可预测 随请求频率变化
适用场景 实时监控、数据记录 参数标定、单次读取
配置复杂度 高,需配置ODT 低,直接发命令

4.3.1 DAQ模式:ECU主动上报

DAQ模式下,ECU按照预设的事件(比如每10ms、每曲轴转一圈)自动发送DTO。主设备只需要在开始时配置好ODT,之后就可以坐等数据了。

ODT的结构是这样的:每个ODT条目指向ECU内存中的一个地址,长度可以是1、2、4字节。ECU在事件触发时,把ODT指向的所有数据打包成一个DTO发出来。

注意:DAQ模式虽然效率高,但会占用CAN总线带宽。我曾经在一个项目里,同时开了8个DAQ列表,每个列表10ms周期,结果总线负载直接飙到60%。后来不得不把一些不关键的信号改成POLLING模式。

4.3.2 POLLING模式:主设备主动查询

POLLING模式就简单多了。主设备发一条UPLOAD命令,ECU返回数据。想读哪个地址,直接指定就行。

// 读取地址0x8000处的4字节数据
CRO: 0x23 0x03 0x00 0x80 0x00 0x04 0x00 0x00
     CMD  CTR  ADDRESS(3字节)  SIZE

// 应答
DTO: 0xFF 0x00 0x12 0x34 0x56 0x78 0x00 0x00
     PID  ERR  DATA(4字节)

POLLING模式的缺点很明显:慢。发一条命令等一个应答,来回至少2ms(假设500kbps CAN)。读10个信号就要20ms。所以它只适合标定参数的单次读写,不适合实时监控。

4.4 两种模式的混合使用

实际项目中,没人只用一种模式。我通常的做法是:

  1. 标定阶段:用POLLING模式读写标定参数,比如扭矩限制、点火角
  2. 监控阶段:用DAQ模式采集关键信号,比如转速、水温、爆震强度
  3. 调试阶段:两种模式同时用,DAQ跑后台,POLLING读临时变量

但要注意,CCP协议规定同一时刻只能有一种模式处于激活状态。所以切换时需要先停止DAQ,再切到POLLING,或者反过来。

我的经验:在CANape里配置DAQ时,把周期信号和事件信号分开。比如转速用10ms周期,爆震用曲轴角度触发。这样既能保证实时性,又不会浪费总线带宽。

CCP通信模式工作流程 主设备(标定工具) 从设备(ECU) CAN总线 选择工作模式 DAQ模式(ECU主动上报) POLLING模式(主设备查询) 1. 配置ODT(SET_DAQ_LIST_MODE) 2. 启动DAQ列表(START) 3. ECU按事件自动发送DTO 1. 主设备发送UPLOAD命令 2. ECU返回DTO应答 3. 主设备解析数据 两种模式不能同时激活,切换前需停止当前模式

4.5 避坑指南

最后分享几个我踩过的坑,希望能帮你少走弯路。

坑1:DAQ列表编号从0开始

有些ECU的DAQ列表编号从0开始,有些从1开始。我曾经在项目里用0号列表,结果ECU死活不响应。后来查手册才发现,那款ECU的列表编号从1开始。所以拿到新ECU,第一件事就是看它的CCP实现手册。

坑2:ODT配置顺序不能乱

配置ODT时,必须先写ODT条目,再写ODT列表。顺序反了,ECU会报错。我见过一个同事,调了两天没搞定,最后发现是顺序问题。

坑3:CAN ID冲突

如果总线上有多个ECU,CRO和DTO的CAN ID可能会冲突。我建议在标定工具里为每个ECU分配独立的CAN ID范围,比如ECU1用0x100/0x101,ECU2用0x102/0x103,以此类推。