使用CAN本人歸納為6個步驟:
0.測試之前最好先下載安裝好測試工具can-utils
sudo apt-get install can-utils
1.加載can設(shè)備驅(qū)動:
- sudo modprobe can
- sudo modprobe can_raw
- sudo modprobe mttcan
2.設(shè)置波特率(注意這里不能使能can或者打開can)
- sudo ip link set can0 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on
- sudo ip link set can1 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on
如果出現(xiàn)了RTNETLINK answers: Device or resource busy 這種情況,則需要使用命令
- sudo ip link set down can0
- sudo ip link set down can1
來關(guān)閉掉;
3.設(shè)置為回環(huán)模式(因為要測試使用,在不外接can驅(qū)動和120歐姆電阻的情況下是可以回環(huán)測試的,使用can0設(shè)備)
sudo ip link set can0 type can loopback on
如果由外設(shè),可以省略此步驟。
4.開啟can設(shè)備:
- sudo ip link set up can0
- sudo ip link set up can1
5.發(fā)送和接收:
發(fā)送:
cansend can0 123#abcdabcd
cansend是命令,can0是參數(shù),123是ID,#分隔符,abcdabcd是發(fā)送數(shù)據(jù)。
接收:接收需要另外開一個終端
candump can0
candump 是命令,can0是參數(shù),表示哪個設(shè)備,這個命令是阻塞型的,會一直等待接收。
6.關(guān)閉can設(shè)備。
- sudo ip link set down can0
- sudo ip link set down can1
上面的測試,本人是在tx2上面一會兒就跑通了。但是不滿足控制出身的技術(shù)人員對于控制的需要,所以需要自己寫一個程序來實現(xiàn)接收和發(fā)送。使用了實例程序:
兩個c文件:1.can_send.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <net/if.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <linux/can.h> #include <linux/can/raw.h> int main() { int s,nbytes; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame[2]={{0}}; s=socket(PF_CAN,SOCK_RAW,CAN_RAW); strcpy(ifr.ifr_name,"can0"); ioctl(s,SIOCGIFINDEX,&ifr); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(s,(struct sockaddr*)&addr,sizeof(addr)); setsockopt(s,SOL_CAN_RAW,CAN_RAW_FILTER,NULL,0); frame[0].can_id = 0x11; frame[0].can_dlc =1; frame[0].data[0]= 'Y'; frame[1].can_id = 0x11;//0x33; frame[1].can_dlc =1; frame[1].data[0]= 'N'; while(1) { nbytes = write(s, &frame[0], sizeof(frame[0])); printf("nbytes=%d\n",nbytes); if(nbytes != sizeof(frame[0])) { printf("Send Error frame[0]\n!"); break; //發(fā)送錯誤,退出 } sleep(1); nbytes = write(s, &frame[1], sizeof(frame[1])); if(nbytes != sizeof(frame[1])) { printf("Send Error frame[1]\n!"); break; } sleep(1); } close(s); return 0; }
2.can_receive.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <net/if.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <linux/can.h>
- #include <linux/can/raw.h>
- int main()
- {
- int s, nbytes;
- struct sockaddr_can addr;
- struct ifreq ifr;
- struct can_frame frame;
- struct can_filter rfilter[1];
- s = socket(PF_CAN, SOCK_RAW, CAN_RAW); //創(chuàng)建套接字
- strcpy(ifr.ifr_name, "can0" );
- ioctl(s, SIOCGIFINDEX, &ifr); //指定 can0 設(shè)備
- addr.can_family = AF_CAN;
- addr.can_ifindex = ifr.ifr_ifindex;
- bind(s, (struct sockaddr *)&addr, sizeof(addr)); //將套接字與 can0 綁定
- //定義接收規(guī)則,只接收表示符等于 0x11 的報文
- rfilter[0].can_id = 0x11;
- rfilter[0].can_mask = CAN_SFF_MASK;
- //設(shè)置過濾規(guī)則
- setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
- while(1)
- {
- nbytes = read(s, &frame, sizeof(frame));
- //接收報文//顯示報文
- if(nbytes > 0)
- {
- printf("ID=0x%X DLC=%d data[0]=0x%X\n",frame.can_id,frame.can_dlc,frame.data[0]);
- //printf(“ID=0x%X DLC=%d data[0]=0x%X\n”, frame.can_id, frame.can_dlc, frame.data[0]);
- }
- }
- close(s);
- return 0;
- }
實測也是可以實現(xiàn)發(fā)送與接收的。