/******************************************************************************
�� �� ����Communication_Over_CAN.c
��������������CAN���ߵ��ź��շ��������ļ�
��    �ߣ�����
��    ����V1.3
��    �ڣ�2017.5.31
******************************************************************************/

#include "Communication_Over_CAN.h"
#pragma MESSAGE DISABLE C4301

CoCANTxMsgFIFOStruct     CoCANTxMsgFIFO;
CoCANRxMsgFIFOStruct     CoCANRxMsgFIFO;

CoCANTxMsgIDLookupStruct CoCANTxMsgTable[CAN_TX_MSG_NUM];
CoCANRxMsgIDLookupStruct CoCANRxMsgTable[CAN_RX_MSG_NUM];

CoCANCycleMsgStruct      CoCANCycleMsg;

CoCANCtrlStruct          CoCANCtrl;

/******************************************************************************
��������CoCAN_L_Data_Indication
��  �ܣ�����·�㴫�ݶ���,����ָʾ���ݵĵ��ﲢ��������
        �ú������뱻�²�(��·��)��������
��  ����Identifier ��CAN����ID
        DLC        ���������ݳ���
        Data       ��������������
����ֵ����
******************************************************************************/
void CoCAN_L_Data_Indication ( uint16_t Identifier, uint8_t DLC, uint8_t *Data )
{
    uint8_t i;

    //����Ƿ��������ձ���
    if ( CoCANCtrl.RxEnable != CoCAN_ENABLE )
        return;

    //���FIFO�Ƿ�����
    if ( CoCANRxMsgFIFO.Depth >= CoCAN_RX_MSG_FIFO_MAX_DEPTH )
        return;

    //��������
    CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].Identifier = Identifier;

    for ( i = 0; i < DLC; i++ )
        CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].Data[i]  = Data[i];

    CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].DLC        = DLC;
    //FIFO����
    CoCANRxMsgFIFO.Depth++;
    CoCANRxMsgFIFO.Iptr++;

    if ( CoCANRxMsgFIFO.Iptr >= CoCAN_RX_MSG_FIFO_MAX_DEPTH )
        CoCANRxMsgFIFO.Iptr = 0;
}

/******************************************************************************
��������CoCAN_L_Data_Request
��  �ܣ�����·�㴫�ݱ���,��������
��  ����Identifier������ID
        DLC       �����ij���
        Data      ����������
����ֵ����
******************************************************************************/
#pragma INLINE
void CoCAN_L_Data_Request ( uint16_t Identifier, uint8_t DLC, uint8_t *Data )
{
    MSCAN0_L_Data_Request ( Identifier, DLC, Data, 2 );
}

/******************************************************************************
��������CoCAN_L_Data_Confirm
��  �ܣ�����·�㴫�ݶ���,����ָʾ���ݵķ��ͽ��
        �ú������뱻�²�(��·��)��������
��  ����Identifier    ��CAN����ID
        TransferStatus�����ķ��ͽ����COMPLETE     �������
                                      NOT_COMPLETE ����δ�ܷ������
����ֵ����
******************************************************************************/
/*void CoCAN_L_Data_Confirm(uint16_t Identifier, uint8_t TransferStatus)
{
  uint8_t i;
  uint8_t Index;

  Index = CoCAN_Search_Tx_Msg(Identifier);

  if (Index != 0xFF)
  {
    //if (TransferStatus == COMPLETE)
    //{
      CoCANTxMsgTable[Index].TxReq = CoCAN_TX_IDLE;

      //�����Ա���������һ�η���ʱ��
      i = CoCANTxMsgTable[Index].Index;
      if (i != 0xFF)
        CoCANCycleMsg.TxTimer[i] = CoCANCtrl.Timer + CoCANTxMsgTable[Index].Cycle;

      *CoCANTxMsgTable[Index].pStatus |= CAN_UPDATE;
    //}
    //else
    //{
    //  if (CoCANTxMsgTable[Index].TxReq == CoCAN_TX_ON)      //ȷ�������͵�����ʧ��������װ�뷢��FIFO
    //  {
    //    CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Iptr] = Index;

        //FIFO����
    //    if (CoCANTxMsgFIFO.Depth < CAN_TX_MSG_NUM)
    //      CoCANTxMsgFIFO.Depth++;
    //    CoCANTxMsgFIFO.Iptr++;
    //    if (CoCANTxMsgFIFO.Iptr >= CAN_TX_MSG_NUM)
    //      CoCANTxMsgFIFO.Iptr = 0;

        //������������
    //    CoCANTxMsgTable[Index].TxReq = CoCAN_TX_REQ;
    //  }
    //}
  }
}*/

