/**********************************************************************
* 文件名称： can_controller.c
* 功能描述： CAN抽象结构体框架的具体实现函数
*            主要实现调用硬件驱动的接口封装
* 文件目的： 掌握CAN底层驱动的抽象
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/

/**************头文件**************************************************/
#include "can_controller.h"
#include "string.h"

/**************宏定义**************************************************/
#define CAN_BAUD_NUM    3		//可用配置波特率个数

/**************全局变量定义*********************************************/
const unsigned int CAN1_baud_table[CAN_BAUD_NUM][5] = 
{
    //波特率， CAN_SJW，     CAN_BS1，        CAN_BS2，    CAN_Prescaler 
	{250,   CAN_SJW_1tq,    CAN_BS1_15tq,   CAN_BS2_5tq,    8},		    //250k  ok
	{500,   CAN_SJW_1tq,    CAN_BS1_15tq,   CAN_BS2_5tq,    4},			//500K	ok
	{1000,  CAN_SJW_1tq,    CAN_BS1_15tq,   CAN_BS2_5tq,    2},			//1000K	ok
};

pCanInterrupt    g_pCanInterrupt = NULL;


/**************函数声明*************************************************/
int register_can_controller(const pCAN_COMM_STRUCT p_can_controller);



/***********************************************************************
****************CAN控制器抽象接口实现代码*******************************
***********************************************************************/

/**********************************************************************
* 函数名称： void CAN_Baud_Process(unsigned int Baud,CAN_InitTypeDef *CAN_InitStructure)
* 功能描述： 计算波特率
* 输入参数： 无
* 输出参数： 无
* 返 回 值： 无
* 注    意：CAN时钟为42M
* CAN_SJW : CAN_SJW_1tq - CAN_SJW_4tq	  不能比任何一相位缓冲段长
* CAN_BS1 : CAN_BS1_1tq - CAN_BS1_16tq
* CAN_BS2 : CAN_BS2_1tq - CAN_BS2_8tq
* CAN_Prescaler : 1 - 1024
* 	配置说明：
* CAN_SJW + CAN_BS1 / (CAN_SJW + CAN_BS1 + CAN_BS2)
* 	0.75     baud > 800k
* 	0.80     baud > 500k
* 	0.875    baud <= 500k
* 	baud = 42M / (CAN_SJW + CAN_BS1 + CAN_BS2) / CAN_Prescaler
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN_Baud_Process(unsigned int Baud,CAN_InitTypeDef *CAN_InitStructure)
{
	unsigned int i = 0;
	for(i = 0;i < CAN_BAUD_NUM;i ++)
	{
		if(Baud == CAN1_baud_table[i][0])
		{
			CAN_InitStructure->CAN_SJW = CAN1_baud_table[i][1];
			CAN_InitStructure->CAN_BS1 = CAN1_baud_table[i][2];
			CAN_InitStructure->CAN_BS2 = CAN1_baud_table[i][3];
			CAN_InitStructure->CAN_Prescaler = CAN1_baud_table[i][4];
			return;	
		}
	}	
}


/**********************************************************************
* 函数名称： int CAN_Set_Controller( void )
* 功能描述： 单片机内部CAN控制器初始化，包括GPIO(TX,RX），CAN外设时钟，波特率，过滤器等
* 输入参数： 无
* 输出参数： 无
* 返 回 值： int can_port:返回对应CAN控制器的通道号，类比socketcan中的套接口
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
int CAN_Set_Controller( void )
{
    /* STM32 GPIO结构体 */
    GPIO_InitTypeDef       GPIO_InitStructure;
    /* STM32 CAN结构体 */
    CAN_InitTypeDef        CAN_InitStructure;
    /* STM32 CAN过滤器结构体 */
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    /*************************************************************/
    /*CAN相关GPIO配置，此处为：CAN_TX, CAN_RX*/
    
    /*使能GPIO时钟*/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    /*初始化管脚配置*/
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_0 ;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    /*将GPIO设置为CAN复用模式*/
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); 
    
    /*************************************************************/
    /*CAN控制器相关配置，此处为波特率，采样率等*/

    /* 使能CAN时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    /* 初始化CAN控制器工作模式*/
    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);
    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN工作模式

    /* 初始化CAN波特率 */
    CAN_Baud_Process(500,&CAN_InitStructure);
    CAN_Init(CAN1, &CAN_InitStructure);  
    

    /*************************************************************/
    /* 初始化CAN过滤器 */
    CAN_FilterInitStructure.CAN_FilterNumber = 0;	                    /* CAN1滤波器号从0到13 */
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;	    /* 滤波屏蔽模式 */
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;	    /* 不屏蔽任何ID */
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;		/* 不屏蔽任何ID */
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;	    
                                                     
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);       
 
    /*************************************************************/
    /* 设置完CAN后，返回当前设置的CAN的端口号，此处主要类比linux socketcan中的套接口 */
    
    
    return CAN_PORT_CAN1;
    /*************************************************************/
}

