(二)CAN通信协议代码-基础版

(1)CAN初始化函数


/* -------------------------- Filter global --------------------------*/
#define STDID 0
#define EXTID 1

/* 过滤器编号 */
static u8 filterNumber = 0;

/* 内部函数声明 */
void myCanFilterList(u8 can_dev, uint32_t* p_canId, int size, int flag);
u8 myCanFilterMask(u8 can_dev, uint32_t* p_canIdMask, int size, int flag);
u8 canIdSeparation(u8 can_dev, uint32_t* p_canId, int size, u8 filterMode);
u8 myFilter(u8 can_dev, u32* p_canId, u8 filterMode, u8 filterScale);

/* --- CANx 设备属性设置 --- */
typedef struct __can_port_t {
    u32 can_dev;
    gpio_pin_t tpin;
    gpio_pin_t rpin;
    u32 pin_map;
    u32 can_rcc;
    CAN_TypeDef* can_channel;
    u8 irq;
    u8 pre_priority;
    u8 sub_priority;
    u8 can_res;
    u32 IT_flag;
} can_port_t;

static can_port_t can_port[CAN_DEV_CNT] = {
    [CAN_DEV1] = {
        .can_dev = CAN_DEV1,
        .tpin = { GPIO_Pin_12, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_TX PA12
        .rpin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_RX PA11
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN1,
        .can_channel = CAN1,
        .irq = CAN1_RX0_IRQn,
        .pre_priority = 0,
        .sub_priority = 0,
        .IT_flag = CAN_IT_FMP0,
    },
    [CAN_DEV2] = {
        .can_dev = CAN_DEV2,
        .tpin = { GPIO_Pin_13, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_TX PB13
        .rpin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_RX PB12
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN2,
        .can_channel = CAN2,
        .irq = CAN1_RX1_IRQn,
        .pre_priority = 0,
        .sub_priority = 0,
        .IT_flag = CAN_IT_FMP1,
    }
};

/*--- 常用CAN波特率 ---*/
typedef struct __can_tq_t {
    u16 can_baudrate;
    u16 can_prescaler;
    u8 can_syn_jump_width;
    u8 can_time_bit_seg1;
    u8 can_time_bit_seg2;
    u8 can_res;
}can_tq_t;

typedef enum __can_baud_t{
    CAN_BAUD_5KHZ,
    CAN_BAUD_10KHZ,
    CAN_BAUD_20KHZ,
    CAN_BAUD_40KHZ,
    CAN_BAUD_50KHZ,
    CAN_BAUD_80KHZ,
    CAN_BAUD_100KHZ,
    CAN_BAUD_125KHZ,
    CAN_BAUD_200KHZ,
    CAN_BAUD_250KHZ,
    CAN_BAUD_400KHZ,
    CAN_BAUD_500KHZ,
    CAN_BAUD_666KHZ,
    CAN_BAUD_800KHZ,
    CAN_BAUD_1000KHZ,
    CAN_BAUD_NUM
}can_baud_t;

/*CAN 波特率,预分频值,SJW,BS1,BS2 */
static can_tq_t can_baud_array[CAN_BAUD_NUM] = {
    [CAN_BAUD_5KHZ]    =  {5,    400, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_10KHZ]   =  {10,   200, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_20KHZ]   =  {20,   100, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_40KHZ]   =  {40,   50,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_50KHZ]   =  {50,   40,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_80KHZ]   =  {80,   25,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_100KHZ]  =  {100,  20,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_125KHZ]  =  {125,  16,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_200KHZ]  =  {200,  10,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_250KHZ]  =  {250,  36,  CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq},
    [CAN_BAUD_400KHZ]  =  {400,  5,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_500KHZ]  =  {500,  4,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_666KHZ]  =  {666,  3,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},
    [CAN_BAUD_800KHZ]  =  {800,  11,  CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq},
    [CAN_BAUD_1000KHZ] =  {1000, 9,   CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq}
};

/*--- 设置CAN波特率 ---*/
int canBaudSet(u32 BaudRate)
{   
    can_tq_t* pcanbaud = can_baud_array;
    u8 c_i;
    u8 canBaudNum;

    for (c_i = 0; c_i < CAN_BAUD_NUM; c_i++) {
        if(pcanbaud->can_baudrate == BaudRate) {
            canBaudNum = c_i;
            break;
        }
        pcanbaud++;
    }
    if (c_i >= CAN_BAUD_NUM) {
        _debug(SYS_INFO, "Setting BaudRate param is unqualified \n");
        return -1;
    }

    return canBaudNum;
}

/** ------------------------ CAN 初始化 ------------------------- *
 * @brief  CAN初始化、配置GPIO为复用功能、CAN过滤器Filter初始化
 * @param  can_dev can设备号
 *         can_mode 工作模式,正常/环回/静默
 *         BaudRate 波特率,注意单位:KHZ
 * @retval 成功 0
 *         失败 1
 * ------------------------------------------------------------ */
u8 can_dev_init(u8 can_dev, u8 can_mode, u32 BaudRate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    can_port_t* pparam = &can_port[can_dev];

    _debug(SYS_INFO, "CAN%d Init start ...\n", pparam->can_dev + 1);

    /* 使能GPIO、CANx外设复用功能时钟使能 */
    RCC_APB1PeriphClockCmd(pparam->can_rcc, ENABLE);
    RCC_APB2PeriphClockCmd(pparam->rpin.gpio_rcc | pparam->tpin.gpio_rcc, ENABLE);
    if (pparam->pin_map != 0) {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    }

    /* GPIO 复用功能初始化:Rx */
    GPIO_InitStructure.GPIO_Pin = pparam->rpin.pin_bit;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_Init(pparam->rpin.gpio_port, &GPIO_InitStructure);

    /* GPIO 复用功能初始化:Tx */
    GPIO_InitStructure.GPIO_Pin = pparam->tpin.pin_bit;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_Init(pparam->tpin.gpio_port, &GPIO_InitStructure);

    /* CAN 初始化 */
    u8 ret_can;
    u8 canBaudNo;
    can_tq_t* pcanbaud = NULL;

    canBaudNo = canBaudSet(BaudRate);
    if (canBaudNo == -1) {
        _debug(SYS_INFO, "Setting BaudRate param is unqualified \n");
        return 1;
    }
    pcanbaud = &can_baud_array[canBaudNo];
    CAN_InitStructure.CAN_Prescaler = pcanbaud->can_prescaler;
    CAN_InitStructure.CAN_SJW = pcanbaud->can_syn_jump_width;
    CAN_InitStructure.CAN_BS1 = pcanbaud->can_time_bit_seg1;
    CAN_InitStructure.CAN_BS2 = pcanbaud->can_time_bit_seg2;
    _debug(SYS_INFO, "BaudRate = %dKHZ, can_prescaler = %d, CAN_SJW_%dtq, CAN_BS1_%dtq, CAN_BS2_%dtq \n",
        pcanbaud->can_baudrate, 
        pcanbaud->can_prescaler, 
        pcanbaud->can_syn_jump_width + 1, 
        pcanbaud->can_time_bit_seg1 + 1, 
        pcanbaud->can_time_bit_seg2 + 1);

    CAN_InitStructure.CAN_Mode = can_mode;
    CAN_InitStructure.CAN_TTCM = DISABLE; // can_time_trigger_communication;
    CAN_InitStructure.CAN_ABOM = DISABLE; // can_auto_bus_off;
    CAN_InitStructure.CAN_AWUM = DISABLE; // can_auto_wakeup;
    CAN_InitStructure.CAN_NART = ENABLE;  // can_no_auto_retransmit;(开启不自动重发)
    CAN_InitStructure.CAN_RFLM = DISABLE; // can_recv_fifo_lock;
    CAN_InitStructure.CAN_TXFP = DISABLE; // can_transmit_fifo_priority;
    ret_can = CAN_Init(pparam->can_channel, &CAN_InitStructure);
    if (ret_can == 0) {
        _debug(SYS_EMERG, "CAN%d Initialize is fail ...\n", pparam->can_dev + 1);
        return 1; 
    }

#if 0
    /* CAN接收中断参数配置 */
    NVIC_InitTypeDef NVIC_InitStructure;
    CAN_ITConfig(pparam->can_channel, pparam->IT_flag, ENABLE);                    // FIFO消息挂号中断允许
    NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;                              // 设置IRQ通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = pparam->pre_priority;   // 设置抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = pparam->sub_priority;          // 设置响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                // 使能IRQ通道
    NVIC_Init(&NVIC_InitStructure);                                                // 初始化CAN中断配置
#endif

    _debug(SYS_INFO, "CAN%d Init end ...\n", pparam->can_dev + 1);
    return 0;
}

/*--------------------------- CANx 去初始化 ---------------------------*/
void can_uninit(u8 can_dev)
{
    can_port_t* pparam = &can_port[can_dev];
    clearFilter(can_dev);                              // 所有过滤器的id都失效
    CAN_DeInit(pparam->can_channel);                   // 复位默认值
    RCC_APB1PeriphClockCmd(pparam->can_rcc, DISABLE);  // 禁止(关闭)CAN_RCC时钟
}

void CAN1_RX0_IRQHandler(void)
{
    CAN_Receive_Msg(CAN_DEV1);
    _debug(SYS_INFO, "CAN1 RX0_IRQHandler...\n");
}

void CAN2_RX0_IRQHandler(void)
{
    CAN_Receive_Msg(CAN_DEV2);
    _debug(SYS_INFO, "CAN2 RX0_IRQHandler...\n");
}


(2)CAN过滤器函数


/*------------------------- 列表模式配置can_id ------------------------*/
/**
  * @brief CAN过滤器 标识符列表模式添加can_id
  * @param can_dev       
  *        p_canList    指向32位地址的指针;
  *                     最高位设置为0表示stdid,11位标准id(0x00 ~ 0x7FF) eg: id = 0x12
  *                     最高位设置为1表示extid,29位扩展id(0x00 ~ 0x1FFF FFFF) eg: id = 0x80000001
  *        size         过滤器的id总数
  * @retval 成功 0
  *         失败 1
  */
u8 myCAN_Filter_List(u8 can_dev, uint32_t* p_canList, int size)
{
    can_port_t* pparam = &can_port[can_dev];
    if ((pparam->can_channel != CAN1) && (pparam->can_channel != CAN2)) {
        _debug(SYS_EMERG, "Can channel is error!\n");
        return 1;
    }
    canIdSeparation(can_dev, p_canList, size, CAN_FilterMode_IdList);
    return 0;
}

/**
  * @brief CAN过滤器 列表模式(默认canId = 0为通用id地址,即id = 0,默认可以通过过滤器)
  * @param can_dev  
  *        p_canId  指向id数组
  *        size     id的个数
  *        flag     过滤器标识符id格式:0-标准id,1-扩展id
  * @retval None
  */
void myCanFilterList(u8 can_dev, uint32_t* p_canId, int size, int flag)
{
    u8 i = 0;
    u8 position; // 保存整数(取整 /)
    u8 remain;   // 保存余数(取余 %)
    u16 filterIdLow;
    u16 filterIdHigh;
    u16 filterMaskIdLow;
    u16 filterMaskIdHigh;
    u32 canId[2] = { 0 }; // 用于保存can过滤器组的2个32位寄存器:filterid和maskid

    switch (flag) { 
        // 标准id,列表模式:按16位宽填充filterId和maskId,最多一次填充4个stdId
        case 0: { 
            position = size / 4;
            remain = size % 4;

            for (i = 0; i < position; i++) { // 左移5位原因: 低5位id映射是 RTR IDE EXID[17:15]
                filterIdLow = *p_canId << 5; 
                p_canId++;
                filterIdHigh = *p_canId << 5;
                p_canId++;
                filterMaskIdLow = *p_canId << 5;
                p_canId++;
                filterMaskIdHigh = *p_canId << 5;
                p_canId++;

                canId[0] = (filterIdHigh << 16) | filterIdLow; // 默认ide = 0,rtr = 0:标准id,数据帧
                canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;
                myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);
            }

            if (remain > 0) {
                filterIdLow = *p_canId << 5; // 在(4 - remain)的剩余区间为无id值,此时默认设置:can_id = 0
                p_canId++;
                filterIdHigh = *p_canId << 5;
                p_canId++;
                filterMaskIdLow = *p_canId << 5;
                p_canId++;
                filterMaskIdHigh = *p_canId << 5;
                p_canId++; // 不可省略

                canId[0] = (filterIdHigh << 16) | filterIdLow;
                canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;
                myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);
            }
            break;
        }
        
        // 扩展id,列表模式:按32位宽填充filterId和maskId,最多一次填充2个extId
        case 1: { 
            position = size / 2;
            remain = size % 2;

            for (i = 0; i < position; i++) {
                filterIdLow = *p_canId << 3;
                filterIdHigh = (*p_canId << 3) >> 16;
                p_canId++;
                filterMaskIdLow = *p_canId << 3;
                filterMaskIdHigh = (*p_canId << 3) >> 16;
                p_canId++;

                canId[0] = (filterIdHigh << 16) | filterIdLow | (1 << 2); // 设置ide = 1,rtr = 0:扩展id,数据帧
                canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow | (1 << 2);
                myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_32bit);
            }

            if (remain > 0) {
                filterIdLow = *p_canId << 3;          // 在(2 - remain)的剩余区间为无id值,此时默认设置:can_id = 0
                filterIdHigh = (*p_canId << 3) >> 16;
                filterMaskIdLow = filterIdLow;        // 将剩下的一个32位寄存器,填充和上一个寄存器相同的id 
                filterMaskIdHigh = filterIdHigh;

                canId[0] = (filterIdHigh << 16) | filterIdLow | (1 << 2);
                canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow | (1 << 2);
                myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_32bit);
            }
            break;
        }
    }
}


