#include "can.h"
#include "global.h"
#include <string.h>

#define MASK_ID 0x18CE00EF

CanRxMsg RxMessageImportant;
CanRxMsg RxMessageNormal;

CanData_TypeDef CanDataImportant; //  重要数据
extern SqQueue  CanQueueImportant;
// extern _declare_box8(can1_mpool, BlockSizeCan1, BlockCountCan1);
// extern  os_mbx_declare (can1_mailbox, sizeof(can1_mpool)/sizeof(CanRxMsg));//声明消息邮箱  读取can1数据
// CAN初始化
// tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
// tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
// tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
// brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
// 波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
// mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
// Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
// 则波特率为:42M/((6+7+1)*6)=500Kbps

u32 result;

u8 CAN1_Mode_Init(u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode)
{
    GPIO_InitTypeDef      GPIO_InitStructure;
    CAN_InitTypeDef       CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    NVIC_InitTypeDef      NVIC_InitStructure;

    u32 mask_id = MASK_ID;

    // 使能相关时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能PORTA时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);  // 使能CAN1时钟

    // 初始化GPIO
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11 | GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;      // 复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 100MHz
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;      // 上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);             // 初始化PA11,PA12

    // 引脚复用映射配置
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1); // GPIOB11复用为CAN1
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1); // GPIOB12复用为CAN1

    // CAN单元设置
    CAN_InitStructure.CAN_TTCM      = DISABLE; // 非时间触发通信模式
    CAN_InitStructure.CAN_ABOM      = DISABLE; // 软件自动离线管理
    CAN_InitStructure.CAN_AWUM      = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
    CAN_InitStructure.CAN_NART      = DISABLE; // 禁止报文自动传送
    CAN_InitStructure.CAN_RFLM      = DISABLE; // 报文不锁定,新的覆盖旧的
    CAN_InitStructure.CAN_TXFP      = DISABLE; // 优先级由报文标识符决定
    CAN_InitStructure.CAN_Mode      = mode;    // 模式设置
    CAN_InitStructure.CAN_SJW       = tsjw;    // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
    CAN_InitStructure.CAN_BS1       = tbs1;    // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
    CAN_InitStructure.CAN_BS2       = tbs2;    // Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
    CAN_InitStructure.CAN_Prescaler = brp;     // 分频系数(Fdiv)为brp+1
    CAN_Init(CAN1, &CAN_InitStructure);        // 初始化CAN1

    // 配置过滤器0
    CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0
    CAN_FilterInitStructure.CAN_FilterMode   = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale  = CAN_FilterScale_32bit; // 32位

    CAN_FilterInitStructure.CAN_FilterIdHigh = (u16)((mask_id << 3) >> 16);      // 0xFFFF;
    CAN_FilterInitStructure.CAN_FilterIdLow  = (u16)((mask_id << 3) | (1 << 2)); // 0xFFFF;

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFF0; // 0x0000;//32位MASK
    //    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfff8; // 最后3位不管
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x07FF; // 0; // 最后3位不管

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; // 过滤器0关联到FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation     = ENABLE;           // 激活过滤器0
    CAN_FilterInit(&CAN_FilterInitStructure);                            // 滤波器初始化

    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0消息挂号中断允许.

    NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; // 主优先级为
                                                              // 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    ////////////////////////////////////////////////

    return 0;
}

/**********************************************************************************************************
 *	函 数 名: CAN1_Init
 *	功能说明: CAN1初始化
 *	形    参: 无
 *	返 回 值: 无
 **********************************************************************************************************/
void CAN2_Init(void)
{
#if defined(__CAN_BAUD_500K)
    CAN1_Mode_Init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 6, CAN_Mode_Normal); // CAN1初始化环回模式,波特率500Kbps
#elif defined(__CAN_BAUD_250K)
    CAN1_Mode_Init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 12, CAN_Mode_Normal); // CAN1初始化环回模式,波特率250Kbps
#else
    //  #error no can baud macro!;
#endif
}

//(固定格式:ID为0X12,标准帧,数据帧)
// len:数据长度(最大为8)
// msg:数据指针,最大为8个字节.
// 返回值:0,成功;
//		 其他,失败;
/****************************************************
 *  函数功能：can1发送一组数据
 *  入口参数：msg 数据  len  数据长度  can_id  CAN id
 *  说    明：group_id 从1开始
 *****************************************************/
u8 CAN2_Send_Msg(u8 *msg, u8 len, u32 can_id)
{
    u16      mbox, i;
    CanTxMsg TxMessage;

    TxMessage.StdId = 0x00;            // 标准标识符为0
    TxMessage.ExtId = can_id;          // 设置扩展标示符（29位）
    TxMessage.IDE   = CAN_Id_Extended; // 使用扩展标识符
    TxMessage.RTR   = CAN_RTR_Data;    // 消息类型为数据帧
    TxMessage.DLC   = len;             // 发送两帧信息

    for (i = 0; i < len; i++)
        TxMessage.Data[i] = msg[i]; // 第一帧信息
    mbox = CAN_Transmit(CAN1, &TxMessage);
    i    = 0;
    while ((CAN_TransmitStatus(CAN1, mbox) == CAN_TxStatus_Failed) && (i < 0XFFF))
        i++; // 等待发送结束
    if (i >= 0XFFF)
        return 1;
    return 0;
}

// CAN1中断服务函数
void CAN1_RX0_IRQHandler(void)
{

    CAN_Receive(CAN1, CAN_FIFO0, &RxMessageImportant); // 1.6us  ucos时间戳、示波器测量都是1.6us

    memcpy(CanDataImportant.buf, RxMessageImportant.Data, RxMessageImportant.DLC);
    CanDataImportant.can_id = RxMessageImportant.ExtId;
    if (InsertQueue(&CanQueueImportant, CanDataImportant) == ERROR) // 队列插入数据
    {
    }
}
