/******************************************************************************
文 件 名：MSCAN0.h
功能描述：MSCAN0总线收发控制函数库文件
作    者：张暄
版    本：V1.0
日    期：2016.5.5
******************************************************************************/

#include <hidef.h>           /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include "mc9s12xhy256.h"
#include "stdint.h" 
#include "comdef.h"
#include "Unit_Conv.h"


//#include "AutoGUI.h"
#include "main.h" 

/* Driver */
#include "CRG.h"
#include "ADC.h"
#include "GPIO.h"
#include "MSCAN0.h"
#include "PWM.h"
#include "SCI0_UART.h"

#include "Sound_List.h"

/* System */ 
#include "PowerManagement.h"
#include "API.h" 
#include "Line_In.h"
#include "Key.h"
#include "CRG.h"

/* Protocol */
#include "CAN_Communication_Matrix.h"
#include "Analog_Signal_Conversion.h"
#include "Communication_Over_CAN.h"
#include "Simulated_IIC_Master.h"
#include "Simulated_SPI_Master.h"
#include "YGV642_SPI.h"

/* Device */
#include "EEPROM_24Cxx.h"
#include "EEPROM_24Cxx_Remap.h"
#include "ISD2360.h"
#include "LED.h"
#include "GUI.h"
#include "YGV642.h"

/* Module */
#include "Flash_synchronizer.h"

#include "Non_volatile_Memorys.h"
#include "Sound_Player.h"
#include "System_Status_Monitor.h"
#include "TFT_LCD.h"

/* Implementation */
#include "Popup_List.h"
#include "IO_Manager.h"
#include "Popup_Scheduler.h"
#include "Sound_Scheduler.h"
#include "Warning_Processor.h"
#include "Data_Processor.h"
#include "IPC.h"

/* Application */

#include "Telltales.h"
//#include "Back_Light.h"
#include "Drive_Info.h"
#include "Gauges.h"
#include "Menus.h"
#include "Popups.h"

#include "Startup_Animation.h"

#include "FuelConfig.h" 
//#include "FuelConfig1.h" 
 
 
/*Diagnostic*/
#include "Diag_ID_Def.h"
#include "DoCAN_ISO15765_Config.h"
#include "DoCAN_ISO15765.h"
#include "UDS_ISO14229_Services.h"
#include "Diag_ID_Def.h"
#include "UDS_ISO14229_Server.h"
#include "UDS_ISO14229_Server_Config.h"

#include "API_BD8379.h"

extern uint8_t CanFrameExist;
extern INT8U BUS_OFF_FLAG;
extern uint8_t DiagnosticReceived;
uint32_t                      MSCAN0TxID[3];
MSCAN0BusoffMonitorStruct     MSCAN0Busoff;

extern   void SetErrState(unsigned char n); 
extern void SetRxState(unsigned char n); 
extern void SetTxState(unsigned char n);

extern void CoCAN_L_Data_Indication ( uint32_t Identifier, uint8_t DLC, uint8_t *Data );
extern void CAN1939_L_Data_Indication ( uint32_t Identifier, uint8_t DLC, uint8_t *Data );
//extern void CoCAN_L_Data_Confirm(uint32_t Identifier, uint8_t TransferStatus);

extern void DoCAN_L_Data_Indication ( uint32_t Identifier, uint8_t dlc, uint8_t *pData );
extern void DoCAN_L_Data_Confirm ( uint32_t Identifier, uint8_t TransferStatus );
extern   void NM_Receive_isr_Fun(unsigned int id, unsigned char *pBuf) ;

extern void MSCAN0_L_Data_Request ( uint32_t Identifier, uint8_t DLC, uint8_t *Data, uint8_t Priority ) ;
extern uint8_t  CANNetRxOFF ;
extern uint8_t  CANNetTxOFF ;

extern uint8_t   Time10ms;
extern uint8_t   Time2ms;

typedef struct 
{
  uint32_t Identifier;
  uint8_t  DLC;
  uint8_t  Data[8];
  uint8_t  Priority;  
}MSCAN0TxID_t;

typedef struct 
{
  MSCAN0TxID_t TxBuf[32];
  uint8_t      TxHead;
  uint8_t      TxTail;  
}MSCAN0TxBuf_t;