/*----------------------------- 掩码模式配置can_id --------------------------------*/
/**
  * @brief CAN过滤器 标识符掩码模式 
  * @param can_dev
  *        p_canList 指向32位地址的指针;最高位设置为0表示stdid,11位标准id(0x00 ~ 0x7FF)
  *                  最高位设置为1表示extid,29位扩展id(0x00 ~ 0x1FFF FFFF)
  *        size      过滤器的id总数
  * @retval 成功 0
  *         失败 1
  */
u8 myCAN_Filter_Mask(u8 can_dev, uint32_t* p_canIdMask, int size)
{
    can_port_t* pparam = &can_port[can_dev];
    if ((pparam->can_channel != CAN1) && (pparam->can_channel != CAN2)) {
        _debug(SYS_INFO, "Can channel is error!\n");
        return 1;
    }
    canIdSeparation(can_dev, p_canIdMask, size, CAN_FilterMode_IdMask);
    return 0;
}

/**
  * @brief CAN过滤器 掩码模式
  * @param can_dev  
  *        p_canId  指定的id组
  *        size     id的个数
  *        flag     过滤器标识符id格式:0-标准id,1-扩展id
  * @retval 成功 0
  *         失败 1
  */
u8 myCanFilterMask(u8 can_dev, uint32_t* p_canIdMask, int size, int flag)
{
    u8 i = 0;
    u8 position = 0;
    u32 canId[2] = { 0 };

    if (size % 2) { // 确保掩码id:filterId和maskId成对出现
        _debug(SYS_INFO, "the number of Mask_canId is not pow(2) \n");
        return 1;
    }
   
    switch (flag) {
        // 标准id掩码模式,按32位宽处理
        case 0: 
        {
            position = size / 2;
            for (i = 0; i < position; i++) {
                canId[0] = *p_canIdMask << 21; // 默认ide = 0,rtr = 0; 标准id,数据帧
                p_canIdMask++;
                canId[1] = *p_canIdMask << 21;
                p_canIdMask++;
                printf("can_id[0] = 0x%x, can_id[1] = 0x%x\n", canId[0], canId[1]);
                myFilter(can_dev, canId, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);
            }
            break;
        }

        // 扩展id掩码模式,按32位宽处理
        case 1: 
        {
            position = size / 2;
            for (i = 0; i < position; i++) {
                canId[0] = (*p_canIdMask << 3) | (1 << 2); // 设置ide = 1,rtr = 0; 扩展id,数据帧
                p_canIdMask++;
                canId[1] = (*p_canIdMask << 3) | (1 << 2);
                p_canIdMask++;
                myFilter(can_dev, canId, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);
            }
            break;
        }
    }

    return 0;
}

