定义UDS服务单帧、多帧发送,以及诊断回复报文处理,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace TsMasCSharp.CanManager
{
/// <summary>
/// 定义UDS服务单帧、多帧发送,以及诊断回复报文处理
/// </summary>
class UDS_Service
{
bool isFunc= false;
public byte ServiceID;
public byte ServiceType;
byte[] SendData;
public bool ResponResult = false;
byte[] ResponsData;
bool IsFirstResponsGet = false;
int responseIndex = 0; //诊断数据存储index标志位
public int index36 = 1; //block Index
private System.Timers.Timer timerout;
uint SendID = 0;
uint ResponsID = 0;
public enum UDS_State
{
State_IDLE,
State_Waiting30,
State_WaitingResponse,
State_WaitMultiResponse,
State_Timeout,
State_Stop
}
public UDS_State udsState = UDS_State.State_IDLE;
public UDS_Service(byte serviceid, byte servicetype,byte[] Data = null)
{
// candispatch = dispatch;
isFunc = (serviceid == 0x85 || serviceid == 0x28);
SendID = (uint)(isFunc ? CanDispatch.UDS_FuncReqestID : CanDispatch.UDS_FuncReqestID);
ResponsID = (uint)(isFunc ? CanDispatch.UDS_FuncresponseID : CanDispatch.UDS_responseD);
int idex = 0;
if (Data == null)
{
SendData = new byte[8];
SendData[idex++] = 2;
}
else if (Data.Count() > 5)
{
//多帧
int Sendlenth = (ushort)(2+Data.Count()); //发送长度包扩服务
//多帧 36
if (serviceid == 0x36)
{
if (Data.Count() % CanDispatch.blocksize != 0)
{
//如果数据不是 Block整数倍,则自动填充数据
SendData = new byte[4 + (Data.Count() / CanDispatch.blocksize+1)* CanDispatch.blocksize];
}
else
{
SendData = new byte[4 + Data.Count()];
}
SendData[idex++] = (byte)(0x10 + ((CanDispatch.blocksize+2) >> 8));
SendData[idex++] = (byte)((CanDispatch.blocksize +2)&0xFF);
}
//多帧非36
else
{
SendData = new byte[4 + Data.Count()];
SendData[idex++] = (byte)(0x10 + (Sendlenth >> 8));
SendData[idex++] = (byte)(Sendlenth);
}
}
//单帧
else
{
SendData = new byte[8];
SendData[idex++] = (byte)(3 + Data.Count());
}
SendData[idex++] = serviceid;
SendData[idex++] = servicetype;
ServiceID = serviceid;
ServiceType = servicetype;
if (Data != null)
{
for (int i = 0; i < Data.Count() ; i++)
{
SendData[idex++] = Data[i];
}
}
timerout = new System.Timers.Timer();
timerout.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerTimeout);
}
/// <summary>
/// 收到报文重启超时计时器
/// </summary>
public void RestartTimeoutTimer()
{
timerout.Stop();
timerout.Interval = 5000;
// timerout.Start();
}
/// <summary>
/// 发送首帧报文,适用单帧和多帧
/// </summary>
public void SendFirsFrame()
{
if (SendData.Count() <= 8)
{
//直接发完
udsState = UDS_State.State_WaitingResponse;
}
else
{
if (ServiceID == 0x36)
{
//先发第一帧
byte[] FirstFrame = new byte[8];
FirstFrame[0] = (byte)(0x10 + ((CanDispatch.blocksize + 2) >> 8)); FirstFrame[1] = (byte)((CanDispatch.blocksize + 2) & 0x00ff);
FirstFrame[2] = 0x36; FirstFrame[3] = (byte)index36;
FirstFrame[4] = SendData[4+ (index36 - 1)*CanDispatch.blocksize]; FirstFrame[5] = SendData[5 + (index36 - 1) * CanDispatch.blocksize];
FirstFrame[6] = SendData[6 + (index36 - 1) * CanDispatch.blocksize]; FirstFrame[7] = SendData[7 + (index36 - 1) * CanDispatch.blocksize];
CBootUpdate.indexDownLoad++;
}
//先发第一帧
udsState = UDS_State.State_Waiting30;
}
CanDispatch.TP_Transmit(SendID, SendData, 8);
timerout.Interval = 5000;
// timerout.Start();
}
/// <summary>
/// 发送多帧报文的剩余帧
/// </summary>
public void SendRestFrame()
{
uint ID = (uint)(isFunc ? CanDispatch.UDS_FuncReqestID : CanDispatch.UDS_FuncReqestID);
// 36服务每个block长度为 4+ blocksize
if (ServiceID == 0x36)
{
int index = 1;
byte framecount = 0x21;
byte[] sdata = { framecount, 0, 0, 0, 0, 0, 0, 0 };
int resetbyte = CanDispatch.blocksize-4;
for (int i = 0; i < CanDispatch.blocksize - 4; i++)
{
//8个字节封装一帧
if ((i % 7) == 0 && (i > 0))
{
CanDispatch.TP_Transmit(ID, sdata, 8);
framecount = framecount > 0x2F ?(byte) 0x20 : framecount++;
sdata[0] = framecount;
for (int pindex = 1; pindex < 8; pindex++)
{
sdata[pindex] = 0;
}
index = 1;
resetbyte -= 7;
Thread.Sleep(1);
}
//前8个字节已经发出,所以 i需要+8
sdata[index] = SendData[i + 8 + (index36 - 1) * CanDispatch.blocksize];
index++;
}
if (resetbyte > 0)
{
CanDispatch.TP_Transmit(ID, sdata, 8);
}
udsState = UDS_State.State_WaitMultiResponse;
}
else
{
int index = 1;
byte framecount = 0x21;
byte[] sdata = { framecount, 0, 0, 0, 0, 0, 0, 0 };
int resetbyte = SendData.Count() - 8;
for (int i = 0; i < SendData.Count() - 8; i++)
{
//8个字节封装一帧
if ((i % 7) == 0 && (i > 0))
{
CanDispatch.TP_Transmit(ID, sdata, 8);
framecount = framecount > 0x2F ? (byte)0x20 : framecount++;
sdata[0] = framecount;
for (int pindex = 1; pindex < 8; pindex++)
{
sdata[pindex] = 0;
}
index = 1;
resetbyte -= 7;
Thread.Sleep(1);
}
//前8个字节已经发出,所以 i需要+8
sdata[index] = SendData[i + 8];
index++;
}
if (resetbyte > 0)
{
CanDispatch.TP_Transmit(ID, sdata, 8);
}
udsState = UDS_State.State_WaitingResponse;
}
}
void OnTimerTimeout(object sender, EventArgs e)
{
frmMain.LogType("Request " + ServiceID.ToString("X2") + " " + ServiceType.ToString("X2") + " Timeout!");
ResponResult = false;
udsState = UDS_State.State_Stop;
timerout.Close();
}
void ProcessFinalResponse(ref byte[] tCanfd, uint id)
{
if (ResponsData[0] == (ServiceID + 0x40) && ResponsData[1] == ServiceType)
{
ResponResult = true;
frmMain.LogType("Request " + ServiceID.ToString("X2") + " " + ServiceType.ToString("X2") + " Pos Reponse!");
udsState = UDS_State.State_Stop;
timerout.Close();
}
else if (ResponsData[0] == (0x7F) && ResponsData[1] == ServiceID)
{
ResponResult = false;
frmMain.LogType("Request " + ServiceID.ToString("X2") + " " + ServiceType.ToString("X2") + " Neg Response!");
udsState = UDS_State.State_Stop;
timerout.Close();
}
}
public void ResponseProcess(ref byte[] tCanfd, uint id)
{
if (id!= ResponsID)
{
return;
}
switch (udsState)
{
case UDS_State.State_IDLE:
break;
case UDS_State.State_Waiting30:
if (tCanfd[0] == 0x30)
{
SendRestFrame();
RestartTimeoutTimer();
}
break;
case UDS_State.State_WaitingResponse:
{
//单帧第一帧回复
if ((tCanfd[0] >> 4) == 0 && !IsFirstResponsGet)
{
byte ResonseLenth = (tCanfd[0]);
ResponsData = new byte[ResonseLenth];
for (int i = 0; i < ResonseLenth; i++)
{
ResponsData[i] = tCanfd[i + 1];
}
// 7F 78处理
if ( ResponsData[0] == (0x7F) && ResponsData[1] == ServiceID && ResponsData[2] == 0x78)
{
RestartTimeoutTimer();
}
else
{
ProcessFinalResponse(ref tCanfd, id);
}
}
//多帧第一帧回复
else if ((tCanfd[0] >> 4) == 1 && !IsFirstResponsGet) //多帧
{
byte[] sdata = { 0x30, 0, 0x0, 0, 0, 0, 0, 0 };
CanDispatch.TP_Transmit(SendID,sdata, 8);
//提取response长度
ushort ResonseLenth = (ushort)(((tCanfd[0] & 0x0F) << 8) + tCanfd[1]);
ResponsData = new byte[ResonseLenth];
for (int i = 0; i < 6; i++)
{
ResponsData[i] = tCanfd[i+2];
}
responseIndex += 6;
IsFirstResponsGet = true;
RestartTimeoutTimer();
}
//多帧尾帧回复
else if (IsFirstResponsGet)
{
for (int i = 0; i < 7 && responseIndex< ResponsData.Count(); i++)
{
ResponsData[responseIndex++] = tCanfd[i + 1];
}
if (responseIndex == ResponsData.Count())
{
ProcessFinalResponse(ref ResponsData, id);
}
RestartTimeoutTimer();
}
}
break;
case UDS_State.State_WaitMultiResponse:
{
byte ResonseLenth = (tCanfd[0]);
ResponsData = new byte[ResonseLenth];
responseIndex = 0;
for (int i = 0; i < 7 && responseIndex < ResponsData.Count(); i++)
{
ResponsData[responseIndex++] = tCanfd[i + 1];
}
if (ResponsData[0] == (byte)(ServiceID+0x40))// && ResponsData[1] == index36)
{
if (((SendData.Count() - 4) / CanDispatch.blocksize) >= index36)
{
index36++;
SendFirsFrame();
RestartTimeoutTimer();
}
else
{
ProcessFinalResponse(ref ResponsData, id);
}
}
else if (ResponsData[1] == (byte)(0X7F) && ResponsData[2] == ServiceID)
{
ProcessFinalResponse(ref ResponsData, id);
}
}
break;
}
}
}
}
使用时,流程如下:
void Init()
{
List<UDS_Service> serviceList = new List<UDS_Service>();
serviceList.Add(new UDS_Service(0x10, 0x2));
serviceList.Add(new UDS_Service(0x27, 0x01));
serviceList.Add(new UDS_Service( 0x27, 0x02));
uint drvflielenth = (uint)FlashDrvBinData.Count();
byte[] Data34Drv = {0x44,0xFD, (byte)(DrvADDRESS >> 24), (byte)(DrvADDRESS >> 16), (byte)(DrvADDRESS >> 8), (byte)DrvADDRESS,
(byte)(drvflielenth >> 24), (byte)(drvflielenth >> 16), (byte)(drvflielenth >> 8), (byte)drvflielenth};
serviceList.Add(new UDS_Service(0x34, 0x0, Data34Drv));
serviceList.Add(new UDS_Service( 0x36, 0x1, FlashDrvBinData));
serviceList.Add(new UDS_Service( 0x37, 0x0));
serviceList.Add(new UDS_Service(0x31, 0x1, new byte[] { 0x2, 0x2, 0x98, 0xc3, 0x10, 0x02 }));
serviceList.Add(new UDS_Service(0x31, 0x1, new byte[] { 0XFF, 0x00, 0x44, 0x00, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 }));
uint mcufilelenth = (uint)MCUBinData.Count();
byte[] Data34Mcu = {0,0x44,0xFD, (byte)(McuADDress >> 24), (byte)(McuADDress >> 16), (byte)(McuADDress >> 8), (byte)McuADDress,
(byte)(mcufilelenth >> 24), (byte)(mcufilelenth >> 16), (byte)(mcufilelenth >> 8), (byte)mcufilelenth};
serviceList.Add(new UDS_Service( 0x34, 0x00, Data34Mcu));
serviceList.Add(new UDS_Service( 0x36, 0x1, MCUBinData));
serviceList.Add(new UDS_Service(0x37, 0));
serviceList.Add(new UDS_Service( 0x31, 0x1, new byte[] { 0x2, 0x2, 0x98, 0xc3, 0x10, 0x02 }));
serviceList.Add(new UDS_Service( 0x31, 0x1, new byte[] { 0XFF, 0x00, 0x44, 0x00, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 }));
serviceList.Add(new UDS_Service( 0x11, 0x1));
serviceList[0].SendFirsFrame();
}
void OnRecieveData(ref byte[] tCanfd,uint id)
{
serviceList[processStep].ResponseProcess(ref tCanfd, id);
if (serviceList[processStep].udsState == UDS_Service.UDS_State.State_Stop)
{
if (serviceList[processStep].ResponResult)
{
if (processStep < serviceList.Count())
{
processStep++;
serviceList[processStep].SendFirsFrame();
}
else
{
FinishDownLoad();
}
}
else
{
FinishDownLoad();
}
}
}