//static MSCAN0TxID_t  BackUpTxBuf[5];
static MSCAN0TxBuf_t                 MSCAN0TxBuf;

/******************************************************************************
函数名：MSCAN0_L_Data_Request
功  能：该函数由上层调用,用于请求向总线上发送一组报文
参  数：Identifier：报文ID
        DLC       ：报文长度
        Data      ：报文数据
        Priority  ：发送优先级 0 - 2 数字越小优先级越高
返回值：无
******************************************************************************/
void MSCAN0_L_Data_Service(void)
{                                     
  uint8_t  BufSel;
  uint16_t cnt = 0;
  uint8_t Priority = 0;
  static uint32_t temp = 0;
  
  if ((MSCAN0TxBuf.TxHead != MSCAN0TxBuf.TxTail) && (TpTimingCtrl.Cnt - temp >= 20)) 
  {    
    BufSel   = 0x01;
    BufSel <<= MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Priority;

    //当前优先级的发送缓冲区为空时,上报发送失败并退出发送
    if ((CAN0TFLG & 0x07) == 0)
    {
      temp = TpTimingCtrl.Cnt;
      return;
    }
    
    DisableInterrupts;
    
   // CAN0TBSEL = BufSel;   		                //选择指向指定的发送缓冲区
    if((CAN0TFLG & 0x01) == 0x01) 
    {
      Priority = 0;
      CAN0TBSEL = 1;
    }//选择指向指定的发送缓冲区
    else if((CAN0TFLG & 0x02) == 0x02) 
    {
      Priority = 1;
      CAN0TBSEL = 2;  
    } 
    else if((CAN0TFLG & 0x04) == 0x04) 
    {
      Priority = 2; 
      CAN0TBSEL = 4;
    }
    
    BufSel = CAN0TBSEL;
    
   // CAN0TXIDR0 = (uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier >> 3);  //写入标识符ID
  //  CAN0TXIDR1 = (uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier << 5);
    
       //写入标识符ID
    CAN0TXIDR0 =  (uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier >> 21);
    CAN0TXIDR1 =  ((uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier >> 13) & 0xE0) | ((uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier >> 15) & 0x07);
    CAN0TXIDR2 =  (uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier >> 7);
    CAN0TXIDR3 =  (uint8_t)(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier << 1) & 0xFE;
    
    CAN0TXIDR1_SRR = 1;
    CAN0TXIDR1_IDE = 1;
    
    CAN0TXDLR = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].DLC;
    
    CAN0TXDSR0 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[0]; //
    CAN0TXDSR1 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[1];  //
    CAN0TXDSR2 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[2];  //
    CAN0TXDSR3 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[3];  //
    CAN0TXDSR4 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[4];
    CAN0TXDSR5 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[5];
    CAN0TXDSR6 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[6];
    CAN0TXDSR7 = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[7];
    
/*                                                      
      BackUpTxBuf[BufSel].Identifier=MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier; 
      BackUpTxBuf[BufSel].DLC = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].DLC;
      BackUpTxBuf[BufSel].Priority =  MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Priority;
      BackUpTxBuf[BufSel].Data[0] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[0];
      BackUpTxBuf[BufSel].Data[1] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[1];
      BackUpTxBuf[BufSel].Data[2] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[2];
      BackUpTxBuf[BufSel].Data[3] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[3];
      BackUpTxBuf[BufSel].Data[4] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[4];
      BackUpTxBuf[BufSel].Data[5] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[5];
      BackUpTxBuf[BufSel].Data[6] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[6];
      BackUpTxBuf[BufSel].Data[7] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Data[7];
                                                                                     */
    
    EnableInterrupts;
               
//   if(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier==0x729)
//    CAN0TXTBPR = 1;//MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Priority;                    //设置优先级,各Buffer优先级相同,则BufferID越小,优先级越高
//    else

    CAN0TXTBPR = BufSel;//MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Priority;                    //设置优先级,各Buffer优先级相同,则BufferID越小,优先级越高
    CAN0TFLG  = BufSel;                       //启动发送
    CAN0TIER |= BufSel;                       //启动相应CAN发送中断
    
    MSCAN0TxID[Priority] = MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier;    
    
   // MSCAN0_L_Data_Confirm(MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxHead].Identifier, COMPLETE);
      MSCAN0TxBuf.TxHead++;            
      if(MSCAN0TxBuf.TxHead >= 32)
        MSCAN0TxBuf.TxHead = 0; 
          
    /*cnt = 0;
    while((CAN0TFLG & BufSel) != BufSel) 
    {
      cnt++;
      if(cnt >= 1800)  
        break;
    }*/
  }
}