/*----------------------- canIdSeparation 分离 ---------------------------*/
/**
  * @brief 将canId数组分离出标准id(11bits)和扩展id(29bits)
  * @param can_dev  
  *        p_canId  指向can_id数组
  *        size     id的个数
  *        filterMode 过滤器模式
  * @retval 成功 0
  *         失败 1
  */
u8 canIdSeparation(u8 can_dev, uint32_t* p_canId, int size, u8 filterMode)
{
    u8 i;
    u32 canId;
    u32 stdIdBuff[56] = { 0 }; // canId为标准id:按16位宽处理节约资源(56 = 14组过滤器 * 4个stdid)
    u32 extIdBuff[28] = { 0 }; // canId为扩展id:按32位宽处理(28 = 14 * 2个extid)
    u8 std_i = 0;              // 记录id的个数
    u8 ext_i = 0;

    /* 把标准id和扩展id分离出来后放入:stdIdBuff、extIdBuff*/
    for (i = 0; i < size; i++) {
        canId = *p_canId;
        _debug(SYS_INFO, "canId = 0x%x\n", canId);

        /* 
           整个id的值超过取值范围:
           canId & 0x7FFFFFFF:不考虑最高位,只考虑后31位; 
           & (~ 0x1FFFFFFF):不考虑低29位,如果(30:31)位有数据,则超过取值 
        */
        if ((canId & 0x7FFFFFFF) & (~ 0x1FFFFFFF)) { 
            _debug(SYS_INFO, "CAN id is unqualified, beyond scale \n");
            return 1;
        }

        /* 标准id最高位为0时,stdid取值范围超过0x7FF */
        if (((canId >> 31) == 0) && (canId & (~ 0x7FF))) {
            _debug(SYS_INFO, "CAN stdid is unqualified, beyond scale \n");
            return 1;
        }

        /* 将标准id和扩展id各自分离出来:移除低31位,只保留最高位:标识位 */
        if (canId >> 31) { // 1 = 扩展帧
            extIdBuff[ext_i] = canId & 0x7FFFFFFF; // 除去最高位(标识位),以获得扩展帧
            ext_i++;
        } else { 
            stdIdBuff[std_i] = canId;
            std_i++;
        }

        p_canId++; // canid地址自动加1
    }

    for (i = 0; i < std_i; i++) {
        _debug(SYS_INFO, "stdIdBuff[%d] = 0x%x, std_i = %d\n", i, stdIdBuff[i], std_i);
    }
    printf("---------------------------------\n");
    for (i = 0; i < ext_i; i++) {
        _debug(SYS_INFO, "extIdBuff[%d] = 0x%x, ext_i = %d\n", i, extIdBuff[i], ext_i);
    }
    _debug(SYS_INFO, "---------------------------------\n");

    /* 清除can通道的所有过滤器中的id */
    clearFilter(can_dev);

    /* 设置can_id  0:标准Id; 1:扩展Id */
    if (filterMode == CAN_FilterMode_IdList) { 
        myCanFilterList(can_dev, stdIdBuff, std_i, STDID);  
        myCanFilterList(can_dev, extIdBuff, ext_i, EXTID);

    } else {
        myCanFilterMask(can_dev, stdIdBuff, std_i, STDID);
        myCanFilterMask(can_dev, extIdBuff, ext_i, EXTID);
    }

    return 0;
}

