目录
一、前言
halle,大家好,我是小鸟鹏。
上篇文章《CANoe_UDS-boorloader 自动测试系列(二)基本刷写流程》简单介绍了整Bootloader的基本刷写流程,包括具体使用哪些服务实现哪些功能,对刷写流程还不熟悉的小伙伴请移步观看上一篇文章。
从本章开始,我开始介绍基于CANoe的UDS bootloader,如何用CAPL实现刷写和自动化测试。那么今天我们就先使用CAPL实现一个基本功能:UDS报文的接收和解析,以及如何将数据组成UDS报文对外发送。分享源码及思路。
二、CAPL实现
1、报文接收
CAN报文的接收使用CAPL的内置函数是:
testWaitForMessage(RESPONSE_ID_DEFAULT,g_P2server); //等待CAN报文
TestGetWaitEventMsgData(g_RxMessage); //接收CAN报文数据
以上组合可以实现超时等待指定ID报文,testWaitForMessage()第一个参数为要等待的报文ID号,第二个参数为超时时间,返回值为1表示等待到了报文。TestGetWaitEventMsgData()则是接收保报文数据。
接收报文函数:
variables
{
const dword PHYSICS_ID_DEFAULT = 0x722;
const dword FUNTION_ID_DEFAULT = 0x7DF;
const dword RESPONSE_ID_DEFAULT = 0x734;
const dword g_P2server = 5000;
}
void WaitServerResponse(byte responsecode ,dword id ,byte service)
{
if(responsecode == 0)//不需要响应
{
if(1 == testWaitForMessage(RESPONSE_ID_DEFAULT,g_P2server)) //等待报文
{
CanTp_RxMessageData(); //接收报文数据
write("====》service:0x%x fail0",service);
}
else
{
write("====》service:0x%x 当前服务响应正确",service);
}
}
else//需要回响应
{
if(1 == testWaitForMessage(RESPONSE_ID_DEFAULT,g_P2server)) //等待报文
{
CanTp_RxMessageData(); //接收报文数据
if(responsecode == service+0x40)//需要响应完整的正响应请求
{
if(g_RxMessage.byte(1) == responsecode || g_RxMessage.byte(2) == responsecode)//返正响应
{
write("====》service:0x%x 当前服务响应正确",service);
if(g_RxMessage.byte(0) >= 0x10 && g_RxMessage.byte(0) < 0x20)//收到首帧的正响应
{
CanTp_TxFC(PHYSICS_ID_DEFAULT, 0x30, 0x00, 0x0A);//发送流控帧
while(1)
{
if(1 == testWaitForMessage(RESPONSE_ID_DEFAULT,150))//收到连续帧
{
//连续帧
CanTp_RxMessageData();
}
else//没收到连续帧停止检测
{
break;
}
}
}
}
else
{
if((0x7F == g_RxMessage.byte(1)) && (0x78 == g_RxMessage.byte(3)))
{
Proces0x7Fxx0x78Response(responsecode);
}
else
{
write("====》service:0x%x fail1",service);
}
}
}
else//需要负响应
{
if(g_RxMessage.byte(1) == 0x7F)//负响应
{
if(g_RxMessage.byte(3) == responsecode)
{
write("====》service:0x%x 当前服务响应正确",service);
}
else
{
write("====》service:0x%x fail2",service);
}
}
else
{
write("====》service:0x%x fail3",service);
}
}
}
else//需要回复,却没回复响应帧
{
write("====》service:0x%x P2server Timout",service);
}
}
}
定义好后就可以通过这个函数接收报文并且按照UDS帧格式解析,我们可以自定义server和期待返回的NRC,通过这个函数就可以判断下位机返回的NRC是否正确。
2、报文发送
CAN报文的发送使用CAPL的内置函数是:
output(g_TxMessage); //发送一帧CAN报文
发送报文函数:
void DiagnosticServiceSend(byte responsecode ,dword id ,dword dlc ,byte data[])
{
int DataLength,i,Tp_n;
byte Tp_Buf[4096];
byte ErrorStatus = E_NOT_OK;
DataLength = Tp_n = 0;//初始化
g_TxMessage.id = id;
g_TxMessage.dlc = 8;
if(dlc > 0x00)
{
if(dlc <= 0x07)
{
g_TxMessage.byte(0) = dlc;//单帧长度
for(DataLength = 0; DataLength < 7; DataLength++)//单帧数据赋值
{
g_TxMessage.byte(DataLength+1) = 0;
g_TxMessage.byte(DataLength+1) = data[DataLength];
}
output(g_TxMessage);
}
else if(0x08 <= dlc && dlc <= 0xfff)//首帧
{
g_TxMessage.byte(0) = 0x10 + (dlc>>8);//首帧
g_TxMessage.byte(1) = dlc&0xff;//首帧长度
for(DataLength = 0; DataLength < 6; DataLength++)//首帧数据
{
g_TxMessage.byte(DataLength+2) = data[DataLength];
}
output(g_TxMessage);
for(i = DataLength; i < (int)dlc; i++)//连续帧数据赋值
{
Tp_Buf[Tp_n] = data[i];
Tp_n++;
}
CanTp_TxCF(responsecode, id, dlc, Tp_Buf);//连发续帧函数
}
WaitServerResponse(responsecode ,id,data[0]);//响应码检测
}
}
定义好发送函数后通过这个函数可以实现发送任何服务请求和任意长度的UDS数据帧,自动等待响应后自动判断NRC的正确性。
通过以上的两个函数接口我们就可以任意服务的诊断了,底层的业务已经实现,剩下的就是根据协议对每个服务进行封装就行了。如果各位小伙伴有问题或者有更好的建议欢迎指正!【抱拳】。
三、总结展望
本文介绍了基于CAPL实现的两个函数接口,一个是UDS帧的接收和解析,一个是发送UDS帧。这两个函数接口是后续实现各种业务代码的基础,非常重要哦!
后续我会持续更新这个系列,但是时间不固定,视工作情况决定,但是有时间的话会尽快更新的。你们的关注是我更新最大的动力,码字不易,求个三连。。。
下一篇:
CANoe_UDS-booroader 自动测试系列(三)基本功能:CAPL实现#10服务会话控制
如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
作者:小鸟鹏
联系方式:
标签:UDS,service,CANoe,报文,CAPL,responsecode,byte,ID From: https://blog.csdn.net/m0_68882790/article/details/141312615