void MSCAN0_L_Data_Request(uint32_t Identifier, uint8_t DLC, uint8_t *Data, uint8_t Priority)
{
  uint8_t i = 0;
  uint8_t tmp = MSCAN0TxBuf.TxHead;
  uint8_t cnt = 0;
  
  DisableInterrupts;
  
  cnt = (tmp > MSCAN0TxBuf.TxTail) ? (MSCAN0TxBuf.TxHead - MSCAN0TxBuf.TxTail - 1) : (32 - MSCAN0TxBuf.TxTail + MSCAN0TxBuf.TxHead - 1); 
  
  if ((DLC > 8) || (Priority > 2)) 
  { 
    EnableInterrupts;
    return;  
  }
  if(Identifier==0x18FEF717 ) 
    {
      if(1 == CANNetTxOFF)
      {
         EnableInterrupts;
         return;
       }
    }
  /*if(Identifier != 0x729 ) 
  {
    if(Identifier == 0x402) 
    {
      ;
    } 
    else 
    {
      if(DIAG_TST_BIT_SET(m_28SerComCtrlState ,DIAG_COM_NOR_TX,uint8_t)) 
      {          
        EnableInterrupts;
        return;  
      }
    }
  }
  */  
  MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxTail].Identifier = Identifier;
  MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxTail].DLC = DLC;
  
  for(i = 0; i < 8; i++) 
    MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxTail].Data[i] = 0;
        
  for(i = 0; i < DLC; i++) 
    MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxTail].Data[i] = Data[i];
  
    
  MSCAN0TxBuf.TxBuf[MSCAN0TxBuf.TxTail].Priority = Priority;
      
  MSCAN0TxBuf.TxTail++;
  if(MSCAN0TxBuf.TxTail >= 32)
    MSCAN0TxBuf.TxTail = 0;
 
  EnableInterrupts;
  
  return;
}
#if 0
void MSCAN0_L_Data_Request ( uint32_t Identifier, uint8_t DLC, uint8_t *Data, uint8_t Priority )
{
    uint8_t  i;
    //uint8_t  BufDetect;
    uint8_t  BufSel;
    

    /*if((Identifier >= 0x400) && (Identifier <= 0x4ff) ) 
    {
      if(1 == CANNetTxOFF)
         return;
      
    }*/
    if(Identifier==0x18FEF717 ) 
    {
      if(1 == CANNetTxOFF)
         return;
      
    }
    //MSCAN与CAN BUS不同步,或ID无效,或发送数据长度大于8,或优先级设置错误时,上报发送失败并退出发送
    if ( ( CAN0CTL0_SYNCH == 0 ) || ( DLC > 8 ) || ( Priority > 2 ) ) //|| (Identifier > 0x07FF)
    {
        MSCAN0_L_Data_Confirm ( Identifier, NOT_COMPLETE );
        return;
    }



    BufSel   = 0x01;
    BufSel <<= Priority;

    //当前优先级的发送缓冲区为空时,上报发送失败并退出发送
    if ( CAN0TFLG & BufSel == 0 )
    {
        MSCAN0_L_Data_Confirm ( Identifier, NOT_COMPLETE );
        return;
    }

    if ( MSCAN0TxID[Priority] != 0xFFFF )     //前一次报文发送未得到结果但是Buffer被意外清空
        MSCAN0_L_Data_Confirm ( MSCAN0TxID[Priority], NOT_COMPLETE );

    MSCAN0TxID[Priority] = Identifier;        //保存ID
    CAN0TBSEL = BufSel;   		                //选择指向指定的发送缓冲区
   /* CAN0TXIDR0 = ( uint8_t ) ( Identifier >> 3 ); //写入标识符ID
    CAN0TXIDR1 = ( uint8_t ) ( Identifier << 5 );
    CAN0TXIDR1_SRR = 0;
    CAN0TXIDR1_IDE = 0;*/

    //写入标识符ID
    CAN0TXIDR0 =  (uint8_t)(Identifier >> 21);
    CAN0TXIDR1 =  ((uint8_t)(Identifier >> 13) & 0xE0) | ((uint8_t)(Identifier >> 15) & 0x07);
    CAN0TXIDR2 =  (uint8_t)(Identifier >> 7);
    CAN0TXIDR3 =  (uint8_t)(Identifier << 1) & 0xFE;

    //发送（扩展帧）
    CAN0TXIDR1_SRR = 1;
    CAN0TXIDR1_IDE = 1;
  
    for ( i = 0; i < DLC; i++ )               //写入数据
        * ( ( &CAN0TXDSR0 ) + i ) = Data[i];

    CAN0TXDLR = DLC;
    //CAN0TXTBPR = 0;                         //设置优先级,各Buffer优先级相同,则BufferID越小,优先级越高
    CAN0TFLG  = BufSel;                       //启动发送
    CAN0TIER |= BufSel;                       //启动相应CAN发送中断
}
#endif 
/******************************************************************************
函数名：MSCAN0_L_Data_Indication
功  能：该函数用于向上层指示一帧报文的到来,并同时将报文数据传递至上层
        注意：1.使用时应将上层的报文传递函数包含于本函数之中,报文到来时则会调用
                相应的函数传递报文数据
              2.本函数与中断相关,被调用的上层的报文传递函数应尽可能简短
参  数：Identifier：报文ID
        DLC       ：报文长度
        Data      ：报文数据
返回值：无
******************************************************************************/
void MSCAN0_L_Data_Indication ( uint32_t Identifier, uint8_t DLC, uint8_t *Data )
{
   /*PduInfoType NW_MessageBuffer; 
   
   if( ( Identifier >= 0x18FFFA00 ) && ( Identifier <= 0x18FFFAFF ) ) {//网络管理报文
        NW_MessageBuffer.SduDataPtr = Data;
        NW_MessageBuffer.SduLength = DLC;
        CanNm_RxIndication(0, 0,&NW_MessageBuffer);   
        NM_RECEIVE=1; 
        sleepFlg=1;   
    
   } */
     
   //过滤1939-21 故障码的多包报文
    if( ( Identifier == DIAG_ID_Rx_PHY ) || ( Identifier == DIAG_ID_Rx_FUN ) )
   { 
        DoCAN_L_Data_Indication ( Identifier, DLC, Data );
   }
   else
   {
        //应用报文
        CoCAN_L_Data_Indication ( Identifier, DLC, Data );
   }

    //if ((Identifier == 0x7E3) || (Identifier == 0x7EB))
    //  DoCAN_L_Data_Indication(Identifier, DLC, Data);
    //else
    //  CoCAN_L_Data_Indication(Identifier, DLC, Data);
}

 /******************************************************************************
函数名：MSCAN0_L_Data_Confirm
功  能：该函数用于向上层指示请求发送的报文的发送结果
        注意：1.使用时应将上层的报文发送结果传递函数包含于本函数之中,报文发送事
                件产生时则会调用相应的函数传递报文发送结果
              2.本函数与中断相关,被调用的上层的报文发送结果传递函数应尽可能简短
参  数：Identifier    ：报文ID
        TransferStatus：报文发送结果：COMPLETE     发送完成
                                      NOT_COMPLETE 报文未能发送完成
返回值：无
******************************************************************************/
void MSCAN0_L_Data_Confirm ( uint32_t Identifier, uint8_t TransferStatus )
{
    if (Identifier == DIAG_ID_Tx)
    {
        DoCAN_L_Data_Confirm ( Identifier, TransferStatus );
    }
}