/******************************************************************************
��������CoCAN_Init
��  �ܣ�CAN�����ź��շ���ʼ������
        ���ڳ�ʼ�����źų�ʼֵ,��ʼ�����Ķ�ʱ��,�Լ����ɱ��Ŀ��ٲ��ұ�
��  ������
����ֵ����
******************************************************************************/
void CoCAN_Init ( void )
{
    uint8_t   i;
    uint8_t   Index;
    uint8_t   RxMsgNum;
    uint8_t   TxMsgNum;
    uint16_t  Identifier;
    //���ɱ��Ŀ��ٲ��ұ�
    //���ٲ��ұ����ɹ�����Index��Ա����ʱ���ڴ�ű��Ĵ洢�����Ա��е�λ����Ϣ
    //��λ����Ϣ�����ں��������в��ұ�����������䱨�Ŀ��ٲ��ұ�
    RxMsgNum             = 0;
    TxMsgNum             = 0;

    for ( Index = 0; Index < CoCAN_TOTAL_MSG_NUM; Index++ )
    {
        Identifier = CANMsgAttrTable[Index].ID;

        //�ҵ����ձ���,�������ɽ��ձ��Ŀ��ٲ��ұ�
        if ( CANMsgAttrTable[Index].Dir == CAN_MSG_Rx )
        {
            if ( RxMsgNum == 0 )        //���ٲ��ұ���һ������⴦��
            {
                CoCANRxMsgTable[0].Identifier = Identifier;
                CoCANRxMsgTable[0].Index      = Index;
            }
            else                        //���ݱ���ID�Ӵ�С���в��ұ�
            {
                i = RxMsgNum;

                while ( i )
                {
                    if ( CoCANRxMsgTable[i - 1].Identifier > Identifier )
                    {
                        CoCANRxMsgTable[i].Identifier = CoCANRxMsgTable[i - 1].Identifier;
                        CoCANRxMsgTable[i].Index      = CoCANRxMsgTable[i - 1].Index;
                        CoCANRxMsgTable[i - 1].Identifier = Identifier;
                        CoCANRxMsgTable[i - 1].Index      = Index;
                    }
                    else
                    {
                        CoCANRxMsgTable[i].Identifier = Identifier;
                        CoCANRxMsgTable[i].Index      = Index;
                        break;
                    }

                    i--;
                }
            }

            RxMsgNum++;
        }
        //�ҵ����ͱ���,�������ɷ��ͱ��Ŀ��ٲ��ұ�
        else
        {
            if ( TxMsgNum == 0 )        //���ٲ��ұ���һ������⴦��
            {
                CoCANTxMsgTable[0].Identifier = Identifier;
                CoCANTxMsgTable[0].Index      = Index;
            }
            else                        //���ݱ���ID�Ӵ�С���в��ұ�
            {
                i = TxMsgNum;

                while ( i )
                {
                    if ( CoCANTxMsgTable[i - 1].Identifier > Identifier )
                    {
                        CoCANTxMsgTable[i].Identifier = CoCANTxMsgTable[i - 1].Identifier;
                        CoCANTxMsgTable[i].Index      = CoCANTxMsgTable[i - 1].Index;
                        CoCANTxMsgTable[i - 1].Identifier = Identifier;
                        CoCANTxMsgTable[i - 1].Index      = Index;
                    }
                    else
                    {
                        CoCANTxMsgTable[i].Identifier = Identifier;
                        CoCANTxMsgTable[i].Index      = Index;
                        break;
                    }

                    i--;
                }
            }

            TxMsgNum++;
        }
    }

#if CoCAN_MSG_NUM_CHECK

    //���Ա��еı��������붨��ı���������һ��ʱ������ѭ���ȴ����Ź���λ
    if ( CoCAN_TOTAL_MSG_NUM != CAN_TX_MSG_NUM + CAN_RX_MSG_NUM )
        for ( ;; );

    //���Ա��еı��������붨��ı���������һ��ʱ������ѭ���ȴ����Ź���λ
    if ( ( TxMsgNum != CAN_TX_MSG_NUM ) || ( RxMsgNum != CAN_RX_MSG_NUM ) )
        for ( ;; );

#endif
    //���Ʊ��IJ��ұ���Ϣ,���������Ա��Ĺ�����
    CoCANCycleMsg.TxNum  = 0;
    CoCANCycleMsg.RxNum  = 0;

    //���ͱ���
    for ( i = 0; i < CAN_TX_MSG_NUM; i++ )
    {
        Index = CoCANTxMsgTable[i].Index;       //ȡ�����Ĵ洢�����Ա��е�λ����Ϣ

        if ( CANMsgAttrTable[Index].Type == CAN_MSG_CYCLE )
        {
            CoCANTxMsgTable[i].Offset = CANMsgAttrTable[Index].Offset;
            CoCANTxMsgTable[i].Cycle  = CANMsgAttrTable[Index].Cycle;
            CoCANTxMsgTable[i].Index  = CoCANCycleMsg.TxNum;
            CoCANCycleMsg.TxIndex[CoCANCycleMsg.TxNum] = i;
            CoCANCycleMsg.TxNum++;
        }
        else
            CoCANTxMsgTable[i].Index = 0xFF;      //��ʾ�������Ա���

        CoCANTxMsgTable[i].DLC     = CANMsgAttrTable[Index].DLCMax;
        CoCANTxMsgTable[i].pMsg    = CANMsgAttrTable[Index].pMsg;
        CoCANTxMsgTable[i].pInit   = CANMsgAttrTable[Index].pInit;
        CoCANTxMsgTable[i].pStatus = CANMsgAttrTable[Index].pStatus;
    }

    //���ձ���
    for ( i = 0; i < CAN_RX_MSG_NUM; i++ )
    {
        Index = CoCANRxMsgTable[i].Index;       //ȡ�����Ĵ洢�����Ա��е�λ����Ϣ

        if ( CANMsgAttrTable[Index].Type == CAN_MSG_CYCLE )
        {
            CoCANRxMsgTable[i].Cycle = CANMsgAttrTable[Index].Cycle;
            CoCANRxMsgTable[i].Index = CoCANCycleMsg.RxNum;
            CoCANCycleMsg.RxIndex[CoCANCycleMsg.RxNum] = i;
            CoCANCycleMsg.RxNum++;
        }
        else
            CoCANRxMsgTable[i].Index = 0xFF;      //��ʾ�������Ա���

        CoCANRxMsgTable[i].DLCMax   = CANMsgAttrTable[Index].DLCMax;
        CoCANRxMsgTable[i].DLCMin   = CANMsgAttrTable[Index].DLCMin;
        CoCANRxMsgTable[i].pMsg     = CANMsgAttrTable[Index].pMsg;
        CoCANRxMsgTable[i].pInit    = CANMsgAttrTable[Index].pInit;
        CoCANRxMsgTable[i].pTimeOut = CANMsgAttrTable[Index].pTimeOut;
        CoCANRxMsgTable[i].pMask    = CANMsgAttrTable[Index].pMask;
        CoCANRxMsgTable[i].pStatus  = CANMsgAttrTable[Index].pStatus;
    }

    CoCAN_Reset();
    CoCAN_Set_Mode ( CoCAN_MODE_INIT );      //�����ڳ�ʼ��ģʽ
}