/**--------------------------- myFilter CAN过滤器配置 ---------------------*/
/* @brief CAN过滤器,寄存器配置 
  * @param can_dev 
  *        p_canId  指定的id组
  *        size     id的个数
  *        filterMode   过滤的模式:列表/掩码
  *        filterScale  过滤器位宽
  * @retval 成功:0
  *         失败:1
  */
u8 myFilter(u8 can_dev, u32* p_canId, u8 filterMode, u8 filterScale)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    can_port_t* pparam = &can_port[can_dev];
    u32 can_id[2] = {p_canId[0], p_canId[1]};
    
    // printf("canId[0] = 0x%x, canId[1] = 0x%x, filternum = %d\n", can_id[0], can_id[1], filterNumber);
    // printf("p_canId[0] = 0x%x, p_canId[1] = 0x%x, filternum = %d\n", p_canId[0], p_canId[1], filterNumber);
    /* 防止can通道分配的过滤器编号超过编号取值范围:CAN1:0 ~ 13; CAN2:14 ~ 27 */
    if (pparam->can_channel == CAN1) {
        if(filterNumber > 13) {
            _debug(SYS_INFO, "the distribution of Can Filter Number go beyond rank: CAN1 > 13\n");
            return 1;
        }
    } else { 
        CAN_SlaveStartBank(14); // 开启CAN2通道
        if(filterNumber > 27) {
            _debug(SYS_INFO, "the distribution of Can Filter Number go beyond rank:  CAN2 > 27\n");
            return 1;
        }
    }
    
    /* 一组过滤器的2个32位寄存器拆分成四个16位的基础寄存器 */
    CAN_FilterInitStructure.CAN_FilterIdLow = *p_canId;
    CAN_FilterInitStructure.CAN_FilterIdHigh = *p_canId >> 16;
    _debug(SYS_INFO, "CAN_FilterId = 0x%x\n", *p_canId);  
    p_canId++;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = *p_canId;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = *p_canId >> 16;
    _debug(SYS_INFO, "CAN_FilterMaskId = 0x%x\n", *p_canId); 
    _debug(SYS_INFO, "filterNumber = %d\n", filterNumber);
    
    if (pparam->can_channel == CAN1) { 
        CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; 
    } else { 
        CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1; 
    }

    CAN_FilterInitStructure.CAN_FilterNumber = filterNumber; // CAN1:0 ~ 13; CAN2:14 ~ 27
    filterNumber++;
    CAN_FilterInitStructure.CAN_FilterScale = filterScale;
    CAN_FilterInitStructure.CAN_FilterMode = filterMode; 
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    return 0;
}

