疑惑
问:发 1 帧报文,最多 TEC+8吗
答:错,报文传输过程中,每检测到一个总线错误,都会触发一次 TEC 累加。 一整帧 CAN 报文很长(SOF+ID+DLC + 数据 + CRC+ACK),只要总线波形畸变,这一帧报文在传输途中会连续报好几个填充错误,每检出 1 个错误,TEC 就 + 8
问:为什么tec和rec最大只有128
答:硬件限制寄存器使用7bit,f1/4有这个限制,h7没有。所以f1/4不会进入BusOff
注意:重定向printf要打开Micro LIB
CAN-1:双节点基础通信
参数:sFilterConfig.SlaveStartFilterBank = 14;
含义:(硬件基础要有两个CAN)
- CAN1(主)使用过滤器0 ~ 13(一共 14 组)
- CAN2(从)使用过滤器14 ~ 27(一共 14 组)
启动CAN接收通知(开启接收中断)
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
CAN-2:使用DBC
DBC 全称:Database CAN
简单一句话:DBC 是 CAN 总线的报文描述文件(后缀.dbc),是车载 CAN 的 “翻译字典”,由 Vector 公司定义的文本格式。
核心作用
CAN 总线原始传输的只有十六进制字节流,比如:ID:0x123 Data: 08 00 40 1F ...单纯看这串数字,你不知道哪几个字节代表发动机转速、水温、车速。 DBC 文件里面写好了一套规则,用来把原始 CAN 数据翻译成工程值(物理量)。
DBC 里面存了哪些信息
- Message(报文)
- 报文 ID、报文名称、周期(周期报文)、数据长度 DLC
- 例如:
EngineMsg : 0x0A0, DLC=8
- Signal(信号)
- 信号名称:
EngineRPM、VehicleSpeed - 起始位、信号长度、字节序 (Intel/Motorola)、数据类型 (有符号 / 无符号)
- 缩放因子、偏移量:
物理值 = 原始值 × 缩放 + 偏移 - 最小值、最大值、单位(RPM、km/h、℃)
- 信号名称:
- 附加内容:注释、节点(Node,ECU)、值表(枚举,比如 0 = 关闭,1 = 开启)
DBC 基础语法结构
DBC =Database CAN,CAN 总线数据库文件,纯文本,后缀
.dbc,ZCANPRO 可以直接导入,自动解析 CAN 报文、信号、缩放偏移。规则:信号位序是 Motorola (大端)/Intel (小端),车载常用 Motorola(ZCANPRO 里可以选择字节序)
1. 文件头部信息段(必写)
VERSION "demo_can" NS_ : NS_DESC_ : CM_ : BA_DEF_ : BA_ : VAL_ :| 关键字 | 英文全称 | 作用 |
|---|---|---|
VERSION | Version | DBC 版本名称,字符串,随便写,ZCANPRO 仅展示 |
NS_ | Namespace | 命名空间,固定写NS_ :,DBC 标准保留,几乎不用改 |
NS_DESC_ | Namespace Description | 命名空间描述,一般空着 |
CM_ | Comment | 注释,给报文 / 信号加说明文字 |
BA_DEF_ | Attribute Definition | 属性定义,自定义 DBC 的属性(如报文周期、ECU 名称) |
BA_ | Attribute | 属性值,给上面定义的属性赋值 |
VAL_ | Value | 信号枚举值,比如 0=Off,1=On,ZCANPRO 解析后显示文字而不是原始数字 |
2. 节点定义BU_
BU_=Bus Unit总线单元,代表总线上的 ECU(节点) 语法:
BU_: ECU1 CANAnalyzer含义:总线上有 2 个节点:ECU1(STM32)、CANAnalyzer(ZCANPRO 分析仪)
注意:名字不能有空格
BU_后面跟所有参与 CAN 收发的 ECU 名称。
3. 报文定义BO_【核心!BO = Message / Board Message】
BO_=Board Object报文对象,代表一帧 CAN 报文 语法模板:
BO_ 100 EngineMsg: 8 ECU1 SG_ EngineRPM : 0|16@0+ (1,0) [0,8000] "rpm" CANAnalyzer SG_ Temp : 16|8@0+ (1,-40) [-40,125] "degC" CANAnalyzerBO_ 行拆解
BO_ 100 EngineMsg: 8 ECU1
BO_:Board Object,报文起始标记100:CAN ID,十进制!注意 DBC 里 ID 默认十进制,不是十六进制!CAN ID 0x100,DBC 里要写 256,ZCANPRO 导入这点很容易踩坑
EngineMsg:报文名称,自定义8:报文数据长度 DLC,0~8,CAN2.0 最多 8 字节ECU1:发送该报文的节点(发送方 ECU)
SG_ 信号行 SG = Signal
SG_ EngineRPM : 0|16@0+ (1,0) [0,8000] "rpm" CANAnalyzerSG_=Signal信号,报文中提取的一个物理量
表格
| 片段 | 含义 | ||
|---|---|---|---|
EngineRPM | 信号名 | ||
| `0 | 16` | ` 起始位 | 信号长度 bit`,从 bit0 开始,占 16bit |
@0 | 字节序:0=Motorola 大端;1=Intel 小端(车载 CAN 大多 Motorola) | ||
+ | 符号:+= 无符号 unsigned;-= 有符号 signed | ||
(1,0) | (缩放因子Factor,偏移Offset)物理值 = 原始整数 × Factor + Offset | ||
[0,8000] | 物理值范围[最小值,最大值],ZCANPRO 用来校验 | ||
"rpm" | 单位字符串 | ||
CANAnalyzer | 接收这个信号的节点(接收方 ECU) |
Motorola (大端 @0):高位放在低字节,车载 ECU 最常用,ZCANPRO 解析车载 DBC 默认这个。 Intel (@1):小端,低位放低字节,单片机裸机代码常用。
注释 CM_ (CM=Comment)
CM_ "发动机报文,周期100ms";CM_ SG_ 100 EngineRPM "发动机转速";给报文或者信号写备注,ZCANPRO 里可以看到说明。
4. 属性定义 BA_DEF_ / BA_(BA=Attribute)
常用:定义报文周期,ZCANPRO 可以读取周期信息
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 5000; BA_ "GenMsgCycleTime" BO_ 100 100;BA_DEF_ BO_ "GenMsgCycleTime" INT 0 5000;BA_DEF_ = Attribute Definition,定义一个报文属性GenMsgCycleTime(报文周期),整数,范围 0~5000msBA_ "GenMsgCycleTime" BO_ 100 100;BA_ = Attribute,给 ID=100 报文赋值:周期 100ms,ZCANPRO 可以展示报文周期
5. 枚举 VAL_ (VAL=Value)
信号数值映射文字,ZCANPRO 解析直接显示文本,不用看原始数字
VAL_ 100 Gear 0 "N" 1 "D" 2 "R" ;含义:报文 ID100 里的信号 Gear,0=N 挡,1=D 挡,2=R 挡。
6. 完整可直接导入 ZCANPRO 的最小 DBC 示例
新建文本,复制下面全部内容,保存为demo.dbc,直接拖进 ZCANPRO 即可
VERSION "DemoCAN" NS_ : NS_DESC_ : CM_ : BA_DEF_ : BA_ : VAL_ : BU_: ECU1 CANAnalyzer BO_ 256 EngineMsg: 8 ECU1 SG_ EngineRPM : 0|16@0+ (1,0) [0,8000] "rpm" CANAnalyzer SG_ EngineTemp : 16|8@0+ (1,-40) [-40,125] "degC" CANAnalyzer CM_ BO_ 256 "发动机周期报文,100ms"; CM_ SG_ 256 EngineRPM "发动机转速"; BA_DEF_ BO_ "GenMsgCycleTime" INT 0 5000; BA_ "GenMsgCycleTime" BO_ 256 100;错误解析
前置重要说明:
ZCANPRO 里的消极错误是软件中文翻译名词,≠ CAN 协议的被动错误状态 (Error Passive)。
CAN 协议规定两大类错误事件:
①仲裁丢失(Arbitration Lost):属于总线仲裁竞争失败,独立一类,不属于 “消极错误”;
②CAN 标准 5 类总线错误(消极错误字段描述的就是这 5 种):位错误、位填充错误、CRC 错误、ACK 错误、格式错误。 所以日志里会分成两组独立字段:消极错误相关字段+仲裁错误段表示,分开记录两类不同故障。
一、基础公共字段
- 序号:错误事件的流水编号,0、1 代表第 0、1 条捕获到的总线错误
- 源设备类型:USBCAN-II,代表这条错误是周立功 USBCAN-II 分析仪硬件采集上报
- 源设备 / 源通道:设备 0,通道 0 → 使用分析仪的第 0 号 CAN 通道抓包
- 时间:ZCANPRO 本地时间戳,捕获到这个错误的时刻
- 节点状态:CAN 节点错误状态机(CAN 2.0A/B 协议标准)
- 主动状态 (Error Active):TEC<128,REC<128。节点可以正常收发报文;发送出错 TEC+8。
- 被动状态 (Error Passive):TEC≥128 或 REC≥128。节点不能主动发送报文,只能接收;发送失败 TEC 只 + 1。
- 总线关闭 (BusOff):TEC≥256,彻底脱离总线,只能接收复位后恢复。
你的日志:TEC=127 还在主动;发生一次仲裁丢失,TEC+1 变成 128 → 切换被动状态。
- REC:Receive Error Counter,接收错误计数器收到报文出错时增加。你这里 REC 一直 = 0:接收报文全部正常,接收侧没有任何错误。
- TEC:Transmit Error Counter,发送错误计数器节点发送报文失败时增加。你的错误全部来自发送侧,所以 TEC 持续上涨,REC 不变。
二、【错误码】字段
含义:USBCAN-II 硬件寄存器原始错误值,是 CAN 控制器 ESR(错误状态寄存器)读取出来的十六进制原始数据,ZLG 硬件自定义编码。
0x00000004:仲裁丢失事件(Arbitration Lost)0x00000010:发送错误标记,TEC 计数达到被动阈值后上报
作用:底层原始编号,用来区分错误大类,软件根据这个值解析后面的文字描述。
三、【消极错误代码类型】
针对5 类标准 CAN 总线错误做分类编号:位错误、位填充错误、CRC 错误、ACK 错误、格式错误。 编号
1=其它错误
- 什么时候不是其它错误:如果是位错误,这里会显示【位错误】;ACK 丢失就显示【ACK 错误】。
- 本次场景:错误是仲裁丢失,仲裁丢失不属于这 5 类标准消极错误,所以归类为「其它错误」。
四、【消极错误属性】
标记这个标准总线错误发生在发送流程还是接收流程
0:发送错误:错误发生在节点向外发送报文的过程,对应 TEC 累加1:接收错误:错误发生在接收报文,对应 REC 累加
你的日志全部是
0:发送错误,代表所有错误都是发送报文的时候产生。
五、【消极错误段表示】
含义:仅针对 5 类标准 CAN 消极错误,记录错误发生在报文哪一段 CAN 报文分段:SOF 起始帧、仲裁段、控制段、数据段、CRC 段、ACK 段、EOF 帧结束。
- 如果是 ACK 错误,这里会标记在 ACK 段;位错误发生在数据段,就标记数据段。
- 重点:仲裁丢失不属于消极错误,所以这个字段填充
0 00000,代表【无标准消极错误】,这个字段无效。
六、【仲裁错误段表示】(独立字段,和消极错误分开)
专门用来记录仲裁丢失的位置,仲裁丢失是独立于消极错误的一类事件。 你的日志:
丢失在位位:1含义:节点发送报文时,在仲裁段第 1bit发生仲裁丢失。 原理: CAN 发送时,发送节点一边发,一边采样总线电平回读对比。 本节点发出隐性电平 1,但是总线被其他节点拉成显性电平 0。 CAN 规则:0 优先级高于 1,本节点输掉仲裁,立刻停止发送报文,TEC 计数增加。 你这个场景:STM32 和 USB-CAN 分析仪同一时刻同时发送报文,ID 仲裁冲突,在仲裁段第 1bit 输掉仲裁。
CAN周期报文设计
ID 分配
ID 分配实际上是在进行通信优先级设计
发送调度
实质上:管理“什么时候把哪些 CAN 报文交给 CAN 控制器发送”
抖动控制(jitter)
实际发送时间相对于理想时间存在变化
为什么会产生抖动:仲裁等等...
rolling counter
作用:让接收方知道报文是否连续到达,检测是否有丢帧、重复、乱序
checksum
含义:根据报文中的数据计算一个校验值,并把这个校验值也放进报文
为什么需要Checksum:不是 CRC 不好,是看安全等级、成本、算力、规范继承。低安全等级场景,Checksum 足够用,而且更简单、更快、更容易标准化,所以 AUTOSAR 专门保留了 E2E Profile1(RollCnt+Checksum)。