基于CAN总线的汽车诊断协议UDS(上位机开发网络层及错误代码解析)

     UDS协议栈的开发和测试对于刚刚接触UDS协议的开发人员来说,不但需要阅读大量的标准文档,短时间内很难理解透彻,标准协议栈代码的编写更加困难,刚入门又没有快捷简单的测试工具帮助加快理解和验证,使得UDS诊断开发对于一般的初创公司或者小型企业来说,是一个比较难跨越的门槛。一般的企业通过购买专业的软件工具和专业的培训服务来获取UDS诊断开发和测试的技术。本文的目的是通过简单快捷的UDS上位机软件测试界面,有助于帮助开发者加快UDS协议栈的理解和开发测试,能够帮助开发者快速的掌握UDS开发和测试的一般过程和方法。

         

首先贴出网络层协议源码:

namespace Uds

{

    public class uds_trans

    {

        public enum AddressingModes

        {

            Physical_Addressing,

            Functional_Addressing,

        }

 

        private int id;

        ///

        /// UDS默认填充字节

        ///

        public byte fill_byte = 0x55;

 

        public int tx_id;

        public int rx_id;

        public int test_id;

        /*

        ** Frame types arranged in numericalorder for efficient switch statement

        ** jump tables.

        */

        private enum FrameType

        {

            TX_SF = 0, /* Single Frame */

            TX_FF = 1, /* First Frame */

            TX_CF = 2, /* Consecutive Frame */

            TX_FC = 3  /* Flow Control Frame */

        };

 

        /*

        ** Masks for the PCI(Protcol ControlInformation) byte.

        ** The MS bit contains the frame type.

        ** The LS bit is mapped differently,depending on frame type, as follows:

        ** SF: DL (number of diagnostic bytes NOT including the PCI byte; only the

        **      3 LS bits are used).

        ** FF: XDL (extended data length; always be 0.)

        ** CF: Sequence number,4 bits, max value:15.

        ** FC: Flow Status. The value of FS shall be set to zero that means that

        **     the tester is ready to receive a maximum number of CF.

        */

        private enum PCI /* Don't change thesevalues, these must be  */

        {

            /* MS bits -  Frame Type */

            FRAME_TYPE_MASK = 0xF0,

            SF_TPDU = 0x00,             /* Single frame                 */

            FF_TPDU = 0x10,             /* First frame                  */

            CF_TPDU = 0x20,             /* Consecutive frame            */

            FC_TPDU = 0x30,             /* Flow control frame           */

            FC_OVFL_PDU = 0x32,         /* Flow control frame           */

 

            /* LS bits - SF_DL */

            SF_DL_MAX_BYTES = 0x07,     /* SF Max Data Length */

            SF_DL_MASK = 0x07,          /* number diagnostic data bytes */

            SF_DL_MASK_LONG = 0x0F,     /* change to check the 4 bits for testing,number diagnostic data bytes */

 

            /* LS bits - FF_DL */

            FF_EX_DL_MASK = 0x0F,       /*Extended data length         */

 

            /* LS bits - CF_SN */

            CF_SN_MASK = 0x0F,          /* Sequence number mask         */

            CF_SN_MAX_VALUE = 0x0F,     /* Max value of sequence number */

 

            /* LS bits - FC Saatus */

            FC_STATUS_CONTINUE = 0x00,  /* Flow control frame, CONTINUE */

            FC_STATUS_WAIT = 0x01,      /* Flow control frame, WAIT */

            FC_STATUS_OVERFLOW = 0x02,  /* Flow control frame, OVERFLOW */

            FC_STATUS_MASK = 0x0F,

        };

 

        private int N_As = 25;

        private int N_Ar = 25;

 

        private int N_Bs = 75;

        private int N_Br;

 

        private int N_Cr = 150;

        private int N_Cs;

 

        private int FC_BS_MAX_VALUE = 0;

        private int FC_ST_MIN_VALUE = 5;

 

        private int CF_SN_MAX_VALUE = 15;