/*------------------------ 清除CANx通道 过滤器 --------------------------*/
/* 清除can通道的所有过滤器中的id 
 * 思路:将所有过滤器组全部以掩码模式(扩展id)填充:filterid和maskid对应位全置1,不过滤任何id
 */
void clearFilter(u8 can_dev)
{   
    can_port_t* pparam = &can_port[can_dev];
    u8 i = 0;
    u32 maskId = 0xFFFFFFF8 | (0x1 << 2);
    u32 canIdClear[2] = {0};
    canIdClear[0] = maskId;
    canIdClear[1] = maskId;
    
    if(pparam->can_channel == CAN1) {
        filterNumber = 0;
    } else {
        filterNumber = 14;
    }

    // 以掩码模式,扩展id填充过滤器
    for(i = 0; i < 14; i++) {
        myFilter(can_dev, canIdClear, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);
    }

    // 恢复过滤器的默认起始编码号
    if (pparam->can_channel == CAN1) {
        filterNumber = 0;
    } else {
        filterNumber = 14;
    }
}

(3)CAN 发送/接收函数

/* ------------------------ CANx 发送msg --------------------------------
* @功能:CANx 发送一组数据(固定can_id = 0x12, 标准帧, 数据帧)
* @参数:len:数据长度(最大为 8)
        msg:数据指针,数据最大为 8 个字节.
* @返回值:0, 成功;
        其他,失败;
* -------------------------------------------------------------------- */
u8 CAN_Transmit_Msg(u8 can_dev, u8* msg, u8 len)
{
    u16 i;
    u8 tx_mbox;
    CanTxMsg TxMessage;
    can_port_t* pparam = &can_port[can_dev];

    TxMessage.StdId = 0x12;
    TxMessage.ExtId = 0x12;
    TxMessage.IDE = CAN_Id_Standard;
    TxMessage.RTR = CAN_RTR_Data; 
    TxMessage.DLC = len;
    for (i = 0; i < len; i++) {
        TxMessage.Data[i] = msg[i];
    }
    _debug(SYS_INFO, "can%d translate = %s\n", pparam->can_dev + 1, msg);

    tx_mbox = CAN_Transmit(pparam->can_channel, &TxMessage);
    if (tx_mbox == CAN_TxStatus_NoMailBox) {
        _debug(SYS_INFO, "CAN%d Transmit Status is No MailBox ...\n", pparam->can_dev + 1);
        return 1;
    }

    /* 等待CAN发送一段时间;如果超时,则失败 */
    i = 0;
    while ((CAN_TransmitStatus(pparam->can_channel, tx_mbox) == CAN_TxStatus_Failed) && (i < 0xFFF)) {
        i++;
    }
    if (i >= 0xFFF) {
        _debug(SYS_INFO, "CAN%d Transmit fail, time out ...\n", pparam->can_dev + 1);
        return 1;
    }

    return 0;
}