/**********************************************************************
* 函数名称： void CAN_Set_Interrupt(int can_port,  pCanInterrupt callback)
* 功能描述： 使能CAN中断处理，并传入应用的的回调函数，回调函数主要处理应用层的功能
* 输入参数： can_port,端口号
*            callback： 中断具体处理应用功能的回调函数
* 输出参数： 无
* 返 回 值： 无
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN_Set_Interrupt(int can_port,  pCanInterrupt callback)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    /* 根据CAN端口号配置中断 */
    switch( can_port )
    {
        case CAN_PORT_CAN1:
        {	
            /* 初始化回调接口函数 */
            if ( NULL != callback ) 
            {
                g_pCanInterrupt = callback;
            }
    
            /* 使用CAN0_RX中断，在linux socket can中类似创建接收线程 */
            NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; 
            NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
            NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
            NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
            NVIC_Init(&NVIC_InitStructure);
            CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
        }
        break;
        
        default:
            break;
        
    }
    return ;
}


/**********************************************************************
* 函数名称： void CAN_Read(int can_port, CanRxMsg* recv_msg)
* 功能描述： CAN读取接收寄存器，取出接收到的报文
* 输入参数： can_port,端口号     
* 输出参数： recv_msg：接收报文
* 返 回 值： 无
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN_Read(int can_port, CanRxMsg* recv_msg)
{ 
    switch( can_port )
    {
        case CAN_PORT_CAN1:
        {
            /* 从FIFO中读取CAN报文 */
            CAN_Receive(CAN1,CAN_FIFO0, recv_msg);
        }
        break;
        
        default:
            break;
    }
    return ;
}
 
/**********************************************************************
* 函数名称： void CAN_Write(int can_port, CanTxMsg send_msg)
* 功能描述： CAN报文发送接口，调用发送寄存器发送报文
* 输入参数： can_port,端口号     
* 输出参数： send_msg：发送报文
* 返 回 值： 无
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN_Write(int can_port, CanTxMsg send_msg)
{
    unsigned char i;
    uint8_t transmit_mailbox = 0;
    CanTxMsg TxMessage;
    
    switch( can_port )
    {
        case CAN_PORT_CAN1:
        {
            TxMessage.StdId = send_msg.StdId;	  // 标准标识符为0x000~0x7FF
            TxMessage.ExtId = 0x0000;             // 扩展标识符0x0000
            TxMessage.IDE   = CAN_ID_STD;         // 使用标准标识符
            TxMessage.RTR   = CAN_RTR_DATA;       // 设置为数据帧 
            TxMessage.DLC   = send_msg.DLC;       // 数据长度, can报文规定最大的数据长度为8字节
            
            for(i=0; i<TxMessage.DLC; i++)
            {
                TxMessage.Data[i] = send_msg.Data[i];
            }
            transmit_mailbox = CAN_Transmit(CAN1,&TxMessage);  /* 返回这个信息请求发送的邮箱号0,1,2或没有邮箱申请发送no_box */	
        }
        break;
        
        default:
            break;
    }
    return ;
}

/**********************************************************************
* 函数名称： void CAN1_RX0_IRQHandler(void)
* 功能描述： CAN接收中断函数
* 输入参数： 无  
* 输出参数： 无
* 返 回 值： 无
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN1_RX0_IRQHandler(void)
{
    /* 如果回调函数存在，则执行回调函数 */
    if( g_pCanInterrupt != NULL)
    {
        g_pCanInterrupt();
    }  
    
    /* 清除挂起中断 */
    CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  
}


/**********************************************************************
* 名称：     can1_controller
* 功能描述： CAN1结构体初始化
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
CAN_COMM_STRUCT can1_controller = {
    .name                   = "can0",
	.can_port               = CAN_PORT_CAN1,        
	.can_set_controller     = CAN_Set_Controller,
    .can_set_interrput      = CAN_Set_Interrupt,
    .can_read               = CAN_Read,
    .can_write              = CAN_Write, 
};


/**********************************************************************
* 函数名称： void CAN1_contoller_add(void)
* 功能描述： CAN结构体注册接口，应用层在使用can1_controller前调用
* 输入参数： 无  
* 输出参数： 无
* 返 回 值： 无
* 修改日期             版本号        修改人           修改内容
* -----------------------------------------------
* 2020/05/13         V1.0             bert            创建
***********************************************************************/
void CAN1_contoller_add(void)
{
    /*将can1_controller传递给应用层*/
    register_can_controller( &can1_controller );
}


/***********************************************************************
****************End Of File*********************************************
***********************************************************************/