/******************************************************************************
函数名：MSCAN0_Bus_Off_Monitoring_Service
功  能：MSCAN0 Bus-off状态监控服务,监控Bus-off状态并尝试恢复
参  数：无
返回值：无
*******************************************************************************
注  意：该服务函数必须每20ms被调用一次
******************************************************************************/
void MSCAN0_Bus_Off_Monitoring_Service ( void )
{
#if !MSCAN0_BUS_OFF_AUTO_RECOVERY
#if MSCAN0_BUS_LIMP_MODE_ENABLE

    if ( MSCAN0Busoff.Status == MSCAN0_BUS_LIMP )
        return;	                                  //CAN总线已经在跛行模式(多次恢复失败),则不再恢复

#endif

    if ( CAN0MISC_BOHOLD )                        //如果Bus-off发生
    {
        MSCAN0Busoff.Timer++;

        if ( MSCAN0Busoff.Status == MSCAN0_BUS_STABLE )
            MSCAN0Busoff.Status = MSCAN0_BUS_OFF_LV1;

        if ( MSCAN0Busoff.Status == MSCAN0_BUS_OFF_LV1 )
        {
            if ( MSCAN0Busoff.Timer >= MSCAN0_BUS_OFF_LV1_RECOVERY_TIME / 20 )
            {
                MSCAN0Busoff.Timer = 0;
                CAN0MISC_BOHOLD = 1;                      //写1清零,请求恢复Bus-off
                MSCAN0Busoff.Cnt++;

                if ( MSCAN0Busoff.Cnt >= 10 )
                {
                    BUS_OFF_FLAG = 1;
                    MSCAN0Busoff.Cnt = 0;
                    MSCAN0Busoff.Status = MSCAN0_BUS_OFF_LV2;
                }
            }
        }
        else if ( MSCAN0Busoff.Status == MSCAN0_BUS_OFF_LV2 )
        {
            if ( MSCAN0Busoff.Timer >= MSCAN0_BUS_OFF_LV2_RECOVERY_TIME / 20 )
            {
                MSCAN0Busoff.Timer = 0;
                CAN0MISC_BOHOLD = 1;                      //写1清零,请求恢复Bus-off
            }

#if MSCAN0_BUS_LIMP_MODE_ENABLE
            MSCAN0Busoff.Cnt++;

            if ( MSCAN0Busoff.Cnt > MSCAN0_BUS_LIMP_MODE_THRESHOLD )
            {
                MSCAN0Busoff.Cnt = 0;
                MSCAN0Busoff.Status = MSCAN0_BUS_LIMP;  //进入CAN总线跛行模式
                CAN0_PHY_STB = 1;                       //进入省电模式
                MSCAN0_Init();				                  //通过初始化终止所有CAN收发
                CAN0RIER_RXFIE = 0;   		              //禁止CAN接收中断
                CAN0RIER_WUPIE = 0;                     //关闭唤醒中断
                CAN0CTL0_WUPE  = 0;                     //禁止唤醒使能

                if ( CAN0RFLG_WUPIF )
                    CAN0RFLG_WUPIF = 1;                   //如果有唤醒中断请求标志也一并清除(写1清零)
            }

#endif
        }
    }
    else                                          //总线正常,没有Bus-off发生
    {
        BUS_OFF_FLAG = 0;
        MSCAN0Busoff.Status = MSCAN0_BUS_STABLE;
        MSCAN0Busoff.Timer = 0;
        MSCAN0Busoff.Cnt   = 0;
    }

#endif
}