/******************************************************************************
��������CoCAN_Reset
��  �ܣ�����CAN�����շ�״̬,�ú�����Ӱ�죺
        1.����/����FIFO�������
        2.���źŻָ�����ʼֵ
        3.����״̬�ָ�����ʼ��״̬
        4.���з������󽫱�ȡ��
        5.����/���Ͷ�ʱ����������
        ���ñ�����,����Ӱ��CANͨ�ŵĽ���/����ʹ��״̬
��  ������
����ֵ����
******************************************************************************/
void CoCAN_Reset ( void )
{
    uint8_t i;
    uint8_t j;
    //��ʼ�����ͱ���FIFO
    CoCANTxMsgFIFO.Iptr  = 0;
    CoCANTxMsgFIFO.Optr  = 0;
    CoCANTxMsgFIFO.Depth = 0;
    //��ʼ�����ձ���FIFO
    CoCANRxMsgFIFO.Iptr  = 0;
    CoCANRxMsgFIFO.Optr  = 0;
    CoCANRxMsgFIFO.Depth = 0;

    //���ͱ���
    for ( i = 0; i < CAN_TX_MSG_NUM; i++ )
    {
        //��ʼ�������ź�ֵ
        for ( j = 0; j < CoCANTxMsgTable[i].DLC; j++ )
            CoCANTxMsgTable[i].pMsg[j] = CoCANTxMsgTable[i].pInit[j];

        //��ʼ������״̬
        *CoCANTxMsgTable[i].pStatus  = 0x00;
        //�����������
        CoCANTxMsgTable[i].TxReq   = CoCAN_TX_IDLE;
    }

    //���ձ���
    for ( i = 0; i < CAN_RX_MSG_NUM; i++ )
    {
        //��ʼ������
        for ( j = 0; j < CoCANRxMsgTable[i].DLCMax; j++ )
            CoCANRxMsgTable[i].pMsg[j] = CoCANRxMsgTable[i].pInit[j];

        //��ʼ������״̬
        *CoCANRxMsgTable[i].pStatus  = 0x00;
    }

    //���ö�ʱ��
    CoCANCtrl.Timer = 0;

    for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
        CoCANCycleMsg.TxTimer[i] = CoCANTxMsgTable[CoCANCycleMsg.TxIndex[i]].Offset;

    for ( i = 0; i < CoCANCycleMsg.RxNum; i++ )
        CoCANCycleMsg.RxTimer[i] = CoCANRxMsgTable[CoCANCycleMsg.RxIndex[i]].Cycle;
}