/** ------------------------ CANx 接收msg ------------------------------
 * @brief CANx 接收一组数据(固定格式:ID = 0X12, 标准帧, 数据帧)
 * @param can_dev CAN设备号
 *        msg:数据指针,数据最大为 8 个字节
 * @retval 0:无数据被收到
 *      其他:成功接收的数据长度
 * ------------------------------------------------------------------ */
u8 CAN_Receive_Msg(u8 can_dev, u8 * msg)
{
    u32 i;
    CanRxMsg RxMessage;
    can_port_t* pparam = &can_port[can_dev];

    /* 判别是哪个接收邮箱有数据挂起 */
    if (CAN_MessagePending(pparam->can_channel, CAN_FIFO0)) {
        CAN_Receive(pparam->can_channel, CAN_FIFO0, &RxMessage);
        for (i = 0; i < RxMessage.DLC; i++) {
            msg[i] = RxMessage.Data[i];
            printf("CAN1 msg[%d]\n", i, msg[i]);
        }
        return RxMessage.DLC;
    } else if (CAN_MessagePending(pparam->can_channel, CAN_FIFO1)) {
        CAN_Receive(pparam->can_channel, CAN_FIFO1, &RxMessage);
        for (i = 0; i < RxMessage.DLC; i++) {
            msg[i] = RxMessage.Data[i];
            printf("CAN2 msg[%d]\n", i, msg[i]);
        }

        _debug(SYS_INFO, "can receive msg CAN_id = 0x%x ...\n", RxMessage.StdId);
        return RxMessage.DLC;
    }

    /* 没有接收到数据,直接退出 */
    return 0;
}

头文件

#ifndef __P_CAN_H__
#define __P_CAN_H__

/*------------- type define -----------------*/
// can_dev 参数取值范围
typedef enum {
    CAN_DEV1,
    CAN_DEV2,
    CAN_DEV_CNT
} CAN_DEV_E;

/*------------- Function --------------------*/
// BaudRate 单位为HKZ
u8 can_dev_init(u8 can_dev, u8 can_mode, u32 BaudRate);
void can_uninit(u8 can_dev);

// 过滤器函数
u8 myCAN_Filter_List(u8 can_dev, uint32_t* p_canList, int size);
u8 myCAN_Filter_Mask(u8 can_dev, uint32_t* p_canIdMask, int size);
void clearFilter(u8 can_dev);

// can发送msg,固定can_id = 0x12, 标准帧, 数据帧
u8 CAN_Transmit_Msg(u8 can_dev, u8* msg, u8 len);
u8 CAN_Receive_Msg(u8 can_dev, u8 * msg);
#endif

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值