在linux上开发CAN接口,但没有实体的CAN设备 (如VMware系统),可以考虑使用虚拟CAN接口来进行数据调试。(思路和虚拟串口一样)
vcan指令安装步骤:(测试平台Ubuntu16.04,每次电脑重启后需重安装,可做成bash脚本方便一键安装)
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
测试vcan是否安装成功,用指令ifconfig -a , 其中带有vcan0的信息就代表安装成功了。(vcan0成了网卡)
...................
vcan0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
安装成功后查看CAN设备,在 /sys/class/net 目录下会发现有vcan0设备 (Linux内核2.6+)
安装can调试工具,sudo install can-utils .
设置CAN参数
1)ip link set vcan0 down (#停止vcan0设备)
2)ip link set vcan0 type can bitrate 50000 loopback off (#设置can总线工作波特率)
3)ip link set vcan0 up (#启动设备,can总线使能)
设置好后,可以查看CAN总线状态:
ip -details link show vcan0
4)测试虚拟can数据收发。分别打开两个终端,分别负责数据接收和发送。
先启动接收指令,它会阻塞等待数据
candump vcan0
在另外终端测试发送can数据
cansend vcan0 123#abcd
此时在接收端会看到van0 123 [2] AB CD ,解析一下收到的数据:van0是设备的名称,后面是can_id 它的范围是0~~0x7ff (Standar Frame Format),中括号里是收到的字节数,后面跟着数据的16进制。
5) 按 Ctrl+c 结束终端测试
======================================================
(SocketCan)程序测试方法:
/*************************************************************************
* File Name: test_can.c
* Author: bnis
* Mail: [email protected]
* Created Time: 2020-02
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
int sock_fd,nbytes;
char buf[20];
struct ifreq ifr;
struct can_frame frame;
struct sockaddr_can addr;
sock_fd = socket(PF_CAN,SOCK_RAW,CAN_RAW);
if( sock_fd < 0){
perror("create can_socket failed! \n");
exit(-1);
}
/*set up can interface*/
strcpy((char *)ifr.ifr_name,"vcan0");//here use virtual CAN to test
printf("can_socket ceate ok, port name = %s\n",ifr.ifr_name);
/*assign can device*/
ioctl(sock_fd,SIOCGIFINDEX, &ifr);
addr.can_family =AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
/*bind can device*/
if(bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))<0 )
{
perror("bind can device failed\n");
close(sock_fd);
exit(-2);
}
/*configure can_id and can data length*/
frame.can_id = 0x10F;
strcpy((char *)frame.data,"hello"); //68.65.6c.6c.6f
frame.can_dlc = strlen(frame.data);
nbytes = write(sock_fd,&frame, sizeof(frame));
if(nbytes <0)
{
perror("CAN_send fail");
}
printf("can_id = %X ,data len = %d ,interface = %s \n",
frame.can_id,frame.can_dlc,ifr.ifr_name);
printf("frame.data = %s \n",frame.data);
printf("ifindex= %d \n",ifr.ifr_ifindex);
//use can-tool command "cansend" to test
printf("-------waiting to receive can data----------\n");
nbytes = read(sock_fd, &frame, sizeof(frame));
if(nbytes>0 )
{
printf("Device:%s ,ID=%#X,DLC= %d,DATA=[%s]\n",
ifr.ifr_name, frame.can_id,frame.can_dlc,frame.data);
}
printf("--------receive done-----------\n");
close(sock_fd);
return 0;
}
/* 关于can_id数据组织
* Controller Area Network Identifier structure
*
* bit 0-28 : CAN identifier (11/29 bit , SFF/EFF)
* bit 29 : error message frame flag (0 = data frame, 1 = error message)
* bit 30 : remote transmission request flag (1 = rtr frame)
* bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
*/
//关于can帧结构体
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
传统的can数据长度最大只能支持8字节,扩展的 can-fd 协议则可支持64字节。
=======================================================
参考文献:
#英伟达TX2平台CAN收发测试
https://www.cnblogs.com/happyamyhope/p/8796844.html
#CAN编程讲解
https://blog.csdn.net/ppdyhappy/article/details/79458458