/******************************************************************************
��������CoCAN_Set_Mode
��  �ܣ�����CANͨ�ŵĹ���ģʽ
��  ����Mode��CoCAN_MODE_INIT   - ��ʼ��ģʽ,���Ľ��ں�̨���жϳ�����
              CoCAN_MODE_NORMAL - ��������ģʽ,�����ɱ��ķ��ͳ�����з���
����ֵ����
******************************************************************************/
void CoCAN_Set_Mode ( uint8_t Mode )
{
    uint8_t i;

    if ( Mode == CoCAN_MODE_INIT )
    {
        if ( CoCANCtrl.Mode != CoCAN_MODE_INIT )
        {
            CoCANCtrl.Mode = CoCAN_MODE_INIT;
            CoCANCtrl.Prescaler = 0;
        }
    }
    else
    {
        if ( CoCANCtrl.Mode != CoCAN_MODE_NORMAL )
        {
            CoCANCtrl.Mode = CoCAN_MODE_NORMAL;

            //���ý��ձ��Ķ�ʱ��
            for ( i = 0; i < CoCANCycleMsg.RxNum; i++ )
                CoCANCycleMsg.RxTimer[i] = CoCANRxMsgTable[CoCANCycleMsg.RxIndex[i]].Cycle + CoCANCtrl.Timer;
        }
    }
}

/******************************************************************************
��������CoCAN_Rx_Enable
��  �ܣ�CAN����ͨ�Ž��չ���ʹ��/�ر�
��  ����En��CoCAN_DISABLE        - ��ֹCAN����ͨ�Ž��չ���
            COCAN_PSEUDO_DISABLE - ��ֹCAN����ͨ�Ž��չ���,������������ĵ���״̬
            CoCAN_ENABLE         - CAN����ͨ�Ž��չ���ʹ��
����ֵ����
******************************************************************************/
void CoCAN_Rx_Enable ( uint8_t En )
{
    uint8_t i;

    if ( ( En == CoCAN_DISABLE ) || ( En == COCAN_PSEUDO_DISABLE ) )
        CoCANCtrl.RxEnable = En;
    else
    {
        if ( CoCANCtrl.RxEnable != CoCAN_ENABLE )
        {
            CoCANCtrl.RxEnable = CoCAN_ENABLE;

            //���ý��ձ��Ķ�ʱ��
            for ( i = 0; i < CoCANCycleMsg.RxNum; i++ )
                CoCANCycleMsg.RxTimer[i] = CoCANRxMsgTable[CoCANCycleMsg.RxIndex[i]].Cycle + CoCANCtrl.Timer;
        }
    }
}

