/******************************************************************************
�� �� ����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;



//�����ڷ��ͱ���װ��FIFO��
void CoCAN_Tx_Fill_FIFO(uint8_t cycleMsgID)
{
  //���Ķ�����е���ţ�CoCANTxMsgTable��
  uint8_t Index = CoCANCycleMsg.TxIndex[cycleMsgID];

  //�ⷢ������������
  if ( *(CoCANTxMsgTable[Index].pStatus) & CAN_TX_EN )
  {
    //��������Ϣ����FIFO��
    CoCANTxMsgFIFO.Index[CoCANTxMsgFIFO.Iptr] = Index;
    
    //FIFO����
    if (CoCANTxMsgFIFO.Depth < CAN_TX_MSG_NUM)
      CoCANTxMsgFIFO.Depth++;

	//FIFO��ǰ��дλ����λ��ѭ����λ��
    CoCANTxMsgFIFO.Iptr++;
    if (CoCANTxMsgFIFO.Iptr >= CAN_TX_MSG_NUM)
      CoCANTxMsgFIFO.Iptr = 0;
    
    //���������Ա�����һ�η���ʱ��
    CoCANCycleMsg.TxTimer[cycleMsgID] = CoCANCtrl.Timer + CoCANTxMsgTable[Index].Cycle;
	//�����ѷ���TAG
    *(CoCANTxMsgTable[Index].pStatus) |= CAN_UPDATE;
  }
  //end
}

//��FIFO�з���һ������
void CoCAN_Tx_SendOutOne()
{
  //һ��ֻ����1������
  uint8_t 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;
  //end
}


/******************************************************************************
��������CoCAN_L_Data_Indication
��  �ܣ� ����·�㴫�ݶ���,����ָʾ���ݵĵ��ﲢ��������
        �ú������뱻�²�(��·��)��������
��  ���� Identifier ��CAN����ID
        DLC        ���������ݳ���
        Data       ��������������
����ֵ����
******************************************************************************/
void CoCAN_L_Data_Indication(uint32_t Identifier, uint8_t DLC, uint8_t *Data)
{
  uint8_t i;
  
  //����Ƿ��������ձ���
  if (CoCANCtrl.RxEnable != CoCAN_ENABLE)
  {
  if (Identifier==0x18FFA021)
  {}
  else
    return;
  }
  //���FIFO�Ƿ�����
  if (CoCANRxMsgFIFO.Depth >= CoCAN_RX_MSG_FIFO_MAX_DEPTH)
    return;
  
  //��������
  CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].Identifier = Identifier;//ID
  for (i = 0; i < DLC; i++)
    CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].Data[i]  = Data[i];	//Data
  CoCANRxMsgFIFO.Msg[CoCANRxMsgFIFO.Iptr].DLC        = DLC;		//DLC
  
  //FIFO����
  CoCANRxMsgFIFO.Depth++;
  CoCANRxMsgFIFO.Iptr++;
  if (CoCANRxMsgFIFO.Iptr >= CoCAN_RX_MSG_FIFO_MAX_DEPTH)
    CoCANRxMsgFIFO.Iptr = 0;
  
  //end
}

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

  //����CAN_Communication_Matrix.h����Ϣ������Ϣ
  for (Index = 0; Index < CoCAN_TOTAL_MSG_NUM; Index++)
  {
    Identifier = CANMsgAttrTable[Index].ID;
    
    //���ձ��Ŀ��ٲ��ұ� (CoCANRxMsgTable)
    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++;
    }
        
    //���ͱ��Ŀ��ٲ��ұ�(CoCANTxMsgTable)
    else
    {
      if(TxMsgNum == 0)           //���ٲ��ұ���һ������⴦��
      {
        CoCANTxMsgTable[0].Identifier = Identifier;
        CoCANTxMsgTable[0].Index      = Index;
      }
      else                        //���ݱ���ID�Ӵ�С���в��ұ�
      {
        i = TxMsgNum;
		//���ͱ��İ�ID���򣨴�С��������
        while (i)
        {
          //���һ��ID�����²����ID
          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;
  }

  //CanӲ����ʼ��
  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  = 0x01;
  }
  
  //���ö�ʱ��
  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(CoCANCtrl.Mode == Mode)
  	return;

  //��״̬��¼
  CoCANCtrl.Mode = Mode;

  //CoCAN_MODE_INIT
  if (Mode == CoCAN_MODE_INIT)
    CoCANCtrl.Prescaler = 0;

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

/******************************************************************************
��������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++)      //0λΪ����������ģ�����Ҫ������  20190929   
        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)
    {
      //���÷��ͱ��Ķ�ʱ��
      for (i = 0; i < CoCANCycleMsg.TxNum; i++)    //0λΪ����������ģ�����ʱ�򲻿��������
        CoCANCycleMsg.TxTimer[i] = CoCANTxMsgTable[CoCANCycleMsg.TxIndex[i]].Offset + CoCANCtrl.Timer + 20;
    }
	CoCANCtrl.TxEnable = CoCAN_ENABLE;
  }

  //�رշ���
  else
  {
    //ԭ�����ǹر�
    if (CoCANCtrl.TxEnable != CoCAN_DISABLE)
    {
	  //��շ��ͱ���FIFO
	  
      CoCANTxMsgFIFO.Iptr  = 0;
      CoCANTxMsgFIFO.Optr  = 0;
      CoCANTxMsgFIFO.Depth = 0;
      //�����������
      for (i = 0; i < CAN_TX_MSG_NUM; i++)    //0λΪ����������ģ��ص�ʱ�򲻹��������     ,����������IJ���0λ
      {
        //if(CoCANTxMsgTable[i].Identifier==0x18FEF717)          //20200301���Է�����4�����DZ���������ȴ�����״̬��Ӧ�ޱ��ķ���
        //{}
       // else
        CoCANTxMsgTable[i].TxReq = CoCAN_TX_IDLE;
      }
    }
	CoCANCtrl.TxEnable = CoCAN_DISABLE;
  }
  //end
}

/******************************************************************************
��������CoCAN_Search_Tx_Msg
��  �ܣ� �ӷ��ͱ��Ŀ��ٲ��ұ����ҵ�Ŀ�걨��ID����Ϣ�洢λ��
��  ���� Identifier��Ŀ�걨��ID
����ֵ���ñ��ĵ���Ϣ�ڷ��ͱ��Ŀ��ٲ��ұ��еĴ洢λ��
        0xFF��ʾδ���ҵ�����
******************************************************************************/
//#pragma INLINE
uint8_t CoCAN_Search_Tx_Msg(uint32_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(uint32_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, j;
  uint8_t   Index;
  uint32_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;

	//end
  }
  
  //����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];
         if(*CoCANRxMsgTable[Index].pStatus & CAN_UPDATE) 
        {
            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)      //20200702
      {
        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;
          //}
        }
      }
    }
  }
 /* else      20200306
   {
      //������ķ���ʱ�䵽,��Ҫ���͵ı���װ�뷢��FIFO
         for (i = 0; i < CoCANCycleMsg.TxNum; i++)
         {
             if(CoCANTxMsgTable[i].Identifier==0x18FEF717)
             {
              if (CoCANCycleMsg.TxTimer[i] <= CoCANCtrl.Timer)         //if(CoCANTxMsgTable[i].Identifier==0x18FEF717)
              {
                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++;
  //�����ʱ�����λ������ֵΪ 0 - 23767,���λ��Ϊ��λλ
  if (CoCANCtrl.Timer > 0x7FFF)                  
  {
    //�ܼ�ʱ��
    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(uint32_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(uint32_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))
    return;
  
  //���г�ʼ������
  CoCANCtrl.Prescaler = 0;

  //���������Է���
  if (CoCANCtrl.TxEnable == CoCAN_ENABLE)
  {
    //���ڷ��ͱ��ķ���
    for (i = 0; i < CoCANCycleMsg.TxNum; i++)
    {
      //������ķ���ʱ�䵽,��Ҫ���͵ı���װ�뷢��FIFO
      if (CoCANCycleMsg.TxTimer[i] == CoCANCtrl.Timer) 
        CoCAN_Tx_Fill_FIFO(i);
    }
  }
    
  //�����ķ���FIFO�еı��ķ��ͳ�ȥ
  if (CoCANTxMsgFIFO.Depth)
    CoCAN_Tx_SendOutOne();
  
  //********************************ȫ�ֶ�ʱ����
  CoCANCtrl.Timer++;
  //��ʱ�����������λ������ֵΪ 0 - 23767��
  if (CoCANCtrl.Timer > 0x7FFF)                  
  {
    CoCANCtrl.Timer &= 0x7FFF;
    for (i = 0; i < CoCANCycleMsg.TxNum; i++)
      CoCANCycleMsg.TxTimer[i] &= 0x7FFF;
  }
  //end
}