2017/09/11

Raspberry PiでCAN通信 その3【C言語で標準フレームの送信】

Raspberry Pi上で、C言語によるCAN通信の標準フレーム送信をします。

can-utilsのソースコードを解析した結果、
標準フレームの送信をする処理を起こしました。

動作環境は、OS:raspbian jessie です。
CANデバイスは、まだCANモジュールが来ていないので、
以下のコマンドで作った仮想CANデバイス(vcan1)で送信します。
sudo modprobe vcan
sudo ip link add dev vcan1 type vcan
sudo ip link set vcan1 up

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>

#define CAN_NAME "vcan1"

int cansend_stdframe(unsigned short id, unsigned char dlc, unsigned char data[])
{
    int s;
    struct ifreq ifr;
    struct sockaddr_can addr;
    struct can_frame frame;
    int loopback;

    if(CAN_MAX_DLEN < dlc)
    {
        fprintf(stderr, "dlc too long.\n");
        return -1;
    }

    memset(&frame, 0, sizeof(frame));
    frame.can_id = id;
    frame.can_dlc = dlc;
    memcpy(&(frame.data[0]), &(data[0]), dlc); 

    if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
    {
        perror("socket");
        return -2;
    }

    memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
    strncpy(ifr.ifr_name, CAN_NAME, sizeof(ifr.ifr_name));

    ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
    if(! ifr.ifr_ifindex)
    {
        perror("if_nametoindex");
        return -3;
    }

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

    /* no loopback */
    loopback = 0; /* 0 = disabled, 1 = enabled(default) */
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

    if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        return -4;
    }

    if(write(s, &frame, CAN_MTU) < CAN_MTU)
    {
        perror("write");
        return -5;
    }

    close(s);

    return 0;
}

int main(int argc, char argv[])
{
    unsigned char data[] = { 0x11, 0x22, 0x33, 0x44 };

    cansend_stdframe(0x0123, sizeof(data), data);
}

ループバックをoffにしているので、candumpで見ていても、何も出てきません。
loopbackの値を1にすれば、出てくるようになります。

CAN標準フレームの送信に必要な処理は、これでわかりました。

次は、これをpythonで実装します。

0 件のコメント:

コメントを投稿