我会尽量保持简短。我有一个C应用程序,可以使用以下方法打开可以套接字的端口 ...
struct sockaddr_can lCanAddr;
struct ifreq lIfr;
if ((*aCanSocket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
log_error("socket not created");
return -1;
}
strcpy(lIfr.ifr_name, CANSOCKETNAME);
ioctl(*aCanSocket, SIOCGIFINDEX, &lIfr);
lCanAddr.can_family = AF_CAN;
lCanAddr.can_ifindex = lIfr.ifr_ifindex;
....
如何检测以下情况:
答案 0 :(得分:0)
SocketCAN使用错误帧报告CAN总线错误。这些是特殊的can_frame
,在can_id
中设置了位0x20000000。 can_id
中的其他位以及data
中的字节包含有关错误的信息。有关更多信息,请参见<linux/can/error.h>
。
要接收错误帧,首先必须启用它们。 SocketCAN支持过滤它们,但最简单的方法就是全部启用它们:
can_err_mask_t optval = CAN_ERR_MASK;
setsockopt(*aCanSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &optval, sizeof(optval));
每次读取CAN帧时,首先必须检查它是错误帧还是正常数据帧。
通常,在尝试发送CAN帧之前,您不会收到错误帧。在CAN总线损坏的情况下,这通常会迅速导致总线关闭错误。当您收到CAN_ERR_BUSOFF
中设置了0x040(can_id
)位的错误帧时,可以检测到这一点。
我不确定如果没有设备连接到总线,您是否会收到错误消息。但是,如果驱动程序支持,可能还有另一种检查方法。如果总线上没有其他设备,发送的帧的ACK位将不会被清除,这是CAN控制器可以检测到的。如果驱动程序将未确认的帧视为未发送,则可以在应用程序中检测到这一点。首先,您必须设置一些选项,以便接收所有发送的帧:
setsockopt(*aCanSocket, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &(int){ 1 }, sizeof(int));
setsockopt(*aCanSocket, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &(int){ 1 }, sizeof(int));
第二,您必须使用recvmsg()
来读取CAN帧,以便可以检查msg_flags
结构的msghdr
成员。如果它包含MSG_CONFIRM
标志,则它是传输确认。它指示该帧已成功通过您接收它的套接字发送。您可以使用它来检测CAN总线上是否存在其他设备。如果发送框架并收到确认,则存在其他设备。如果您从未收到确认,则说明您是公交车上唯一的设备(否则还有其他问题)。