目录
(1) 10服务:$10 01 (默认会话) DefaultSession
(2)10服务:$10 02 (编程会话) ProgrammingSession
(3)10服务:$10 03 (扩展会话) ExtendedSession
系列目录:
《CANoe_UDS-Bootloader刷写系列-含源码(一)刷写基本流程》
《CANoe_UDS-Bootloader刷写系列-含源码(二)CAPL实现$10服务》
《CANoe_UDS-Bootloader刷写系列-含源码(三)CAPL实现$27服务密钥解锁》
《CANoe_UDS-Bootloader刷写系列-含源码(四)CAPL实现$34 & $36 & $37服务数据传输》 --待续
《CANoe_UDS-Bootloader刷写系列-含源码(五)CAPL实现$31服务例程控制》 --待续
《CANoe_UDS-Bootloader刷写系列-含源码(六)CAPL实现$22 & $2E 服务读写配置》
《CANoe_UDS-Bootloader刷写系列-含源码(七)CAPL实现$85 & $28服务预编程步骤》
《CANoe_UDS-Bootloader刷写系列-含源码(七)干货 CAPL实现CRC数据校验》
《CANoe_UDS-Bootloader刷写系列-含源码(八)干货 CANoe_Panel刷写上位机面板制作》
《CANoe_UDS-Bootloader刷写系列-含源码(九)CAPL框架全流程测试及报文分析-查漏补缺》
前言
哈喽,大家好,我还是Tom。
从上一篇文章《CANoe_UDS-Bootloader刷写系列-含源码(一)刷写基本流程》我们了解了刷写需要的一些UDS服务和具体的刷写流程。
本来今天想对上一章提到的ISO14229,ISO15765,ISO11898等有关于刷写相关的协议内容进行一个详细解读,省得大家去读晦涩难懂的协议。后来发现已经有相关博主解读过了,并且非常全面,内容很有质量。
链接自取 《ISO14229协议详细解读》
那么今天就使用CANoe软件内CAPL编程实现$10服务的收发,以及分享编写思路及源码
一,协议相关
根据刷写相关规范内了解到的10服务内最常用的子服务只有三种:默认会话,编程会话,扩展会话
即:在预编程步骤和后编程步骤通常我们使用的是0x03扩展会话,在主编程步骤(正式编程)我们需要进入的是0x02编程会话
而0x01默认会话则基本不需要在刷写中使用,只是充当一个在各个会话内跳转的翘板
(1) 10服务:$10 01 (默认会话) DefaultSession
从下图我们知道,10服务是由两个字节组成,
第一个字节是服务DiagnosticSessionControl(0x10),此字段是不变的。
第二个字节是子服务sub_function(0x00-0xFF),需要进入默认会话内此字段为0x01。向总线内ECU发送此字段说明你要进入默认会话了,ECU会自动切换进入默认会话。
下图为子服务0x01的具体协议要求
(2)10服务:$10 02 (编程会话) ProgrammingSession
第一个字节是服务DiagnosticSessionControl(0x10),此字段是不变的。
第二个字节是子服务sub_function(0x00-0xFF),需要进入编程会话内此字段为0x02。向总线内ECU发送此字段说明你要进入编程会话了,ECU会自动切换进入编程会话
注意:在10 02(编程会话)内诊断刷写才算正式开始,此会话内会进行31服务例程控制,34 36 37等服务进行上传下载操作。也就是我们所说的主编程步骤
下图为子服务0x02的具体协议要求
(3)10服务:$10 03 (扩展会话) ExtendedSession
第一个字节是服务DiagnosticSessionControl(0x10),此字段是不变的。
第二个字节是子服务sub_function(0x00-0xFF),需要进入扩展会话此字段为0x03。向总线内ECU发送此字段说明你要进入扩展会话了,ECU会自动切换进入扩展会话
(4)肯定响应 & 否定响应(NRC)
NRC:
二,CAPL实现
废话不多说,接下来讲一下在capl实现$10服务的收发
首先我们需要知道CANoe中CAPL分为两种Node Type,分别为Simulation node (仿真节点) 与 Test node(测试节点)!
而这两种类型的代码存在一部分差异,今天需要使用的是Test node(测试节点)来进行代码实现
首先,发送了10服务之后肯定是需要将ECU返回的Rx报文进行接收,我们先定义一下接收报文
定义接收函数:
variables{
char wait_rsp_text_event[18]="response received";
const int BUFFER_SIZE_2048=0x2048;
const int BUFFER_SIZE_1024=0x1024;
const int LENGTH_4=4;
byte rxBuffer[BUFFER_SIZE_2048];
long rxBufferLen=0;
}
OSEKTL_DataInd(long rxCount)
{
long i;
dword glhandle=0;
/* Get received data */
OSEKTL_GetRxData( rxBuffer, 8192);
write("检索接收到的数据存储至rxBuffer");
rxBufferLen=rxCount;
//signal response received
for(i=0;i<rxBufferLen;i++){
Write("收到来自 %d 的字节 0x%x: [%02x]", i, OSEKTL_GetSrcAdr(), rxBuffer[i]);
}
if(rxBufferLen>0)
TestSupplyTextEvent(wait_rsp_text_event);
}
//process will suspend for tTime ms to wait for response
int wait_server_response(byte request[],dword _tTime){
long status=0;
int result=0;
long flag=5;
flag=2;result=0;status=0;
//loop while response pending
while(flag>=0)
{
status=testWaitForTextEvent(wait_rsp_text_event,_tTime);
if(status<0){
write("service %x:服务无法等待服务器响应",request[0]);
return -1;
}else if(status==0){
return -1;
}
if(result==-3){
write("-----------响应 等待---------------");
flag=5;
}
if(result==-2){
write("Warning:意外的积极响应");
flag--;
}
if(result==-1){
write("service %x:收到总线负面回应",rxBuffer[1]);
break;
}
if(result==0){
write("收到积极响应111111\n");
break;
}
}
if(result<0){
msgBeep(5);
return -1;
}
return result;
}
定义好接收报文后就可以进行10服务的发送了
发送函数:
variables{
dword timeout=3000;
}
int session_control(byte _session_type){
byte request[2]={0x10,0x01};
request[1]=_session_type;
OSEKTL_SetTxId(" ID "); //设置寻址ID,区分功能寻址或物理寻址
OSEKTL_DataReq(request,elcount(request));
OSEKTL_DataInd(rxCount);
return wait_server_response(request,timeout);
}
MainTest(){
testModuleTitle("FBL测试");
write("----------------------MinTest启动-----------------------");
session_control(0x01); //Send
session_control(0x02);
session_control(0x03);
}
最近项目忙起来了 拖更了 不好意思,后续会将其他诊断服务与如何制作上位机面板,代码读取文件并解析,密钥解锁等源码继续分享至本专栏,,,,码字不易,求个三连