        private int SF_DL_MAX_BYTES = 7;

 

        /*

        ** Time to wait for the tester to senda FC frame in response

        ** to a FF(wait for flow control frametime out).

        ** N_As + N_Bs = 25 +75 = 100ms

        */

        private int FC_WAIT_TIMEOUT;//N_As +N_Bs + 50;

 

        /*

        ** wait for Consecutive frame time out

        ** N_Cr < 150ms

        */

        private int CF_WAIT_TIMEOUT;//N_Cr; //(N_Cr- 10))

 

        private int RX_MAX_TP_BYTES = 0xFFF;

 

 

        public uds_trans()

        {

            can_rx_info.frame = new byte[8];

            can_tx_info.frame = new byte[8];

 

            FC_WAIT_TIMEOUT = N_As + N_Bs + 50;/* N_As + N_Bs + 50 */

            CF_WAIT_TIMEOUT = N_Cr;             /* (N_Cr - 10)) */

        }

 

        private readonly intbeginning_seq_number = 1;

        private readonly int TPCI_Byte = 0;

        private readonly int DL_Byte = 1;

        private readonly int BS_Byte = 1;

        private readonly int STminByte = 2;

 

        private class tx_info

        {

            public bool tx_rx_idle = false;

            public bool tx_fc_tpdu = false;

            public bool tx_last_frame_error = false;

            public bool tx_wait_fc = false;

            public bool tx_in_progress = false;

 

            public int tx_block_size = 0;           /* BS(Block Size) in a flow ControlFrame */

            public int tx_stmin_time = 20;

            public int tx_cf_stmin_wait_time =20;   /* STmin Time in Flow Control Frame*/

            public int tx_fc_wait_time =0;         /* Wait for FC when has sentFF */

 

            public int lenght;

            public int offset;

            public int next_seq_num;

            public byte[] buffer;

            public byte[] frame;

        }

 

        private class rx_info

        {

            public bool rx_in_progress = false;

 

            public bool rx_msg_rcvd =false;        /* if the message has neverbeen received to be used by application level software */

            public bool tx_aborted = false;

 

            public int rx_cf_wait_time = 0;

            public boolrx_fc_wait_timeout_disable = false;

            public bool rx_overflow = false;

 

            public int lenght;

            public int offset;

            public int next_seq_num;

            public byte[] buffer;

            public byte[] frame;

        }

 

        private tx_info can_tx_info = newtx_info();

        private rx_info can_rx_info = newrx_info();

 

        #region Event

 

        public class FarmsEventArgs : EventArgs

        {

            public int id = 0;

            public int dlc = 0;

            public byte[] dat = new byte[8];

            public long time = 0;

            public override string ToString()

            {

                time %= 1000000;

                returnid.ToString("X3") + " "

                           +dlc.ToString("X1") + " "

                           + dat.HexToStrings("") + " "

                           + (time /1000).ToString() + "." + (time % 1000).ToString("d3");

            }

        }

 

        public class RxMsgEventArgs : EventArgs

        {

            public int id = 0;

            public byte[] dat;

            public long time = 0;

            public RxMsgEventArgs(int lenght)

            {

                dat = new byte[lenght];

            }

            public override string ToString()

            {

                time %= 1000000;

                returnid.ToString("X3") + " "

                           +dat.HexToStrings(" ") + " "

                           + (time /1000).ToString() + "." + (time % 1000).ToString("d3");

            }

        }

 

        public class ErrorEventArgs : EventArgs

        {

            public string error;

 

            public override string ToString()

            {

                return error;

            }

        }

 

        ///

        /// UDS 传输层发送一帧事件

        ///

        public event EventHandler EventTxFarms;

        ///

        /// UDS 传输层接收一帧事件

        ///

        public event EventHandler EventRxFarms;

        ///

        /// UDS 传输层接收完成事件

        ///

        public event EventHandler EventRxMsgs;

        ///

        /// UDS 传输层错误事件

        ///

        public event EventHandler EventError;

 