/******************************************************************************
��������CoCAN_Tx_Enable
��  �ܣ�CAN����ͨ�ŷ��͹���ʹ��/�ر�
��  ����En��CoCAN_DISABLE - ��ֹCAN����ͨ�ŷ��͹���
            CoCAN_ENABLE  - ʹ��CAN����ͨ�ŷ��͹���
����ֵ����
******************************************************************************/
void CoCAN_Tx_Enable ( uint8_t En )
{
    uint8_t i;

    if ( En < CoCAN_ENABLE )
    {
        if ( CoCANCtrl.TxEnable == CoCAN_ENABLE )
        {
            //��շ��ͱ���FIFO
            CoCANTxMsgFIFO.Iptr  = 0;
            CoCANTxMsgFIFO.Optr  = 0;
            CoCANTxMsgFIFO.Depth = 0;

            //�����������
            for ( i = 0; i < CAN_TX_MSG_NUM; i++ )
                CoCANTxMsgTable[i].TxReq = CoCAN_TX_IDLE;
        }

        CoCANCtrl.TxEnable = CoCAN_DISABLE;
    }
    else
    {
        if ( CoCANCtrl.TxEnable != CoCAN_ENABLE )
        {
            CoCANCtrl.TxEnable = CoCAN_ENABLE;

            //���÷��ͱ��Ķ�ʱ��
            for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
                CoCANCycleMsg.TxTimer[i] = CoCANTxMsgTable[CoCANCycleMsg.TxIndex[i]].Offset + CoCANCtrl.Timer;
        }
    }
}

/******************************************************************************
��������CoCAN_Search_Tx_Msg
��  �ܣ��ӷ��ͱ��Ŀ��ٲ��ұ����ҵ�Ŀ�걨��ID����Ϣ�洢λ��
��  ����Identifier��Ŀ�걨��ID
����ֵ���ñ��ĵ���Ϣ�ڷ��ͱ��Ŀ��ٲ��ұ��еĴ洢λ��
        0xFF��ʾδ���ҵ�����
******************************************************************************/
#pragma INLINE
uint8_t CoCAN_Search_Tx_Msg ( uint16_t Identifier )
{
    uint8_t SearchStart;
    uint8_t SearchPoint;
    uint8_t SearchLen;
    SearchStart = 0;                //�ӷ��Ϳ��ٲ��ұ��ĵ׶������
    SearchLen   = CAN_TX_MSG_NUM;   //���ҳ���Ϊ�������ұ�

    //�����õݹ�ṹ����Ƶ����ջ��ջ��ɵ�ʱ���˷�
    while ( SearchLen )
    {
        SearchPoint = SearchStart + SearchLen / 2;

        if ( CoCANTxMsgTable[SearchPoint].Identifier == Identifier )
        {
            return SearchPoint;
        }
        else if ( CoCANTxMsgTable[SearchPoint].Identifier < Identifier )
        {
            //Ŀ��ID�Ȳ��ҵ��IDֵ��,����Ҳ��ҵ�֮��IJ��ұ�
            //�����һ�εIJ������Ϊ���εIJ��ҵ�֮���һ��,���ҳ���Ϊʣ��IJ��ұ����� - 1
            SearchStart = SearchPoint + 1;
            SearchLen   = SearchLen - SearchLen / 2 - 1;
        }
        else
        {
            //Ŀ��ID�Ȳ��ҵ��IDֵС,����Ҳ��ҵ�֮ǰ�IJ��ұ�
            //�����һ�εIJ��������Ϊԭ������㲻��,���ҳ��ȼ���
            SearchLen   = SearchLen / 2;
        }
    }

    //�������δ���ҵ�Ŀ��ID
    return 0xFF;
}

/******************************************************************************
��������CoCAN_Search_Rx_Msg
��  �ܣ��ӽ��ձ��Ŀ��ٲ��ұ����ҵ�Ŀ�걨��ID����Ϣ�洢λ��
��  ����Identifier��Ŀ�걨��ID
����ֵ���ñ��ĵ���Ϣ�ڽ��ձ��Ŀ��ٲ��ұ��еĴ洢λ��
        0xFF��ʾδ���ҵ�����
******************************************************************************/
#pragma INLINE
uint8_t CoCAN_Search_Rx_Msg ( uint16_t Identifier )
{
    uint8_t SearchStart;
    uint8_t SearchPoint;
    uint8_t SearchLen;
    SearchStart = 0;                //�ӽ��տ��ٲ��ұ��ĵ׶������
    SearchLen   = CAN_RX_MSG_NUM;   //���ҳ���Ϊ�������ұ�

    //�����õݹ�ṹ����Ƶ����ջ��ջ��ɵ�ʱ���˷�
    while ( SearchLen )
    {
        SearchPoint = SearchStart + SearchLen / 2;

        if ( CoCANRxMsgTable[SearchPoint].Identifier == Identifier )
        {
            return SearchPoint;
        }
        else if ( CoCANRxMsgTable[SearchPoint].Identifier < Identifier )
        {
            //Ŀ��ID�Ȳ��ҵ��IDֵ��,����Ҳ��ҵ�֮��IJ��ұ�
            //�����һ�εIJ������Ϊ���εIJ��ҵ�֮���һ��,���ҳ���Ϊʣ��IJ��ұ����� - 1
            SearchStart = SearchPoint + 1;
            SearchLen   = SearchLen - SearchLen / 2 - 1;
        }
        else
        {
            //Ŀ��ID�Ȳ��ҵ��IDֵС,����Ҳ��ҵ�֮ǰ�IJ��ұ�
            //�����һ�εIJ��������Ϊԭ������㲻��,���ҳ��ȼ���
            SearchLen   = SearchLen / 2;
        }
    }

    //�������δ���ҵ�Ŀ��ID
    return 0xFF;
}

