使用CAN BCM发送循环报文时CAN_ID异常为0x00000000的问题
问题原因及解决方案
核心原因
问题出在你对CAN BCM的TX_CP_CAN_ID标志的使用逻辑上:
CAN BCM执行TX_SETUP指令时,默认使用bcm_msg_head.can_id作为发送报文的CAN ID,而非can_frame中的ID。TX_CP_CAN_ID的作用是要求内核把frame[0].can_id的值同步到msg_head.can_id中,但你的代码未初始化msg_head.can_id,且该同步逻辑可能未按预期触发(或内核版本对该标志的支持存在差异),导致msg_head.can_id成为未初始化的垃圾值(恰好为0),最终发送的报文ID为0。
另外需要确认:你预期的0x00000201是扩展帧ID,因此必须保留CAN_EFF_FLAG标志位,实际发送的完整ID应为0x80000201(含扩展帧标志),嗅探工具可能会剥离标志位显示为0x0201,这是正常现象。
修复代码
直接计算并设置msg_head.can_id,移除TX_CP_CAN_ID标志即可解决问题:
// these are placed here for testing unsigned char priority = 0; unsigned char srcaddr = 0; unsigned char destaddr = 2; unsigned objaddr = ESC::enumPWM; struct { struct bcm_msg_head msg_head; struct can_frame frame[4]; } txmsg; txmsg.msg_head.opcode = TX_SETUP; txmsg.msg_head.nframes = 1; // 计算目标CAN ID(包含扩展帧标志) __u32 target_can_id = CAN_EFF_FLAG; target_can_id |= ((0x1F & priority) << 24); target_can_id |= (srcaddr << 16); target_can_id |= (destaddr << 8); target_can_id |= objaddr; // 直接设置msg_head的can_id(BCM发送时会用这个值) txmsg.msg_head.can_id = target_can_id; txmsg.frame[0].can_id = target_can_id; // 可选同步,确保帧数据与头部一致 // 移除TX_CP_CAN_ID标志 txmsg.msg_head.flags = SETTIMER | STARTTIMER; txmsg.msg_head.count = 1200; txmsg.msg_head.ival1.tv_sec = 0; txmsg.msg_head.ival1.tv_usec = 5000; txmsg.msg_head.ival2.tv_sec = 0; txmsg.msg_head.ival2.tv_usec = 0; // configure the data to send txmsg.frame[0].can_dlc = 2; txmsg.frame[0].data[0] = 0x04; txmsg.frame[0].data[1] = 0x4C; txmsg.frame[0].data[2] = 0; txmsg.frame[0].data[3] = 0; txmsg.frame[0].data[4] = 0; txmsg.frame[0].data[5] = 0; txmsg.frame[0].data[6] = 0; txmsg.frame[0].data[7] = 0; int err = write(can->sockfd, &txmsg, sizeof(txmsg));
额外验证
请确认ESC::enumPWM的枚举值确实为0x01,这样计算后的target_can_id才会对应你预期的0x80000201(含扩展帧标志),嗅探工具剥离标志位后即可显示为0x0201。
内容的提问来源于stack exchange,提问作者Coleman
相关产品推荐
相关产品推荐

