在车辆上, Controller Area Network(CAN)是一种常见的通信协议和设备, 用于在车辆内部的各个电子控制单元之间进行数据传输, CAN允许车辆在不同子系统之间进行快速、可靠的实时通信,以协调车辆的各个功能和系统。
有些自动驾驶公司会采集CAN数据用于模块验证,或存为asc文件, 或存为blf文件,下面介绍一种CAN的编码采集,采集的文件格式为asc
首先需要安装驱动,windows下的安装直接可视化界面安装就行, 这里介绍一下linux下的安装驱动和sdk:
wget --content-disposition "https://www.kvaser.com/downloads-kvaser/?utm_source=software&utm_ean=7330130980754&utm_status=latest"
tar xvzf linuxcan.tar.gz
cd linuxcan
make
sudo make install
sudo make load
wget --content-disposition "https://www.kvaser.com/downloads-kvaser/?utm_source=software&utm_ean=7330130981966&utm_status=latest"
tar xvzf kvlibsdk.tar.gz
cd kvlibsdk
make
make check
sudo make install
在驱动安装完成之后, 需要初始化并打开端口
canInitializeLibrary();
canOpenChannel();
初始化完成之后对端口设置,比如这个将频率设置成2M
canSetBusParamsFd(mHnd, canFD_BITRATE_2M_80P, 0, 0, 0);
最后读取端口接收到的数据即可
CanReadWait()
下面给出一个简单案例接收CAN数据 (来源Kvaser官方案例):
int main(int argc, char *argv[])
{
canHandle hnd;
canStatus stat;
int channel;
struct sigaction sigact;
if (argc != 2) {
printUsageAndExit(argv[0]);
}
{
char *endPtr = NULL;
errno = 0;
channel = strtol(argv[1], &endPtr, 10);
if ((errno != 0) || ((channel == 0) && (endPtr == argv[1]))) {
printUsageAndExit(argv[0]);
}
}
/* Use sighand as our signal handler for SIGALRM */
sigact.sa_flags = SA_SIGINFO | SA_RESTART;
sigemptyset(&sigact.sa_mask);
sigact.sa_sigaction = sighand;
if (sigaction(SIGALRM, &sigact, NULL) != 0) {
perror("sigaction SIGALRM failed");
return -1;
}
/* Use sighand and allow SIGINT to interrupt syscalls */
sigact.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &sigact, NULL) != 0) {
perror("sigaction SIGINT failed");
return -1;
}
printf("Counting CAN messages on channel %d\n", channel);
canInitializeLibrary();
/* Open channel, set parameters and go on bus */
hnd = canOpenChannel(channel,
canOPEN_EXCLUSIVE | canOPEN_REQUIRE_EXTENDED | canOPEN_ACCEPT_VIRTUAL);
if (hnd < 0) {
printf("canOpenChannel %d", channel);
check("", hnd);
return -1;
}
stat = canSetBusParams(hnd, canBITRATE_1M, 0, 0, 0, 0, 0);
check("canSetBusParams", stat);
if (stat != canOK) {
goto ErrorExit;
}
stat = canBusOn(hnd);
check("canBusOn", stat);
if (stat != canOK) {
goto ErrorExit;
}
alarm(ALARM_INTERVAL_IN_S);
do {
long id;
unsigned char msg[8];
unsigned int dlc;
unsigned int flag;
unsigned long time;
stat = canReadWait(hnd, &id, &msg, &dlc, &flag, &time, READ_WAIT_INFINITE);
if (stat == canOK) {
if (flag & canMSG_ERROR_FRAME) {
err++;
} else {
if (flag & canMSG_STD)
std++;
if (flag & canMSG_EXT)
ext++;
if (flag & canMSG_RTR)
rtr++;
if (flag & canMSGERR_OVERRUN)
over++;
}
msgCounter++;
} else {
if (errno == 0) {
check("\ncanReadWait", stat);
} else {
perror("\ncanReadWait error");
}
}
} while (stat == canOK);
sighand(SIGALRM, NULL, NULL);
ErrorExit:
alarm(0);
stat = canBusOff(hnd);
check("canBusOff", stat);
stat = canClose(hnd);
check("canClose", stat);
stat = canUnloadLibrary();
check("canUnloadLibrary", stat);
return 0;
}