2017/09/17

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

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

動作環境は、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 canrecv_stdframe(unsigned short *p_id, unsigned char *p_dlc, unsigned char data[])
{
    int ret;
    int s;
    fd_set rdfs;
    struct ifreq ifr;
    struct sockaddr_can addr;
    struct timeval timeout;
    struct can_frame frame;
    int nbytes;

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

    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 -2;
    }

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

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

    while(1)
    {
        FD_ZERO(&rdfs);
        FD_SET(s, &rdfs);

        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        ret = select(s+1, &rdfs, NULL, NULL, &timeout);
        if(ret < 0)
        {
            perror("select");
            return -4;
        }
        else if(0 == ret)
        {
            continue;
        }
        else
        {
            break;
        }
    }

    nbytes = read(s, &frame, sizeof(frame));
    if(nbytes < 0)
    {
        perror("recv");
        return -5;
    }

    if(nbytes == sizeof(frame))
    {
        *p_id = frame.can_id;
        *p_dlc = frame.can_dlc;
        memcpy(data, frame.data, CAN_MAX_DLEN);
    }
    else
    {
        fprintf(stderr, "recv size not std-frame.\n");
    }

    close(s);

    return 0;
}

int main(int argc, char argv[])
{
    unsigned short id;
    unsigned char dlc;
    unsigned char data[CAN_MAX_DLEN];

    canrecv_stdframe(&id, &dlc, data);

    printf("id=%x, dlc=%d, data=%.02x %.02x %.02x %.02x %.02x %.02x %.02x %.02x\n",
        id, dlc, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
}


これで、標準フレームを1回受信し、表示して終わります。

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

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

1 件のコメント:

  1. Amazonで日本のRaspberry Piを販売している林遠と申しますので、よろしくお願いします。
    プログラミングに関するブログ記事を読ませていただきました。Raspberry Piのレビューブログ記事を書いてもらえますか?
    こちらでは、無料サンプルを提供しています。
    連絡メールはjp02@vertue.cnです までご連絡ください。
    皆様からのご連絡をお待ちしております。ありがとうございました。

    返信削除