如何在 Davinci Configurator 中精准配置 UDS 28 服务的激活条件?
你有没有遇到过这样的场景:OTA 刷写时总线突然“卡死”,或者某个节点在不该发报文的时候疯狂发送周期信号?排查到最后发现,竟然是因为通信没有正确隔离。这时候,UDS 28 服务(Communication Control Service)就该登场了。
作为 ISO 14229 标准中控制 ECU 通信行为的核心手段,28 服务就像一个“通信闸门”——允许我们在特定条件下启用或禁用 CAN 报文的收发。尤其是在进入编程模式、执行软件刷新或进行深度诊断时,它能有效避免非必要通信对关键流程的干扰。
但在实际开发中,很多人虽然知道要用 28 服务,却不清楚如何在Davinci Configurator这类 AUTOSAR 配置工具中正确设置其激活条件。结果导致服务无法触发、响应 NRC 错误码,甚至引发误操作风险。
本文将带你深入剖析 UDS 28 服务的本质机制,并以 Vector 的 Davinci Configurator 工具链为依托,手把手教你完成从协议理解到工程落地的全过程配置,确保你的诊断系统既安全又可控。
为什么我们需要 UDS 28 服务?
先别急着打开 Davinci,我们得先搞清楚一个问题:为什么不能直接通过关闭 CAN 控制器来实现通信静默?
答案是:粗暴。
传统方式往往是硬编码调用Can_SetControllerMode(OFFLINE)或逐条禁用 PDU 路由,这类做法存在几个致命问题:
- 粒度太粗:一关全关,连 NM 心跳和应用报文一起掐断;
- 缺乏标准接口:不同供应商实现不一致,测试工具难以兼容;
- 无权限校验:任何人都可以随意切断通信,安全隐患极大;
- 不可恢复性:掉电后状态丢失,重启可能仍处于“失联”状态。
而 UDS 28 服务正是为了解决这些问题而生。它提供了一套标准化、可配置、带权限控制的通信管理机制,真正做到了“想关就关,但必须合法”。
简单说:28 服务不是让你“能不能通信”,而是决定“谁、在什么状态下、能控制哪一部分通信”。
28 服务到底怎么工作?拆开看看
它长什么样?
一条典型的 28 服务请求帧如下:
28 02 0128:服务 ID(SID),表示 Communication Control02:子功能(Sub-function),这里是 Disable Communication01:通信类型掩码(ComType),表示 Normal Communication
这个命令的意思就是:“请禁用本节点的所有正常通信(包括发送与接收)”。
支持的子功能通常包括:
-0x01— Enable Communication
-0x02— Disable Communication
- (部分扩展)0x03— Enable Rx / Disable Tx
- (部分扩展)0x04— Disable Rx / Enable Tx
通信类型掩码则定义了你要控制的报文类别,常见位分配如下:
| Bit | 含义 |
|---|---|
| 0 | 正常通信报文(Normal Communication Messages) |
| 1 | 网络管理报文(NM Messages) |
| 2 | 保留 |
| 3 | 系统等效相关报文(厂商自定义) |
你可以组合使用,比如0x03表示同时控制正常通信和 NM 报文。
它是怎么被执行的?
当诊断仪发出28 02 01请求后,ECU 内部会经历一系列协同处理:
- CAN 接收层捕获原始帧,交由 PduR 路由至 Dcm 模块;
- Dcm 模块解析 SID 是否为
0x28,确认是通信控制服务; - 会话检查:当前是否处于允许执行该操作的诊断会话(如 Extended Session)?
- 安全访问检查:是否已通过 Security Access(例如 Level 3)解锁?
- 若全部通过,调用用户注册的回调函数(如
Dcm_EnableCommunication()); - 回调函数内部调用 ComM、CanIf 等模块 API 实际执行通信使能/禁止;
- 最终返回正响应
68 xx或负响应(如7F 28 22表示条件不符)。
整个过程看似简单,但任何一个环节配置错误都会导致失败。尤其是第 3 和第 4 步——也就是我们常说的“激活条件”。
在 Davinci Configurator 中如何配置这些“开关”?
现在,正式进入实战环节。我们要在 Davinci 中一步步配置好 28 服务的完整行为逻辑。
第一步:开启服务本身
所有 UDS 服务都在Dcm(Diagnostic Communication Manager)模块中统一管理。要启用 28 服务,首先需要激活对应的功能组件。
路径导航:
Dcm → DcmConfigSet → DcmDsp → DcmDspControlDtcSetting找到参数DcmDspControlDtcSettingEnabled,将其设为true。
这相当于告诉 Dcm:“我打算用 28 服务,请准备好处理它的请求。”
同时,在DcmDspSidControlDtcSettingSubFuncTable中添加支持的子功能,例如:
<DcmDspSidControlDtcSettingSubFunc>0x01</DcmDspSidControlDtcSettingSubFunc> <DcmDspSidControlDtcSettingSubFunc>0x02</DcmDspSidControlDtcSettingSubFunc>这样,Dcm 就知道哪些子功能是合法的,不会因未知子功能返回NRC 0x12。
第二步:设定“谁能用”——会话与安全等级绑定
这才是真正的“激活条件”。很多开发者以为只要启用了服务就能用,殊不知还受到两个关键限制:
✅ 会话依赖(Session)
你不能在默认会话下随便禁用通信!否则车辆运行中被人用普通诊断仪一发指令就把通信关了,岂不是灾难?
因此,必须明确指定允许执行该服务的诊断会话类型。
继续在DcmDspControlDtcSetting下配置:
-DcmDspControlDtcSettingSessionRef→ 引用ExtendedSession(0x03)
这意味着只有当 ECU 处于扩展会话时,才能响应 28 服务请求。
建议策略:Disable 操作严格限定在 Extended Session;Enable 操作可放宽至任意会话,便于异常恢复。
✅ 安全等级(Security Access)
即使进入了扩展会话,也必须通过安全验证才能执行敏感操作。
配置项:
-DcmDspControlDtcSettingSecurityAccessLevelRef→ 指向SecurityLevel_03
这就要求诊断设备必须先执行27 03请求种子+密钥认证,成功后才具备执行28 02的权限。
这两个条件共同构成了“双重保险”:既要身份合法,又要权限足够。
如果任一条件未满足,Dcm 应自动返回对应的负响应码:
- 不在正确会话 →NRC 0x22(Conditions Not Correct)
- 未通过安全访问 →NRC 0x33(Security Access Denied)
这些都可以在 Davinci 中预先配置响应映射,无需额外编码。
第三步:连接底层——回调函数才是“执行者”
光有“许可”还不够,还得有人去真正执行“开”和“关”的动作。
这就是回调函数的作用。你需要实现一个 C 函数,由 Dcm 在条件满足后主动调用。
典型原型如下:
Std_ReturnType Dcm_EnableCommunication(uint8 subFunction, uint8 communicationType) { switch(subFunction) { case 0x01: // Enable Communication ComM_CommunicationAllowed(COMM_CHANNEL_CAN0, TRUE); CanIf_SetPduMode(CAN_IF_HRH_MASK_ALL, CANIF_ONLINE); break; case 0x02: // Disable Communication ComM_CommunicationAllowed(COMM_CHANNEL_CAN0, FALSE); CanIf_SetPduMode(CAN_IF_HRH_MASK_ALL, CANIF_OFFLINE); break; default: return E_NOT_OK; } return E_OK; }⚠️ 注意事项:
- 函数名需与 Davinci 中配置的DcmDspControlDtcSettingCallout名称一致;
- 若涉及多核 MCU,注意临界区保护;
- 建议异步执行耗时操作,避免阻塞诊断主循环。
这个函数的作用,就是把高层的“逻辑命令”翻译成底层的实际动作——通知 ComM 改变通信模式,通知 CanIf 更新 PDU 状态。
第四步:考虑更复杂的场景——多通道、细粒度控制
如果你的 ECU 接入了多个 CAN 网络(比如 CAN1 是动力总成网,CAN2 是车身网),就不能一刀切地全部关闭。
此时应怎么做?
方案一:按 Channel 分别控制
修改回调函数,根据communicationType掩码判断目标网络:
if (communicationType & 0x01) { // 控制 CAN1 上的 Normal Communication CanIf_SetPduMode(CAN1_HRH_MASK, mode); } if (communicationType & 0x02) { // 控制 CAN2 上的 NM Communication CanIf_SetPduMode(CAN2_NM_MASK, mode); }并在 Davinci 中合理划分 PDU Group,确保 CanIf 能精确识别每类报文。
方案二:引入 BswM 协调策略
对于更复杂的电源-通信联动场景(如低功耗模式下自动关闭通信),可结合 BswM 模块统一调度:
case 0x02: BswM_RequestMode(BSWM_COMM_OFF); // 触发模式切换事件 break;让基础软件管理层统一协调 ComM、EcuM、WdgM 等模块的行为,提升系统一致性。
实际用在哪?这些场景你一定见过
场景一:Bootloader 刷写期间通信静默
这是最经典的应用:
- 诊断仪发送
10 03进入扩展会话; - 执行
27 03安全解锁; - 发送
28 02 01禁用本节点的正常通信输出; - 开始 Flash 编程;
- 完成后发送
28 01 01恢复通信; - 复位重启。
此举有效防止刷写过程中因定时任务仍在运行而导致的 CAN 报文冲突或缓冲区溢出。
场景二:产线下线检测中的“独占通信”
在工厂自动化测试流程中,往往需要逐个激活 ECU 并进行功能自检。此时可通过 28 服务临时关闭其他无关通信,确保测试环境干净、结果可靠。
容易踩的坑与调试建议
别以为配完就万事大吉。以下是几个高频“翻车点”:
❌ 坑点一:明明发了命令却没有反应
排查方向:
- 当前是否真的进入了 Extended Session?用 CANoe 监听10 03响应;
- 是否遗漏了 Security Access?检查是否有27 03成功响应;
- 回调函数是否被正确绑定?查看生成代码中是否存在函数调用;
- 是否有其他模块(如 ComM)强制维持在线状态?
❌ 坑点二:通信禁用后依然有报文发出
原因可能是:
- 只调用了CanIf_SetPduMode,但未影响 ComM 的全局通信允许标志;
- 某些高优先级报文(如故障广播)被单独配置为 always-on;
- 使用的是 CAN FD,部分静态路由未受控。
解决方法:
- 在回调中同时调用ComM_CommunicationAllowed(FALSE);
- 检查 PduR 路由表,确认所有相关 I-PDU 均受 CanIf 模式控制;
- 对关键报文设置独立使能标志,配合 Dcm 共同管理。
✅ 秘籍:善用 Dem 记录事件
建议在每次执行 28 服务时,触发一个 Dem Event:
Dem_ReportErrorStatus(COMM_CTRL_EXECUTED, DEM_EVENT_STATUS_PASSED);这样后续可以通过售后工具读取历史记录,快速定位“是谁、何时关闭了通信”,极大提升可追溯性。
总结一下:掌握这几点,你就赢了
回到最初的问题:如何在 Davinci Configurator 中正确配置 UDS 28 服务的激活条件?
核心要点其实就四个字:层层设防。
| 层级 | 关键配置 |
|---|---|
| 协议层 | 启用 DcmDspControlDtcSetting,注册子功能 |
| 权限层 | 绑定 Session + Security Level,防止非法调用 |
| 执行层 | 实现回调函数,联动 ComM / CanIf 控制通信 |
| 恢复层 | 确保上电默认通信开启,支持异常恢复 |
一旦你掌握了这套完整的配置逻辑,不仅 28 服务不在话下,其他 UDS 服务(如 10、27、31)的配置思路也能举一反三。
更重要的是,你会开始意识到:AUTOSAR 不只是堆叠模块,而是构建一套受控、可信、可维护的诊断体系。
下次当你看到28 02 01这条命令时,脑海里浮现的不再是一串十六进制数,而是一个完整的状态机流转、权限校验与系统协同的过程。
而这,正是每一个优秀汽车软件工程师的成长印记。
如果你正在做 OTA、UDS 诊断或 AUTOSAR 配置,欢迎在评论区分享你的实践经验,我们一起探讨那些“只有 debug 过才知道”的细节。