/******************************************************************************
��������CoCAN_Signal_Update_Service
��  �ܣ�CAN�����źŸ��·�����
        �ú��������У�1.�����յ��ı��Ľ��������ź�
                      2.��ر����Ƿ��б��Ķ�ʧ
                      3.��ʱ���������Է��ͱ���
��  ������
����ֵ����
*******************************************************************************
ע  �⣺�÷���������ÿ1ms������һ��
******************************************************************************/
void CoCAN_Signal_Update_Service ( void )
{
    uint8_t   i;
    uint8_t   j;
    uint8_t   Index;
    uint16_t  Identifier;
    //һ�����ø÷�����,˵��ϵͳ�Ѿ������ʼ���׶�,��������CANͨ�Ź���ģʽתΪ��������ģʽ
    CoCAN_Set_Mode ( CoCAN_MODE_NORMAL );

    //�ӱ��Ľ���FIFO����ȡ����
    while ( CoCANRxMsgFIFO.Depth )
    {
        Identifier = CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Optr].Identifier;
        Index      = CoCAN_Search_Rx_Msg ( Identifier );

        if ( Index != 0xFF )
        {
            //��֤���ij���
            if ( ( CoCANRxMsgTable[Index].DLCMax >= CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Optr].DLC ) && \
                    ( CoCANRxMsgTable[Index].DLCMin <= CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Optr].DLC ) )
            {
                //������һ�γ�ʱ����
                if ( CoCANRxMsgTable[Index].Index != 0xFF )
                    CoCANCycleMsg.RxTimer[CoCANRxMsgTable[Index].Index] = CoCANCtrl.Timer + CoCANRxMsgTable[Index].Cycle;

                //��������������Buffer
                for ( i = 0; i < CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Optr].DLC; i++ )
                    CoCANRxMsgTable[Index].pMsg[i] = CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Optr].Data[i];

                //������Ķ�ʧ״̬,�ñ��ĸ��±�־
                *CoCANRxMsgTable[Index].pStatus = CAN_UPDATE;
            }
        }

        //FIFO����
        CoCANRxMsgFIFO.Depth--;
        CoCANRxMsgFIFO.Optr++;

        if ( CoCANRxMsgFIFO.Optr >= CoCAN_RX_MSG_FIFO_MAX_DEPTH )
            CoCANRxMsgFIFO.Optr = 0;
    }

    //����COCAN_PSEUDO_DISABLE����״̬��ʱ�������ڽ��ձ��ļ��
    if ( CoCANCtrl.RxEnable != COCAN_PSEUDO_DISABLE )
    {
        for ( i = 0; i < CoCANCycleMsg.RxNum; i++ )
        {
            //������ĵ�����,��������Ĭ��ֵ
            if ( CoCANCycleMsg.RxTimer[i] == CoCANCtrl.Timer )
            {
                Index = CoCANCycleMsg.RxIndex[i];

                for ( j = 0; j < CoCANRxMsgTable[Index].DLCMax; j++ )
                {
                    CoCANRxMsgTable[Index].pMsg[j] &= CoCANRxMsgTable[Index].pMask[j];
                    CoCANRxMsgTable[Index].pMsg[j] |= CoCANRxMsgTable[Index].pTimeOut[j];
                }

                //�ñ��Ķ�ʧ״̬
                *CoCANRxMsgTable[Index].pStatus |= CAN_MSG_LOST;
            }
        }
    }

    if ( CoCANCtrl.TxEnable == CoCAN_ENABLE )
    {
        //���ڷ��ͱ��ķ���
        for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
        {
            //������ķ���ʱ�䵽,��Ҫ���͵ı���װ�뷢��FIFO
            if ( CoCANCycleMsg.TxTimer[i] == CoCANCtrl.Timer )
            {
                Index = CoCANCycleMsg.TxIndex[i];

                if ( *CoCANTxMsgTable[Index].pStatus & CAN_TX_EN )
                {
                    //if (CoCANTxMsgTable[Index].TxReq == CoCAN_TX_IDLE)
                    //{
                    CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Iptr] = Index;

                    //FIFO����
                    if ( CoCANTxMsgFIFO.Depth < CAN_TX_MSG_NUM )
                        CoCANTxMsgFIFO.Depth++;

                    CoCANTxMsgFIFO.Iptr++;

                    if ( CoCANTxMsgFIFO.Iptr >= CAN_TX_MSG_NUM )
                        CoCANTxMsgFIFO.Iptr = 0;

                    //������������
                    //CoCANTxMsgTable[Index].TxReq = CoCAN_TX_REQ;
                    //CoCANTxMsgTable[Index].TxReq = CoCAN_TX_IDLE;
                    //�����Ա���������һ�η���ʱ��
                    CoCANCycleMsg.TxTimer[i] = CoCANCtrl.Timer + CoCANTxMsgTable[Index].Cycle;
                    *CoCANTxMsgTable[Index].pStatus |= CAN_UPDATE;
                    //}
                }
            }
        }
    }

    //�����ķ���FIFO�еı��ķ��ͳ�ȥ
    if ( CoCANTxMsgFIFO.Depth )
    {
        //һ��ֻ����1������
        Index = CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Optr];
        //���ķ�����
        CoCANTxMsgTable[Index].TxReq = CoCAN_TX_ON;
        CoCAN_L_Data_Request ( CoCANTxMsgTable[Index].Identifier, CoCANTxMsgTable[Index].DLC, ( uint8_t * ) CoCANTxMsgTable[Index].pMsg );
        //FIFO����
        CoCANTxMsgFIFO.Depth--;
        CoCANTxMsgFIFO.Optr++;

        if ( CoCANTxMsgFIFO.Optr >= CAN_TX_MSG_NUM )
            CoCANTxMsgFIFO.Optr = 0;
    }

    //ȫ�ֶ�ʱ����
    CoCANCtrl.Timer++;

    if ( CoCANCtrl.Timer > 0x7FFF )                //����ֵΪ 0 - 23767,���λ��Ϊ��λλ
    {
        CoCANCtrl.Timer &= 0x7FFF;                   //����ʱ��ѭ������һ����,����ʱ�������λλ

        for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
            CoCANCycleMsg.TxTimer[i] &= 0x7FFF;

        for ( i = 0; i < CoCANCycleMsg.RxNum; i++ )
            CoCANCycleMsg.RxTimer[i] &= 0x7FFF;
    }
}

