如何使用C中的CAN插座检测打开的CAN总线

时间:2020-11-11 08:28:09

标签: c linux sockets can-bus

我会尽量保持简短。我有一个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;

....

如何检测以下情况:

  1. 当CAN总线损坏或没有设备连接到CAN端口时
  2. CAN总线关闭错误 我尝试通过定期读取或写入套接字来尝试某种方法,但这不会引发任何错误。谁能建议我一种检测这种情况的方法。我正在使用C实现。感谢您的时间和耐心。

1 个答案:

答案 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总线上是否存在其他设备。如果发送框架并收到确认,则存在其他设备。如果您从未收到确认,则说明您是公交车上唯一的设备(否则还有其他问题)。