        private void TxFarmsEvent(int id,byte[] dat, int dlc, long time)

        {

            if (EventTxFarms != null)

            {

                FarmsEventArgs e_args = newFarmsEventArgs();

                e_args.id = id;

                e_args.dlc = dlc;

                e_args.time = time;

                Array.Copy(dat, e_args.dat,dlc);

                EventTxFarms(this, e_args);

            }

        }

 

        private void RxFarmsEvent(int id,byte[] dat, int dlc, long time)

        {

            if (EventRxFarms != null)

            {

                FarmsEventArgs e_args = newFarmsEventArgs();

                e_args.id = id;

                e_args.dlc = dlc;

                e_args.time = time;

                Array.Copy(dat, e_args.dat,dlc);

                EventRxFarms(this, e_args);

            }

        }

 

        private void RxMsgEvent(int id, byte[]dat)

        {

            if (EventRxMsgs != null)

            {

                int lenght = dat.Length;

                RxMsgEventArgs e_rx_msg_args =new RxMsgEventArgs(lenght);

                e_rx_msg_args.id = id;

                Array.Copy(dat,e_rx_msg_args.dat, lenght);

                EventRxMsgs(this,e_rx_msg_args);

            }

        }

 

        private void RrrorEvent(string strings)

        {

            if (EventError != null)

            {

                ErrorEventArgs e_args = newErrorEventArgs();

                e_args.error = strings;

                EventError(this, e_args);

            }

        }

 

        public delegate bool CanWriteData(intid, byte[] dat, int dlc, out long time);

        public delegate bool CanReadData(outint id, ref byte[] dat, out int dlc, out long time);

 

        ///

        /// 利用委托发送一帧数据

        ///

        public CanWriteData WriteData;

        ///

        /// 利用委托接收一帧数据

        ///

        public CanReadData ReadData;

 

        #endregion

 

        #region Trans Thread

 

        Thread testerPresent_thread;

        private void testerPresent_Thread()

        {

            while (true)

            {

                long time;

                if (WriteData != null&& WriteData(test_id, new byte[] { 0x02, 0x3E, 0x80, 0x00, 0x00, 0x00,0x00, 0x00 }, 8, out time) == true)

                {

                    Thread.Sleep(3000);

                }

            }

        }

        private bool tester = false;

        ///

        /// 诊断保持

        ///

        public bool testerPresentCheckd

        {

            set

            {

                tester = value;

                if (tester)

                {

                    testerPresent_thread = newThread(new ThreadStart(testerPresent_Thread));

                   testerPresent_thread.Start();

                }

                else

                {

                    if (testerPresent_thread !=null && testerPresent_thread.IsAlive)

                    {

                       testerPresent_thread.Abort();

                    }

                }

            }

            get

            {

                return tester;

            }

        }

        Thread trans_thread;

        private void CanTrans_Thread()

        {

            long oldTime = DateTime.Now.Ticks;

            while (true)

            {

                long cnt;

                int id;

                int dlc;

                long time;

                byte[] dat = new byte[8];

                while (true)

                {

                    bool rx_frame = false;

                    while (ReadData != null&& ReadData(out id, ref dat, out dlc, out time) == true)

                    {

                        if (id == rx_id&& dlc == 8)

                        {

                            if(can_rx_info.rx_in_progress && dat[0] == 0x02 && dat[1] == 0x7F&& dat[3] == 0x78)

                            {

                                can_rx_info.rx_cf_wait_time = 5000;

                                break;

                            }

                            Array.Copy(dat,can_rx_info.frame, 8);

                            RxFarmsEvent(id,dat, dlc, time);

                            rx_frame = true;

                            break;

                        }

                    }

                    long nowTime =DateTime.Now.Ticks;

                    cnt = nowTime - oldTime;

                    if (cnt > 10000 ||rx_frame)

                    {

                        oldTime = nowTime;

                        break;

                    }

                    else if(!can_tx_info.tx_in_progress && !can_rx_info.rx_in_progress)     //UDS空闲,释放进程

                    {

                        Thread.Sleep(1);

                    }

                }

                CanTrans_Manage((int)(cnt +5000) / 10000);

            }

        }

