/*
  ******************************************************************************
  * @file    APP.c
  * @version V1.0.0
  * @date    2021
  * @brief   CAN demo source code.
  ******************************************************************************
*/
#include "app.h"

CAN_InitTypeDef        CAN_InitStructure;

CanTxRxMsg CAN_RxMessage;

extern volatile uint8_t gu8_CAN_ReceiveFlag;

/*********************************************************************************
* Function    : CAN_GPIO_Config
* Description : Config CAN1 GPIO.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_GPIO_Config(void)
{
    /* Enable GPIO clock */
    System_Module_Enable(EN_GPIOAB);
    GPIO_InitTypeDef GPIO_InitStructure;   	
    /* Initialization GPIO */
    /* PB8:Rx */  /* PB9:Tx */
    GPIO_InitStructure.Pin = GPIO_PIN_8|GPIO_PIN_9;	
    GPIO_InitStructure.Alternate=GPIO_FUNCTION_7;
    GPIO_InitStructure.Pull=GPIO_PULLUP;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Drive = GPIO_DRIVE_LEVEL3;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    
}

/*********************************************************************************
* Function    : CAN_NVIC_Config
* Description : Config CAN IT.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_NVIC_Config(void)
{
    /*CAN通信中断使能*/
    CAN_ITConfig(CANx, CAN_IER_RIE, ENABLE);

    NVIC_ClearPendingIRQ(CAN_IRQn);
    NVIC_SetPriority(CAN_IRQn, 5);
    NVIC_EnableIRQ(CAN_IRQn); 
}
/*********************************************************************************
* Function    : CAN_Mode_Config
* Description : Config CAN Mode.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_Mode_Config(void)
{  
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;     //CAN_Mode_Normal
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;            //CAN_SJW_1tq
    CAN_InitStructure.CAN_BRP=8;                       // //pclk = hclk/2=180M/2=90M   BRP=2*(8+1)=18  TQ=18*(1/90M)=1/5M
    CAN_InitStructure.CAN_TSEG1=CAN_TSEG1_4tq;
    CAN_InitStructure.CAN_TSEG2=CAN_TSEG2_5tq;         //width=1+4+5=10 TQ    baud=1M/(1/5*10)=1M/2=500K   
    CAN_InitStructure.CAN_ABOM=CAN_ABOM_ENABLE;       //ENABLE Bus off recover 
    CAN_Init(CANx,&CAN_InitStructure);	
}

/*********************************************************************************
* Function    : CAN_Filter_Config
* Description : Set CAN Filter to Receive data.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_Filter_Config()
{
    CAN_FilterInitTypeDef  CAN_FilterInitStruct;
	
    CAN_FilterInitStruct.CAN_FilterMode=CAN_FilterMode_Dual;
    CAN_FilterInitStruct.CAN_FilterId1=0x18fe0000;  //Extended Id:ID28...ID0
    CAN_FilterInitStruct.CAN_FilterId2=0x100<<18;   //Standard Id:ID28...ID18,so need (ID<<18)
    /* if want receive all data,please set the CAN_FilterMaskId = 0xFFFFFFFF*/
    CAN_FilterInitStruct.CAN_FilterMaskId1=0x0000FFFF; //only receive CAN id=0x18fexxxx(only care 0x18fexxxx)
    CAN_FilterInitStruct.CAN_FilterMaskId2=0x100<<18; //only receive CAN id=0x100     ( care ID28...ID18)
    CAN_FilterInit(CANx, &CAN_FilterInitStruct);
}

