一个利用CAN实现车辆控制的简单模板

整理一下研究生第一年学到的东西,因为研究方向是和无人车相关,最先学习的就是CAN总线的相关知识了,这里简单地po一个笔者利用C/C++写的一个CAN的使用模板。

1. CAN简单了解

CAN的全称是controller area network是一种车内常用的通信协议,网络的设备直接互联通信。[1]基本上,现在很多车都是使用CAN协议作为车内ECU与各个模块之间的通信手段。这些协议的具体格式:例如它们的时间间隔、帧的每一位是什么含义,发送方和接收方是谁、怎样解读等等,各个车厂各有不同,还没有形成一个统一的标准。而且这些协议车厂不会轻易公开,否则非常容易被人直接控制车辆或者获取车辆的行驶数据。

对于我们来说,直接利用CAN协议进行改造是一件最为轻松的事情,因为我们只需要拿到CAN的协议内容,再利用CAN分析仪和简单电路修改,就可以选择屏蔽掉车内原来的CAN的线路,转而使用我们通过代码发出的指令到各个执行部分,例如ESP、ACC等等。

1.1. CAN协议的结构

这一部分,可以参考http://www.cnblogs.com/pejoicen/p/3986587.html 这篇文章,讲的非常详细,这里笔者就简单地概括了一下:
分为数据帧、远程帧、错误帧、过载帧和帧间隔。其中我们一般使用的都是数据帧。一个数据帧包括了帧起始、仲裁段、控制段、数据段、CRC段、ACK段、帧结束这几个部分,具体的命令含义都是集中在数据段,传输的数据量是8个Byte(64个bit)。
CAN分析仪如下图所示,一般来说是USB转CAN,一台CAN分析仪可以插两个channel。

2. 使用

配套使用的在ubuntu或者树莓派下面需要有libcontrolcan.so,通常在联系卖家的时候可以让其针对你的工控机或者其他控制设备的OS进行发货,得到之后需要将.so放在目录下,能够链接到。

3. 样例模板

class Control {
private:
    /* can structure */
    VCI_CAN_OBJ vco_receive[64];
    VCI_CAN_OBJ vco_send[8];
    VCI_INIT_CONFIG vic_1;
    int nDeviceType;
    int nDeviceInd;
    int nCANInd_1;
    int nCANInd_2;

public:
    Control();
    ~Control();
    /* can device */
    int StartDevice();
    int CloseDevice();

public:
    // functions you need to implement
}
#include "Control.h"

/**
 * @func Control::Control()
 * @brief Default constructor of class Control
 * @details Set the can sturcture information such as can index.
 */
Control::Control() {
    nDeviceType = 4;
    nDeviceInd = 0;
    nCANInd_1 = 0;
    nCANInd_2 = 1;
}


/**
 * @func Control::~Control()
 * @brief Default destructor of class Control
 * @details Close can device.
 */
Control::~Control() {
    // implements
}

int Control::StartDevice() {
    int dwRelOpenDevice;
    int dwRelVCI_InitCAN;
    nDeviceType = 4;
    nDeviceInd = 0;
    nCANInd_1 = 0;
    nCANInd_2 = 1;

    dwRelOpenDevice = VCI_OpenDevice(nDeviceType, nDeviceInd, 0);
    if (dwRelOpenDevice != 1) {
        printf("VCI_OpenDevice fail!\n");
        return -1;
    }

    /*初始 CAN*/
    vic_1.AccCode = 0x80000008;
    vic_1.AccMask = 0xFFFFFFFF;
    vic_1.Filter = 1;
    vic_1.Timing0 = 0x00;
    vic_1.Timing1 = 0x1C;
    vic_1.Mode = 0;
    dwRelVCI_InitCAN = VCI_InitCAN(nDeviceType, nDeviceInd, nCANInd_1, &vic_1);
    if (dwRelVCI_InitCAN != 1) {
        printf("dwRelVCI_InitCAN fail!\n");
        return -1;
    }
    if (VCI_StartCAN(nDeviceType, nDeviceInd, nCANInd_1) != 1) {
        printf("VCI_StartCAN 1 fail!\n");
        return -1;
    }
    VCI_ClearBuffer(nDeviceType, nDeviceInd, nCANInd_1);
    return 1;
}


int Control::CloseDevice() {
    int dwRel;
    dwRel = VCI_CloseDevice(nDeviceType, nDeviceInd);
    if (dwRel != 1) {
        printf("Can Close Errors!\n");
        return -1;
    }
    return 1;
}

4. 参考

[1]https://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%99%A8%E5%8D%80%E5%9F%9F%E7%B6%B2%E8%B7%AF
[2]http://www.cnblogs.com/pejoicen/p/3986587.html

你可能感兴趣的:(嵌入式开发,智能驾驶,CAN,c-c++)