        ///

        /// UDS 传输层开启

        ///

        public void Start()

        {

            trans_thread = new Thread(newThreadStart(CanTrans_Thread));

            trans_thread.Priority =ThreadPriority.Highest;

            trans_thread.Start();

        }

 

        ///

        /// UDS 传输层关闭

        ///

        public void Stop()

        {

            if (trans_thread != null &&trans_thread.IsAlive)

            {

                trans_thread.Abort();

            }

            testerPresentCheckd = false;

        }

 

        #endregion

 

        private byte[] tx_msg = new byte[0];

 

        ///

        /// 发送信息

        ///

        ///

        ///

        ///

        public bool CanTrans_TxMsg(AddressingModesmode, byte[] msg)

        {

            if (msg.Length == 0)

            {

                RrrorEvent("-->Error:Tx Msg Length Is Zero");

                return false;

            }

            if (msg.Length > RX_MAX_TP_BYTES- 2)

            {

                RrrorEvent("-->Error:Tx Msg Length > RX_MAX_TP_BYTES");

                return false;

            }

            if (tx_msg.Length != 0)

            {

                RrrorEvent("-->Error:Tx Msg ing");

                return false;

            }

            if (mode ==AddressingModes.Physical_Addressing)

            {

                id = tx_id;

            }

            else

            {

                id = test_id;

            }

            tx_msg = msg;

            tx_msg = new byte[msg.Length];

            Array.Copy(msg, tx_msg,msg.Length);

            return true;

        }

 

        ///

        /// 发送信息

        ///

        ///

        ///

        ///

        public boolCanTrans_TxMsg(AddressingModes mode, string strings)

        {

            return CanTrans_TxMsg(mode,strings.StringToHex());

        }

 

        private void CanTrans_TxMsg()

        {

            if (tx_msg.Length == 0)

            {

                return;

            }

            /*

            ** Set the tx_in_progress bit...itwill be cleared when TX is done.

            */

            can_tx_info.tx_in_progress = true;

            can_tx_info.tx_last_frame_error =false;

 

            /*

            ** Assign fields in the controlstructure to initiate TX, then TX the

            ** appropriate frame type.

            */

            can_tx_info.offset = 0;

            can_tx_info.lenght = tx_msg.Length;

            can_tx_info.buffer = newbyte[tx_msg.Length];

            Array.Copy(tx_msg,can_tx_info.buffer, can_tx_info.lenght);

            can_tx_info.offset = 0;

            tx_msg = new byte[0];

 

            if (can_tx_info.lenght <= SF_DL_MAX_BYTES)

            {

               CanTrans_TxFrame(FrameType.TX_SF);

            }

            else

            {

               CanTrans_TxFrame(FrameType.TX_FF);

            }

        }

 

        private void CanTrans_TxFrame(FrameTypeframe_type)

        {

            int tx_farme_index = 0;

            int tx_data_bytes = 0;

 

            if (can_tx_info.tx_last_frame_error== false)

            {

                can_tx_info.frame = new byte[8]{ fill_byte, fill_byte, fill_byte, fill_byte, fill_byte, fill_byte, fill_byte,fill_byte };

 

                /*

                ** Place control bytes into theframe.

                */

                switch (frame_type)

                {

                    case FrameType.TX_SF: /*single frame */

                       can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.SF_TPDU |can_tx_info.lenght);

                        tx_data_bytes =can_tx_info.lenght;

                        tx_farme_index = 1;

                        break;

 

                    case FrameType.TX_FF: /* first frame */

                       can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.FF_TPDU |(can_tx_info.lenght >> 8) & 0x0F);

                       can_tx_info.frame[DL_Byte] = (byte)(can_tx_info.lenght & 0xFF);

                        tx_data_bytes = SF_DL_MAX_BYTES- 1;

                        tx_farme_index = 2;

                       can_tx_info.next_seq_num = beginning_seq_number;

                       can_rx_info.rx_fc_wait_timeout_disable = false;

                        break;

 

                    case FrameType.TX_CF: /*conscutive frame */

                       can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.CF_TPDU |can_tx_info.next_seq_num);