/*********************************************************************************
* Function    : CAN_PrintfReceive
* Description : use uart to printf can receive data.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void CAN_PrintfReceive()
{
    printfS("Receive CAN data!\n");
    if(CAN_RxMessage.IDE==CAN_Id_Standard)	
    {
        printfS("CAN IDE type: Standard\n"); 
        printfS("CAN ID=0x%.8x\n",CAN_RxMessage.StdId);
    }
    else
    {
        printfS("CAN IDE type: Extended\n"); 
        printfS("CAN ID=0x%.8x\n",CAN_RxMessage.ExtId);
    }
    if(CAN_RxMessage.RTR==CAN_RTR_Data)	
    {
        printfS("CAN RTR type: Data frame\n"); 
        printfS("data length=%d\n",CAN_RxMessage.DLC);
        for(int i=0;i<CAN_RxMessage.DLC;i++)
        {
            printfS("%.2x ",CAN_RxMessage.Data[i]);
        }
        printfS("\n");
    }
    else
    {
        printfS("CAN RTR type: Remote frame\n"); 
    }
}


/*********************************************************************************
* Function    : CAN_Config
* Description : Config CAN.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void CAN_Config(void)
{
    CAN_GPIO_Config();
    CAN_Mode_Config();
    CAN_Filter_Config();
    CAN_NVIC_Config();
}

/*********************************************************************************
* Function    : APP_Can_Test
* Description : 
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void APP_CAN_Test(enum_TEST_MODE_t fe_Mode)
{
    uint8_t i;
    CanTxRxMsg CAN_TxMessage;
    
    CAN_Config();
    
    CAN_TxMessage.ExtId = 0x18FE0000;
    CAN_TxMessage.RTR = CAN_RTR_Data;
    CAN_TxMessage.IDE = CAN_Id_Extended;
    for(i = 0; i < 8; i++)
            CAN_TxMessage.Data[i] = 0x11+i*2;
    CAN_TxMessage.DLC = 8;
    
    if(CAN_Transmit_SingleShot(CANx, &CAN_TxMessage) == CAN_Status_Success)
        printfS("Transmit CAN data success\r\n");
    else
        printfS("Transmission aborted\r\n");

    switch (fe_Mode)
    {
        /* 循环模式 */
        case TEST_LOOP: 
        {   
            while(1)
            {
                CAN_Receive(CANx,&CAN_RxMessage);
                /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                CAN_PrintfReceive();
                CAN_TxMessage=CAN_RxMessage;
                CAN_Transmit(CANx,&CAN_TxMessage);
                
            } 
        }        
        /* 中断模式 */
        case TEST_IT: 
        {
            while(1)
            {
                if(gu8_CAN_ReceiveFlag==1)
                {
                    /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                    CAN_PrintfReceive();
                    CAN_TxMessage=CAN_RxMessage;
                    CAN_Transmit(CANx,&CAN_TxMessage);//send can frame from receive 
                    gu8_CAN_ReceiveFlag=0;
                }
            }
        }

        default: break; 
    }
}

void APP_CAN_SeltTest(void)
{
    uint8_t i;
    CanTxRxMsg CAN_TxMessage;
    
    CAN_GPIO_Config();
    
    CAN_InitStructure.CAN_Mode = CAN_Mode_SlefTest;  
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;           
    CAN_InitStructure.CAN_BRP=8;                     
    CAN_InitStructure.CAN_TSEG1=CAN_TSEG1_4tq;
    CAN_InitStructure.CAN_TSEG2=CAN_TSEG2_5tq;       
    CAN_InitStructure.CAN_ABOM=CAN_ABOM_ENABLE;      
    CAN_Init(CANx, &CAN_InitStructure);	
        
    CAN_Filter_Config();
    
    CAN_TxMessage.ExtId = 0x18FE0000;
    CAN_TxMessage.RTR = CAN_RTR_Data;
    CAN_TxMessage.IDE = CAN_Id_Extended;
    for(i = 0; i < 8; i++)
            CAN_TxMessage.Data[i] = 0x11+i*2;
    CAN_TxMessage.DLC = 8;    
    
    printfS("\r\n====CAN Demo self receive ====\r\n\r\n");
    
    if(CAN_Transmit_SingleShot(CANx, &CAN_TxMessage) == CAN_Status_Success)
        printfS("Transmit CAN data success\r\n");
    else
        printfS("Transmission aborted\r\n");
    
    
    while(1)
    {
        CAN_Receive(CANx,&CAN_RxMessage);
        /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
        CAN_PrintfReceive();
        CAN_TxMessage=CAN_RxMessage;
        System_Delay_MS(1000);
        CAN_Transmit(CANx,&CAN_TxMessage);
        
    } 
}
