linux下socketCAN实现反转过滤——CAN_INV_FILTER的使用

关于Linux中socket can怎么使用,CSDN上已经有很多文章介绍。本文重点记录can_filter中的 CAN_INV_FILTER的使用,很多文章对此一笔带过,且很多文章翻译不全,或者原文不全,导致自己浪费了些时间,最后在看candump源码时才发现问题所在。

直接贴代码解释,以下为写的一个最简单的canId过滤函数:

宏定义

/** CAN报文过滤方式 **/
#define CAN_FILTER_PASS     0x01    //过滤方式-通过
#define CAN_FILTER_REJECT   0x02    //过滤方式-拒绝

函数声明

    /**
     * @brief canRcvFiltersSet - CAN报文接收过滤设置
     * @param canIdArray: 数组中每个元素为要过滤的canId且不能为0;若该参数置为NULL,则表示该Can口不需要接收任何报文
     * @param arraySize: 数组大小,若canIdArray置为NULL,则该项置0
     * @param filterType: 过滤方式的宏定义,若canIdArray置为NULL,则该项置0,否则应为以下二选一
     *          CAN_FILTER_PASS: 只接收与canIdArray中canId一致的报文
     *          CAN_FILTER_REJECT: 与canIdArray中canId一致的报文都不接收,其它报文接收
     * @return true:成功,false:失败
     */
    bool canRcvFiltersSet(const uint *canIdArray, const uint &arraySize, short filterType);

函数定义

bool rcvFiltersSet(const uint *canIdArray, const uint &arraySize, short filterType)
{
    if(canfd <= 0)	//canfd就不用解释了…
        return false;

    if(NULL == canIdArray){
        setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);    //不需要接收任何报文
        return true;
    }

    struct can_filter rfilter[arraySize];
    bzero(rfilter,sizeof (rfilter));

    for(uint i = 0; i < arraySize; ++i){
        if(canIdArray[i]){
            if(filterType & CAN_FILTER_PASS){
                rfilter[i].can_id = canIdArray[i];
            }
            else{
                rfilter[i].can_id = (canIdArray[i] | CAN_INV_FILTER);
            }
            rfilter[i].can_mask = CAN_EFF_MASK; //这个掩码怎么设置看自己需求
        }else{
            return false;
        }
    }
    //重点!!!很多文章没提到这一点,过滤器反转时需要设置,使各过滤器之间由逻辑或变成逻辑与关系,
    //否则设置的反转过滤器因为相互矛盾导致不起作用
    //简单举例解释,过滤器A接收除0x123之外的报文,过滤器B接收除0x124之外的报文,
    //那么0x123虽然被过滤器A过滤了,但是会被过滤器B通过,同理0x124会被过滤器A通过,所以实际上不起作用
    //下面的设置就是让过滤器之间join起来,只有符合所有过滤器的规则才会被通过
    if(filterType & CAN_FILTER_REJECT){
        int join_filter = 1;
        setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &join_filter, sizeof(join_filter));
    }
    setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
    return true;
}

使用示例:

     *     const uint can_id_reject[] = {0x123, 0x11111678, 0x282};	//除这三种canid之外的报文,都接收
           canRcvFiltersSet(can_id_reject, sizeof(can_id_reject)/sizeof(uint), CAN_FILTER_REJECT);
           
     *     const uint can_id_pass[] = {0x123, 0x11111678, 0x282};	//只接收这三种canid报文,其它不接收
           canRcvFiltersSet(can_id_pass, sizeof(can_id_pass)/sizeof(uint), CAN_FILTER_PASS);

完。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值