/******************************************************************************
��������CoCAN_Transmit_Message
��  �ܣ������ͱ���
        �����͵ı��ļȿ����������͵�,Ҳ�������¼��͵�,���ñ����ڱ������Ա��б�
        �뱻����Ϊ���ͱ���
        ��������Է��ͱ����ڱ���ֹ���ֱ�����ʹ��,��ʹ�ܵ�ͬʱӦ���ô˺���������
        �������ĵ������Է���
��  ����Identifier������ID
����ֵ����
******************************************************************************/
void CoCAN_Transmit_Message ( uint16_t Identifier )
{
    uint8_t Index;

    if ( CoCANCtrl.TxEnable != CoCAN_ENABLE )
        return;

    Index = CoCAN_Search_Tx_Msg ( Identifier );

    if ( Index != 0xFF )            //����λ�ڷ��Ϳ��ٲ��ұ���
    {
        if ( *CoCANTxMsgTable[Index].pStatus & CAN_TX_EN )
        {
            if ( CoCANTxMsgTable[Index].TxReq == CoCAN_TX_IDLE )
            {
                CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Iptr] = Index;

                //FIFO����
                if ( CoCANTxMsgFIFO.Depth < CAN_TX_MSG_NUM )
                    CoCANTxMsgFIFO.Depth++;

                CoCANTxMsgFIFO.Iptr++;

                if ( CoCANTxMsgFIFO.Iptr >= CAN_TX_MSG_NUM )
                    CoCANTxMsgFIFO.Iptr = 0;

                //������������
                CoCANTxMsgTable[Index].TxReq = CoCAN_TX_REQ;
            }
        }
    }
}

