C#UDS 诊断服务CAN报文发送与接收

定义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();
                }
            }
        }

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值