SocketCAN接收29位扩展帧ID与DLC正常但数据全为0问题咨询
问题根因与解决方案
代码层面错误
- 全局
struct can_frame变量污染问题
你所有逻辑共用同一个全局frame变量,bind之后的初始化语句frame.can_id |= CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK;会将初始can_id设为0xDFFFFFFF,如果read操作异常未覆盖结构体内容,就会出现你打印的frame.can_id为0xDFFFFFFF的异常输出。
建议:收发逻辑分别使用独立的局部结构体变量,避免互相干扰。 - 扩展帧过滤规则配置缺失/错误
你提到已配置29位标识符过滤,但贴出的代码中未包含setsockopt配置CAN_RAW_FILTER的逻辑,扩展帧过滤必须在过滤规则中显式携带CAN_EFF_FLAG,否则过滤规则会匹配标准帧,导致接收异常。正确配置示例:
struct can_filter eff_filter = { .can_id = CAN_EFF_FLAG | 0x800, // 目标扩展帧ID,携带EFF标志 .can_mask = CAN_EFF_FLAG | CAN_EFF_MASK // 匹配EFF标志位和全部29位ID }; setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &eff_filter, sizeof(eff_filter));
- RecvCAN函数赋值笔误
代码中RecvBuffer[0][0][5]=frame.data[0];属于明显笔误,应该为RecvBuffer[0][0][5]=frame.data[3];,虽然不会导致全0问题,但会导致后续数据位错位。 - 接收后的调试逻辑错误
你在read之后仅打印了ID,未直接打印frame的data字段,建议直接在read后增加打印逻辑,确认数据是否真的全0,排除RecvBuffer赋值导致的异常:
printf("Recv data: "); for(int i=0;i<frame.can_dlc;i++) printf("%02X ", frame.data[i]); printf("\n");
驱动/系统层面问题
Zynq7000的CAN控制器在Linux 3.10及以下内核版本(Ubuntu12.04默认内核版本)存在扩展帧接收的已知驱动bug,刚好表现为扩展帧ID、DLC正常,但数据字段全为0。很多Zynq用户遇到过相同问题,解决方案如下:
- 先使用系统自带的
candump can0工具测试,确认是否能正常接收上位机发送的扩展帧:- 如果candump也无法正常接收数据,确定为驱动/硬件配置问题
- 如果candump可以正常接收,就是你的应用层代码问题
- 驱动问题修复方案:升级内核到3.18或更高版本,或者手动回查Zynq CAN驱动的补丁,将社区后续修复的扩展帧接收补丁打到你当前的内核中。
内容的提问来源于stack exchange,提问作者Jonne gong
相关产品推荐
相关产品推荐