/******************************************************************************
函数名：MSCAN0_Get_Bus_Status
功  能：获取MSCAN0总线状态
参  数：无
返回值：MSCAN0_BUS_STABLE：总线正常,稳定工作
        MSCAN0_BUS_OFF   ：总线处于Bus-off状态
        MSCAN0_BUS_LIMP  ：总线处于跛行状态(Bus-off后多次恢复均失败而关闭总线)
******************************************************************************/
uint8_t MSCAN0_Get_Bus_Status ( void )
{
    return MSCAN0Busoff.Status;
}

/******************************************************************************
函数名：MSCAN0_Init
功  能：MSCAN0初始化程序
参  数：无
返回值：无
******************************************************************************/
void MSCAN0_Init ( void )
{
   // uint8_t i;
    CAN0CTL0 = 0x01;            //请求 MSCAN进入初始化模式

    while ( ! ( CAN0CTL1_INITAK ) ); //等待进入初始化模式

    CAN0IDAC = 0;   		        //配置屏蔽验收寄存器的工作方式  two 32-bit filter
    CAN0IDAR0 = 0x00;     	    //设置验收寄存器
    CAN0IDAR1 = 0x00;
    CAN0IDAR2 = 0x00;
    CAN0IDAR3 = 0x00;
    CAN0IDMR0 = 0xFF;           //设置屏蔽寄存器 (这里设置为所有报文ID都接收)
    CAN0IDMR1 = 0xFF;
    CAN0IDMR2 = 0xFF;
    CAN0IDMR3 = 0xFF;
    CAN0IDAR4 = 0x00;      	    //设置验收寄存器
    CAN0IDAR5 = 0x00;
    CAN0IDAR6 = 0x00;
    CAN0IDAR7 = 0x00;
    CAN0IDMR4 = 0xFF;           //设置屏蔽寄存器 (这里设置为所有报文ID都接收)
    CAN0IDMR5 = 0xFF;
    CAN0IDMR6 = 0xFF;
    CAN0IDMR7 = 0xFF;
    CAN0CTL1_CANE   = 1;        //使能MSCAN模块
    CAN0CTL1_CLKSRC = 0;        //选择OSCCLK(8MHz)为MSCAN的时钟源
    CAN0CTL1_LISTEN = 0;        //正常运行模式(非监听模式)
#if MSCAN0_BUS_OFF_AUTO_RECOVERY
    CAN0CTL1_BORM = 0;	        //自动总线BUS_OFF恢复
#else
    CAN0CTL1_BORM = 1;	        //总线BUS_OFF由用户控制恢复
#endif
    CAN0CTL1_WUPM = 1;		      //给唤醒加滤波
    CAN0BTR0 = 0X41;            //2tq, Prescaler value=4,波特率 8M/(2 * (1+2+5)=500k
    CAN0BTR1 = 0X14;            //波特率设置 现在这个配置是1+5/1+5+2 = 75%的采样点
    /*
    myBRP=5;            p=(myBRP-1);
    mySJW=3;           sj=(mySJW-1)<<6;		//同步跳转段=2       2015-3-12
    myTSEG1=11;    t_seg1=myTSEG1-1;
    myTSEG2=4;       t_seg2=(myTSEG2-1)<<4;
    CAN0BTR0=sj|p;
    CAN0BTR1=t_seg1|t_seg2;		//设为1次采样       */
    //---------------------------------
    //CAN0CTL0 = 0x00;
    CAN0CTL0 = 0x00;            //退出初始化模式

    while ( CAN0CTL1_INITAK );  //等待退出初始化模式

    while ( !CAN0CTL0_SYNCH );  //等待MSCAN与CAN总线同步

    CAN0TIER = 0x00;            //禁止CAN发送中断
    CAN0RIER_RXFIE = 1;   		  //使能CAN接收中断
    CAN0RIER_WUPIE = 1;
    CAN0_STB = 0;   	          //使能CAN收发器
    MSCAN0Busoff.Status = MSCAN0_BUS_STABLE;
    MSCAN0Busoff.Timer = 0;
#if MSCAN0_BUS_LIMP_MODE_ENABLE
    MSCAN0Busoff.Cnt   = 0;
#endif

   // for ( i = 0; i < 3; i++ )
   //     MSCAN0TxID[i] = 0xFFFF;   //0xFFFF表示无效ID
  MSCAN0TxBuf.TxHead = 0;
  MSCAN0TxBuf.TxTail = 0;   
}