                        tx_farme_index = 1;

                        tx_data_bytes = (can_tx_info.lenght -can_tx_info.offset);

                        if (tx_data_bytes >SF_DL_MAX_BYTES)

                        {

                            tx_data_bytes =SF_DL_MAX_BYTES;

                        }

                       can_tx_info.next_seq_num = (can_tx_info.next_seq_num + 1) %(CF_SN_MAX_VALUE + 1);

 

                        break;

 

                    case FrameType.TX_FC: /*single frame */

                        if(can_rx_info.rx_overflow == true)

                        {

                           can_tx_info.frame[TPCI_Byte] = (byte)PCI.FC_OVFL_PDU;

                        }

                        else

                        {

                           can_tx_info.frame[TPCI_Byte] = (byte)PCI.FC_TPDU;

                        }

                       can_tx_info.frame[BS_Byte] = (byte)FC_BS_MAX_VALUE;

                       can_tx_info.frame[STminByte] = (byte)FC_ST_MIN_VALUE;

                        tx_data_bytes = 0;

                        break;

 

                    default:

                        return;

                }

 

                while (tx_data_bytes != 0)

                {

                   can_tx_info.frame[tx_farme_index++] =can_tx_info.buffer[can_tx_info.offset++];

                    tx_data_bytes--;

                }

 

            }

            long time;

            if (WriteData != null &&WriteData(id, can_tx_info.frame, 8, out time) == true)

            {

                TxFarmsEvent(id,can_tx_info.frame, 8, time);

                can_tx_info.tx_last_frame_error= false;

                can_rx_info.frame[TPCI_Byte] =0;

                /*

                ** Verify if the data has beencompletely transfered. If not, set flag to

                ** transfer CF frames. (For FCframes, s_cantp_tx_info is not used and there

                ** should not be a CF frameafter a FC frame.)

                */

                if (can_tx_info.lenght >can_tx_info.offset && frame_type != FrameType.TX_FC)

                {

                    can_tx_info.tx_in_progress =true;

 

                    if (frame_type ==FrameType.TX_FF)

                    {

                        can_tx_info.tx_wait_fc= true;

                       can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT; /* start flow controlwait timer */

                    }

                }

                else

                {

                    can_tx_info.tx_in_progress= false;

                }

            }

            else

            {

                /* user specific action incasetransmission request is not successful */

                can_tx_info.tx_last_frame_error= true;

            }

        }

 

        private void CanTrans_Manage(int tick)

        {

            CanTrans_TxMsg();

 

            CanTrans_Counter(tick);

 

            /*

            ** If new message has beenreceived, process it.

            */

            if (can_rx_info.frame[TPCI_Byte] !=0)

            {

                CanTrans_RxStateAnalyse();

                /*clear first rx frame byte tocheck a new frame next time*/

                can_rx_info.frame[TPCI_Byte] =0;

            }

 

            if (can_tx_info.tx_in_progress

                &&!can_tx_info.tx_wait_fc

                )

            {

                if (0x00 ==can_tx_info.tx_block_size)

                {

                    /* st_min time, receivedfrom tester*/

                    if (0x00 ==can_tx_info.tx_stmin_time)

                    {

                        CanTrans_TxFrame(FrameType.TX_CF);

                    }

                    else

                    {

                        /* st_min time,received from tester is not 0 */

                        if (0x00 ==can_tx_info.tx_cf_stmin_wait_time)

                        {

                           CanTrans_TxFrame(FrameType.TX_CF);

                           can_tx_info.tx_cf_stmin_wait_time = can_tx_info.tx_stmin_time;

                        }

                    }

                }

                else if (can_tx_info.tx_block_size> 1)

                {

                    if (0x00 ==can_tx_info.tx_stmin_time)

                    {

                       CanTrans_TxFrame(FrameType.TX_CF);

                        if(!can_tx_info.tx_last_frame_error)

                        {

                           can_tx_info.tx_block_size--;

                        }

                    }

                    else

                    {

                        if (0x00 ==can_tx_info.tx_cf_stmin_wait_time)

                        {

                           CanTrans_TxFrame(FrameType.TX_CF);

                            if(!can_tx_info.tx_last_frame_error)

                            {

                               can_tx_info.tx_block_size--;

                            }

 

                            /* start stmintime,interval of consecutive frame */

                           can_tx_info.tx_cf_stmin_wait_time = can_tx_info.tx_stmin_time;

                        }

                    }

 

                    if(can_tx_info.tx_block_size <= 1)

                    {

                        can_tx_info.tx_wait_fc= true;

 

                        /* start flow controlwait timer */

                       can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT;

                    }

                }

            }

            else if (can_tx_info.tx_fc_tpdu)

            {

               CanTrans_TxFrame(FrameType.TX_FC);

                can_tx_info.tx_fc_tpdu = false;

 

                /*start to counter the CF waittime*/

                can_rx_info.rx_cf_wait_time =CF_WAIT_TIMEOUT;

            }

 

            if (can_tx_info.tx_in_progress

                &&can_tx_info.tx_wait_fc

                )

            {

                /* wait for flow control frametime out! */

               if (can_tx_info.tx_fc_wait_time == 0)

                {

                    can_tx_info.tx_in_progress= false;

                    can_tx_info.tx_wait_fc =false;

                   can_tx_info.tx_last_frame_error = false;

                    RrrorEvent("-->Error: Wait For FlowControl Frame Time Out");

                }

            }

            if (can_rx_info.rx_in_progress ==true

                &&!can_tx_info.tx_fc_tpdu

              )

            {

                if (0x00 == can_rx_info.rx_cf_wait_time)

                {

                    can_rx_info.tx_aborted =true;

                    /*

                    ** wait for consecutiveframe Time out,abort Rx.

                    */

                    can_rx_info.rx_in_progress= false;

 

                    /*

                    ** When Time out occurs,ECU has to send negative

                    ** resp(71) for the firstframe.First frame is already copied in to

                    ** g_cantp_can_rx_info.msgbuffer but message length is not yet copied.

                    ** So assign data length asFirst Frame length and set RX_MSG_RCVD

                    ** flag.This flag indicatesto a new message has come.

                    */

                    can_rx_info.lenght =SF_DL_MAX_BYTES - 1;

                    can_rx_info.rx_msg_rcvd =true;

 

                   RrrorEvent("-->Error: Ecu Tx Aborted");

                }

            }

 

            if (can_rx_info.rx_msg_rcvd ==true)

            {

                can_rx_info.rx_msg_rcvd =false;

                if (can_rx_info.tx_aborted ==false)

                {

                    RxMsgEvent(rx_id,can_rx_info.buffer);

                }

                can_rx_info.tx_aborted = false;

            }

        }

 

        private void CanTrans_Counter(int tick)

        {

            /* interval of consecutive frame,STmin = 10ms, separation time */

            if(can_tx_info.tx_cf_stmin_wait_time > 0)

            {

                if(can_tx_info.tx_cf_stmin_wait_time > tick)

                {

                   can_tx_info.tx_cf_stmin_wait_time -= tick;

                }

                else

                {

                   can_tx_info.tx_cf_stmin_wait_time = 0;

                }

            }

 

            /* N_Bs, flow control frame waittime out, 75ms*/

            if (can_tx_info.tx_fc_wait_time> 0)

            {

                if (can_tx_info.tx_fc_wait_time> tick)

                {

                    can_tx_info.tx_fc_wait_time-= tick;

                }

                else

                {

                    can_tx_info.tx_fc_wait_time= 0;

                   can_rx_info.rx_fc_wait_timeout_disable = true;

                }

            }

 

            /* N_Cr,consecutive frame wait timeout, 75ms*/

            if (can_rx_info.rx_cf_wait_time> tick)

            {

                can_rx_info.rx_cf_wait_time -=tick;

            }

            else

            {

                can_rx_info.rx_cf_wait_time =0;

            }

        }

 

        private void CanTrans_RxStateAnalyse()

        {

            PCI flow_control_sts;

            int data_length = 0x00;

 

            /* single frame */

            if ((can_rx_info.frame[TPCI_Byte]& (byte)PCI.FRAME_TYPE_MASK) == (byte)PCI.SF_TPDU)

            {

                /* As per 15765-2 network layerspec when SF_DL is 0 or greater

                ** than 7, just ignore it.

                */

                data_length =(can_rx_info.frame[TPCI_Byte] & (byte)PCI.SF_DL_MASK_LONG);

 

                can_tx_info.tx_in_progress = false;

                can_tx_info.tx_wait_fc = false;

                can_rx_info.rx_in_progress =false;

                can_tx_info.tx_last_frame_error= false;

 

                if ((data_length == 0)

                 || (data_length > SF_DL_MAX_BYTES)

                  )

                {

                    return;

                }

                can_rx_info.lenght =data_length;

                can_rx_info.buffer = newbyte[can_rx_info.lenght];

                /*

                ** Copy the frame to the RXbuffer. Clear the RX_IN_PROGRESS bit

                ** (SF frame) will abortmulti-frame transfer.

                */

                Array.Copy(can_rx_info.frame,1, can_rx_info.buffer, 0, can_rx_info.lenght);

 

                can_rx_info.rx_msg_rcvd = true;

            }

            /* first frame */

            else if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.FF_TPDU)

            {

                data_length = ((int)(can_rx_info.frame[TPCI_Byte]& (byte)PCI.FF_EX_DL_MASK) << 8)

                                         +can_rx_info.frame[DL_Byte];

 

               can_rx_info.rx_fc_wait_timeout_disable = false;

                can_rx_info.lenght =data_length;

                can_rx_info.buffer = newbyte[can_rx_info.lenght];

 

                /*

                ** Clear the RX buffer, copyfirst frame to RX buffer and initiate RX.

                */

                Array.Copy(can_rx_info.frame,2, can_rx_info.buffer, 0, SF_DL_MAX_BYTES - 1);

                can_rx_info.next_seq_num =beginning_seq_number;

                can_rx_info.offset =SF_DL_MAX_BYTES - 1;

 

                can_tx_info.tx_in_progress =false;

                can_tx_info.tx_wait_fc = false;

                can_rx_info.rx_in_progress =true;

 

                /* set flag to send flowcontrol frame */

                can_tx_info.tx_fc_tpdu = true;

            }

            /* Consecutive Frame */

            else if((((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.CF_TPDU)

                /* Don't accept consecutiveframe until flow control frame sent by ECU */

                &&(!can_tx_info.tx_fc_tpdu)

                /* Don't accept consecutiveframe if we are sending CF*/

                &&(!can_tx_info.tx_in_progress))

                )

            {

                /*

                ** Ignore frame unless RX inprogress.

                */

                if (can_rx_info.rx_in_progress)

                {

                    /*

                    ** Verify the sequencenumber is as expected.

                    */

                    if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.CF_SN_MASK) ==can_rx_info.next_seq_num)

                    {

                        data_length =can_rx_info.lenght - can_rx_info.offset;

                        /*

                        **  Last frame in message?

                        */

                        if (data_length <=SF_DL_MAX_BYTES)

                        {

                            Array.Copy(can_rx_info.frame, 1,can_rx_info.buffer, can_rx_info.offset, data_length);

 

                           can_rx_info.rx_in_progress = false;

                           can_rx_info.rx_msg_rcvd = true;

                        }

                        else

                        {

                            /*

                            ** not the lastframe,copy bytes to RX buffer and

                            ** continue RXing.

                            */

                           Array.Copy(can_rx_info.frame, 1, can_rx_info.buffer, can_rx_info.offset,SF_DL_MAX_BYTES);

 

                           can_rx_info.next_seq_num = (can_rx_info.next_seq_num + 1) %(CF_SN_MAX_VALUE + 1);

                            can_rx_info.offset += SF_DL_MAX_BYTES;

                           can_rx_info.rx_cf_wait_time = CF_WAIT_TIMEOUT;

                        }

                    }

                    else

                    {

                        /*

                        ** Invalid sequence number...abort Rx.Asa diagnostic measure,

                        ** consideration wasgiven to send an FC frame here, but not done.

                        */

                       can_rx_info.rx_in_progress = false;

                        /*

                        ** When Invalidsequence number is received, ECU has to send

                        ** negative resp forthe first frame.so set RX_MSG_RCVD flag.

                        ** This flag indicatesto DiagManager as new message has come.

                        */

                        can_rx_info.tx_aborted= true;

                        can_rx_info.rx_msg_rcvd= true;

                       RrrorEvent("-->Error: Ecu Invalid Sequence Number");

                    }

                }

            }

            /* flow control frame */

            else if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.FC_TPDU)

            {

                if (can_tx_info.tx_wait_fc)

                {

                    /*

                       ** Receive Flow Status(FS) forTransmiting the CF Frames.

                       ** The value of FS shall be setto zero that means that the

                       ** tester is ready to receive amaximum number of CF.

                       */

                    flow_control_sts =PCI.FC_STATUS_CONTINUE;

                    if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FC_STATUS_MASK) != 0x00)

                    {

                        /* Flow Status(FS)

                           ** 0: Continue to send(CTS)

                           ** 1: wait(WT)

                           ** 2: Overflow(OVFLW)

                           */

 

                        flow_control_sts =(PCI)(can_rx_info.frame[TPCI_Byte] & (byte)PCI.FC_STATUS_MASK);

                    }

 

                    /*

                    ** Receive the BS and STmin time for Transmiting the CF Frames.

                    */

                    if(can_rx_info.frame[BS_Byte] != 0x00)

                    {

                        can_tx_info.tx_block_size= can_rx_info.frame[BS_Byte] + 1;

                    }

                    else

                    {

                       can_tx_info.tx_block_size = 0x00;

                    }

 

                    if ((can_rx_info.frame[STminByte]& 0x7F) != 0x00)

                    {

                        /*

                        ** Valid Range forSTMin timeout is 0 - 127ms.

                        */

                       can_tx_info.tx_stmin_time = (can_rx_info.frame[STminByte] & 0x7F) +5;   /* extend the delay time */

                    }

                    else

                    {

                       can_tx_info.tx_stmin_time = 20;

                    }

 

                    if ((flow_control_sts ==PCI.FC_STATUS_CONTINUE)

                     &&(can_rx_info.rx_fc_wait_timeout_disable == false)

                      )

                    {

                        can_tx_info.tx_wait_fc= false;

                       can_tx_info.tx_fc_wait_time = 0;

                    }

                    else if (flow_control_sts== PCI.FC_STATUS_WAIT)

                    {

                       can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT;  /* if wait, we will wait another time */

                    }

                    else if (flow_control_sts ==PCI.FC_STATUS_OVERFLOW)

                    {

                        /* do nothing here, ifover flow, we will stop sending

                           any message until wegot new cmd */

                        can_tx_info.tx_fc_wait_time= 1;   /* exit after 10ms */

                       RrrorEvent("-->Error: Ecu Buff Over Flow");

                    }

                    else

                    {

                        /* do nothing here, ifover flow, we will stop sending

                           any message until wegot new cmd */

                       can_tx_info.tx_fc_wait_time = 1;  /* exit after 10ms */

                    }

                }

            }

        }

    }

}

 

你可能感兴趣的:(基于CAN总线的汽车诊断协议UDS(上位机开发网络层及错误代码解析))