4. 诊断会话控制切换
任务目标
编写CAPL脚本,通过诊断仪向ECU发送会话控制请求,实现默认会话、编程会话和扩展会话之间的切换,并通过读取当前会话ID验证切换是否成功。
实现原理
诊断会话控制服务(UDS 0x10)通过子功能参数指定目标会话:0x01为默认会话,0x02为编程会话,0x03为扩展会话。ECU成功切换后返回肯定响应(0x50+子功能)。验证方式为发送读取当前会话ID的请求(UDS 0x22,DID 0xF199),从响应数据中解析会话ID。
关键完整代码
/* 诊断会话控制切换 - CAPL实现 */
variables
{
const int DIAG_REQ_ID = 0x7E0; // 物理请求ID
const int DIAG_RES_ID = 0x7E8; // 物理响应ID
const int SESSION_DID = 0xF199; // 会话ID DID
diagRequest DiagnosticSessionControl_Req;
diagResponse DiagnosticSessionControl_Res;
diagRequest ReadDataByIdentifier_Req;
diagResponse ReadDataByIdentifier_Res;
}
/* 发送会话控制请求 */
void SendSessionControl(byte subFunction)
{
DiagnosticSessionControl_Req.SetPhysicalRequest(DIAG_REQ_ID, DIAG_RES_ID);
DiagnosticSessionControl_Req.SetService(0x10);
DiagnosticSessionControl_Req.SetParameter("SubFunction", subFunction);
DiagnosticSessionControl_Req.SendRequest();
}
/* 读取当前会话ID */
void ReadCurrentSession()
{
ReadDataByIdentifier_Req.SetPhysicalRequest(DIAG_REQ_ID, DIAG_RES_ID);
ReadDataByIdentifier_Req.SetService(0x22);
ReadDataByIdentifier_Req.SetParameter("DID", SESSION_DID);
ReadDataByIdentifier_Req.SendRequest();
}
/* 会话控制响应回调 */
on diagResponse DiagnosticSessionControl_Res
{
if (this.GetResult() == 0) // 0表示肯定响应
{
byte subFunc = this.GetParameter("SubFunction");
write("会话切换成功,子功能: 0x%02x", subFunc);
ReadCurrentSession(); // 切换后读取会话ID验证
}
else
{
write("会话切换失败,NRC: 0x%02x", this.GetResult());
}
}
/* 读取会话ID响应回调 */
on diagResponse ReadDataByIdentifier_Res
{
if (this.GetResult() == 0)
{
word sessionId = this.GetParameter("DIDData");
write("当前会话ID: 0x%04x", sessionId);
// 根据会话ID判断当前会话类型
if (sessionId == 0x01)
write("验证结果: 默认会话");
else if (sessionId == 0x02)
write("验证结果: 编程会话");
else if (sessionId == 0x03)
write("验证结果: 扩展会话");
else
write("验证结果: 未知会话");
}
else
{
write("读取会话ID失败,NRC: 0x%02x", this.GetResult());
}
}
/* 测试主函数 - 依次切换三种会话 */
testcase SessionSwitchTest()
{
write("=== 诊断会话控制切换测试开始 ===");
// 1. 切换到编程会话
write("--- 切换到编程会话 (0x02) ---");
SendSessionControl(0x02);
TestWaitForDiagResponse(DiagnosticSessionControl_Req, 1000);
// 2. 切换到扩展会话
write("--- 切换到扩展会话 (0x03) ---");
SendSessionControl(0x03);
TestWaitForDiagResponse(DiagnosticSessionControl_Req, 1000);
// 3. 切换回默认会话
write("--- 切换回默认会话 (0x01) ---");
SendSessionControl(0x01);
TestWaitForDiagResponse(DiagnosticSessionControl_Req, 1000);
write("=== 诊断会话控制切换测试结束 ===");
}
运行与验证
运行步骤:
- 在CANoe中创建仿真工程,添加一个CAN通道,配置诊断通信参数(请求ID 0x7E0,响应ID 0x7E8);
- 将上述代码添加到CAPL测试节点中,关联到对应通道;
- 在测试模块中调用
SessionSwitchTest()测试用例; - 确保ECU(或仿真面板)已上电并处于可响应诊断请求的状态。
通过条件:
- CAPL输出窗口依次显示“会话切换成功”且子功能值正确;
- 每次切换后读取的会话ID与目标会话一致(0x01/0x02/0x03);
- 最终回到默认会话,验证输出显示“默认会话”。
常见问题
- 响应超时:检查物理请求ID和响应ID是否与ECU配置一致,确认CAN通信正常;
- NRC 0x12(子功能不支持):确认ECU是否支持对应会话切换,部分ECU需先解锁安全等级才能进入编程会话;
- 会话ID读取失败:确认DID 0xF199在目标ECU上有效,若使用其他DID需同步修改代码中的
SESSION_DID常量。