/******************************************************************************
函数名：MSCAN0_Enter_Low_Power_Mode
功  能：令MSCAN0进入低功耗模式
参  数：无
返回值：无
******************************************************************************/
 

void MSCAN0_Enter_Low_Power_Mode ( void )
{
   //MSCAN0_Init();            //透过初始化终止CAN收发
    CAN0_STB = 1;   	          //使能CAN收发器

    if ( CAN0RFLG_WUPIF )       //唤醒中断请求标志 = 1 则写1清0
        CAN0RFLG_WUPIF = 1;

    CAN0CTL0_WUPE = 1;			    //唤醒使能
    //置1后,当MSCAN所有发送完成(发送队列空),接受也完成(CAN总线空闲)后,
    //MSCAN 进入SLEEP模式,并且置 CAN0CTL1_SLPAK=1表示确认
    //在置此位前 CAN0RFLG_WUPIF 必须清除
    //当CAN0CTL0_SLPRQ=1,且CAN0CTL1_SLPAK=1 ,表示MSCAN已经进入睡眠模式
    CAN0CTL0_SLPRQ = 1;			    //请求置MSCAN进入睡眠模式
    //当MSCAN进入睡眠模式后,如果 CAN0CTL0_WUPE = 1 且收到CAN报文后,MSCAN退出睡眠,且CAN0RFLG_WUPIF置1
    //同时 CAN0CTL0_SLPRQ,CAN0CTL1_SLPAK 也将自动清0.
    //在MSCAN进入睡眠模式后,软件也可以主动置CAN0CTL0_SLPRQ = 0,使得MSCAN退出睡眠,CAN0CTL1_SLPAK 也将自动清0.
    //当 CAN0CTL0_SLPRQ = 1后,如果MSCAN还没有进入睡眠模式,那么不能主动清CAN0CTL0_SLPRQ = 0.
    CAN0TARQ = 0x07;            //请求终止所有报文发送.
    CAN0RIER_RXFIE = 0;   			//禁止CAN接收中断         20200618
}

