2018-10-28

MCP2515芯片的使用

树莓派作为大众开源硬件,一些高级功能是需要扩展的,刚刚用到了MCP2515扩展CAN总线,现在总结如下:

前提:使用内核自带的MCP2515驱动

1、打开SPI总线

在raspi-config中使能SPI总线

2、修改内核启动文件

dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25,spimaxfrequency=1000000

然后重启系统

3、例程是基于wiringPi

1、初始化代码如下

int mcp2515_init()
{
    memset(&frame, 0, sizeof(struct can_frame));

    system("sudo ifconfig can0 down");

    delay(10);
    
    system("sudo ip link set can0 type can bitrate 250000");
    system("sudo ifconfig can0 up");
 
    //1.Create socket
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s < 0) {
        perror("socket PF_CAN failed");
        return 1;
    }
    
    //2.Specify can0 device
    strcpy(ifr.ifr_name, "can0");
    ret = ioctl(s, SIOCGIFINDEX, &ifr);
    if (ret < 0) {
        perror("ioctl failed");
        return 1;
    }

    //3.Bind the socket to can0
    addr.can_family = PF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0) {
        perror("bind failed");
        return 1;
    }
    
    //4.Define receive rules
    struct can_filter rfilter[1];
    rfilter[0].can_id = 0x18feca33;
    rfilter[0].can_mask = CAN_SFF_MASK;
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

    return 0;
}

其中比较重要的几点就是波特率的设置,接收滤波器的设置

2、接收滤波器设置

    struct can_filter rfilter[1];
    rfilter[0].can_id = 0x18feca33;
    rfilter[0].can_mask = CAN_SFF_MASK;

经此设置后,MCP2515仅接受扩展ID为0x18feca33的报文

3、发送设置

发送部分的代码摘录如下:

  int mcp2515_write(canframe dataTemp)
{
    canframe frame;
    frame.can_id = CAN_EFF_FLAG|dataTemp.can_id;
    frame.can_dlc = 8;
    for (int i = 0; i < 8; i++)
    {
      frame.data[i]=dataTemp.data[i];
    }   
    nbytes = write(s, &frame, sizeof(frame)); 
    if(nbytes != sizeof(frame)) {
        return 0;
    }
   return 1;
}

CAN_EFF_FLAG表示当前发送扩展帧,无此项时为标准帧

4、接收部分

canframe mcp2515_read()
{
    canframe dataTemp;
 
    for (int i = 0; i < 100; i++)
    {
        nbytes = read(s, &frame, sizeof(frame));
        if(nbytes > 0) {

            dataTemp.can_id=frame.can_id&0x1fffffff;

            for (int i = 0; i < 8; i++)
            {
                dataTemp.data[i]=frame.data[i];
            }
            return dataTemp;
        }
    }
}

接收部分最高位为1时,表示接收的为扩展帧,程序使用的是在线程中查询接收。

你可能感兴趣的:(2018-10-28)