/******************************************************************************
��������CoCAN_Modify_Tx_Msg_Cycle
��  �ܣ��޸ı��ĵķ�������
        �ú������������Է��ͱ�����Ч,�����޸ĵı������¼��͵Ļ����ǽ��ձ���,��
        ��������κ�Ч��
        �����ڻ�����һ�α��ķ��ͳɹ�����Ч
��  ����Identifier������ID
        Cycle     ��Ŀ�걨������
����ֵ����
******************************************************************************/
void CoCAN_Modify_Tx_Msg_Cycle ( uint16_t Identifier, uint16_t Cycle )
{
    uint8_t Index;
    Index = CoCAN_Search_Tx_Msg ( Identifier );

    if ( Index != 0xFF )                            //����λ�ڷ��Ϳ��ٲ��ұ���
        CoCANTxMsgTable[Index].Cycle = Cycle;
}

/******************************************************************************
��������CoCAN_Init_Mode_Tx_ISR
��  �ܣ���ʼ��ģʽ��CANͨ�ű��ķ����жϷ�����
��  ������
����ֵ����
*******************************************************************************
ע  �⣺�÷��������뱻Ƕ�뵽��ʱ�ж���
******************************************************************************/
void CoCAN_Init_Mode_Tx_ISR ( void )
{
    uint8_t   i;
    uint8_t   Index;

    if ( CoCANCtrl.Mode != CoCAN_MODE_INIT )
        return;

    CoCANCtrl.Prescaler++;

    if ( CoCANCtrl.Prescaler > ( uint8_t ) ( 1000 / API_INT_CYCLE ) )
    {
        CoCANCtrl.Prescaler = 0;

        if ( CoCANCtrl.TxEnable == CoCAN_ENABLE )
        {
            //���ڷ��ͱ��ķ���
            for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
            {
                //������ķ���ʱ�䵽,��Ҫ���͵ı���װ�뷢��FIFO
                if ( CoCANCycleMsg.TxTimer[i] == CoCANCtrl.Timer )
                {
                    Index = CoCANCycleMsg.TxIndex[i];

                    if ( *CoCANTxMsgTable[Index].pStatus & CAN_TX_EN )
                    {
                        //if (CoCANTxMsgTable[Index].TxReq == CoCAN_TX_IDLE)
                        //{
                        CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Iptr] = Index;

                        //FIFO����
                        if ( CoCANTxMsgFIFO.Depth < CAN_TX_MSG_NUM )
                            CoCANTxMsgFIFO.Depth++;

                        CoCANTxMsgFIFO.Iptr++;

                        if ( CoCANTxMsgFIFO.Iptr >= CAN_TX_MSG_NUM )
                            CoCANTxMsgFIFO.Iptr = 0;

                        //������������
                        //CoCANTxMsgTable[Index].TxReq = CoCAN_TX_REQ;
                        //CoCANTxMsgTable[Index].TxReq = CoCAN_TX_IDLE;
                        //�����Ա���������һ�η���ʱ��
                        CoCANCycleMsg.TxTimer[i] = CoCANCtrl.Timer + CoCANTxMsgTable[Index].Cycle;
                        *CoCANTxMsgTable[Index].pStatus |= CAN_UPDATE;
                        //}
                    }
                }
            }
        }

        //�����ķ���FIFO�еı��ķ��ͳ�ȥ
        if ( CoCANTxMsgFIFO.Depth )
        {
            //һ��ֻ����1������
            Index = CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Optr];
            //���ķ�����
            CoCANTxMsgTable[Index].TxReq = CoCAN_TX_ON;
            CoCAN_L_Data_Request ( CoCANTxMsgTable[Index].Identifier, CoCANTxMsgTable[Index].DLC, ( uint8_t * ) CoCANTxMsgTable[Index].pMsg );
            //FIFO����
            CoCANTxMsgFIFO.Depth--;
            CoCANTxMsgFIFO.Optr++;

            if ( CoCANTxMsgFIFO.Optr >= CAN_TX_MSG_NUM )
                CoCANTxMsgFIFO.Optr = 0;
        }

        //ȫ�ֶ�ʱ����
        CoCANCtrl.Timer++;

        if ( CoCANCtrl.Timer > 0x7FFF )                //����ֵΪ 0 - 23767,���λ��Ϊ��λλ
        {
            CoCANCtrl.Timer &= 0x7FFF;                   //����ʱ��ѭ������һ����,����ʱ�������λλ

            for ( i = 0; i < CoCANCycleMsg.TxNum; i++ )
                CoCANCycleMsg.TxTimer[i] &= 0x7FFF;
        }
    }
}