/******************************************************************************
函数名：MSCAN0_Exit_Low_Power_Mode
功  能：令MSCAN0退出低功耗模式
参  数：无
返回值：无
******************************************************************************/
void MSCAN0_Exit_Low_Power_Mode ( void )
{
    CAN0CTL0_SLPRQ = 0;         //使得MSCAN退出睡眠

    if ( CAN0RFLG_WUPIF )       //唤醒中断请求标志 = 1 则写1清0
        CAN0RFLG_WUPIF = 1;

    CAN0CTL0_WUPE = 0;			    //禁用唤醒功能
    CAN0_STB = 0;               //使能CAN收发器
    CAN0RIER_RXFIE = 1;   			//使能CAN接收中断
}

/******************************************************************************
函数名：MSCAN0_Get_Wake_Up_Flag
功  能：获取MSCAN0的唤醒状态
参  数：无
返回值：0 - 未被唤醒 1 - 已被唤醒
******************************************************************************/
uint8_t MSCAN0_Get_Wake_Up_Flag ( void )
{
 
   
    if (( CAN0CTL0_SLPRQ == 0 )   ||(CanFrameExist==1))
        return 1;
 
    return 0;
}

#pragma CODE_SEG __NEAR_SEG NON_BANKED   	//置所有中断函数放在FLASH的非分页区

/******************************************************************************
函数名：MSCAN0_TX_ISR
功  能：MSCAN0发送中断服务函数。
        当有CAN报文发送完毕或被中止发送时，执行此函数
参  数：无
返回值：无
******************************************************************************/
void interrupt MSCAN0_TX_ISR ( void )
{
    uint8_t i;
    uint8_t TxFlag;
    uint8_t TxBuf;
    uint8_t BufDetect;
    
    do
    {
        TxFlag = CAN0TFLG;
        TxBuf = CAN0TIER & TxFlag;              //获取发送完毕或被中止发送的报文Buffer
        CAN0TIER &= ~TxBuf;                     //关闭发送完毕或被中止发送的报文Buffer对应的中断
        BufDetect = 1;

        for ( i = 0; i < 3; i++ )
        {
            if ( BufDetect & TxBuf )
            {
                if ( BufDetect & CAN0TAAK )         //报文被成功中止发送
                    MSCAN0_L_Data_Confirm ( MSCAN0TxID[i], NOT_COMPLETE );
                else                                //报文发送成功
                    MSCAN0_L_Data_Confirm ( MSCAN0TxID[i], COMPLETE );

                MSCAN0TxID[i] = 0xFFFF;             //清除报文记录
            }

            BufDetect <<= 1;
        }
    }
    while ( TxFlag != CAN0TFLG );             //避免中断处理期间有新的报文发送完毕
}




/******************************************************************************
函数名：MSCAN0_RX_ISR
功  能：MSCAN0接收中断服务函数。
        当有CAN报文送达时，接收CAN报文
参  数：无
返回值：无
******************************************************************************/
void interrupt MSCAN0_RX_ISR ( void )
{
    uint32_t tmp;
    uint32_t CANMsgID;

   // uint8_t m8;
    CAN0RIER_RXFIE = 0;                      //先禁止MSCAN接收中断


    /*  if ( CAN0RXIDR1_IDE || CAN0RXIDR1_SRR )  //如果收到的数据为扩展帧,或为远程帧
    {
        CAN0RFLG_RXF = 1;                      //清接收中断标志
        CAN0RIER_RXFIE = 1;                    //重新启动MSCAN接收中断
        
        return;
    } */

    //数据接收
    tmp = (uint32_t)(CAN0RXIDR0) << 21;
    tmp &= 0x1FE00000; 
    CANMsgID =  tmp | ((uint32_t)(CAN0RXIDR1 & 0xE0) <<13) |  ((uint32_t)(CAN0RXIDR1 & 0x07) <<15)
                  | ((uint32_t)(CAN0RXIDR2) << 7)
                  | ((uint32_t)(CAN0RXIDR3) >> 1);//ID
    		  
    /* CANMsgID = ( ( uint16_t ) ( CAN0RXIDR0 << 3 ) ) | ( ( uint16_t ) ( CAN0RXIDR1 >> 5 ) );
    if((CANMsgID >= 0x400) && (CANMsgID <= 0x4ff) ) 
    {
      if( 1==CANNetRxOFF )
    	         return;
    	NM_Receive_isr_Fun(CANMsgID, &CAN0RXDSR0); 
    }*/
    if(CANMsgID==0x18FFA021)
    {
      if( 1==CANNetRxOFF )
         return;
    }
    MSCAN0_L_Data_Indication ( CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0 );
    CanFrameExist=1;
    CAN0RFLG_RXF = 1;                        //清接收中断标志
    CAN0RIER_RXFIE = 1;                      //重新启动MSCAN接收中断
}
/*
void interrupt MSCAN0_RX_ISR(void)
{
  uint16_t CANMsgID;

	CAN0RIER_RXFIE = 0;                      //先禁止MSCAN接收中断

	if (CAN0RXIDR1_IDE || CAN0RXIDR1_SRR)    //如果收到的数据为扩展帧,或为远程帧
	{
    CAN0RFLG_RXF=1;                        //清接收中断标志
		CAN0RIER_RXFIE=1;                      //重新启动MSCAN接收中断

    return;
	}

	CANMsgID = ((uint16_t)(CAN0RXIDR0 << 3)) | ((uint16_t)(CAN0RXIDR1 >> 5));

  if((CANMsgID >= 0x400) && (CANMsgID <= 0x47F))
    MSCAN0_L_Data_Indication(CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0);
  else
  {
  	switch(CANMsgID)
  	{
    	case  0x068 :
    	case  0x268 :
    	case  0x2D7 :
      case  0x4D4 :
      case  0x1C8 :
      case  0x370 :
      case  0x1C9 :
      case  0x0F2 :
      case  0x0E2 :
      case  0x082 :
      case  0x094 :
      case  0x288 :
      case  0x088 :
      case  0x120 :
      case  0x293 :
      case  0x115 :
      case  0x160 :
      case  0x07A :
      case  0x30F :
      case  0x2F1 :
      case  0x10D :
      case  0x7E3 :
      case  DIAG_ID_Rx_FUN :
      case  0x279 : MSCAN0_L_Data_Indication(CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0);
                    break;
      default     : break;
  	}
	}

  CAN0RFLG_RXF = 1;                        //清接收中断标志
	CAN0RIER_RXFIE = 1;                      //重新启动MSCAN接收中断
}*/

/******************************************************************************
函数名：MSCAN0_WAKEUP_ISR
功  能：MSCAN0唤醒中断
参  数：无
返回值：无
******************************************************************************/

void interrupt MSCAN0_WAKEUP_ISR ( void )
{
    CAN0RFLG_WUPIF = 1;
    CAN0_STB = 0;
    Time2ms=0;
    Time10ms=0;
    API_Start();
    CanFrameExist=1;
}

#pragma CODE_SEG DEFAULT
