CAN在通讯中应用比较广泛,尤其是汽车领域;高端MCU跑Linux系统后,会把CAN归为网络设备,像操作网卡芯片一样去配置和激活,在操作上面会稍微复杂一些。
一、CAN测试
1、查看设备 ifconfig -a
[root@Jack Jack]$ifconfig -a
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
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:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:19
can1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
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:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:28
eth0 Link encap:Ethernet HWaddr e0:13:12:16:ba:01
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::e213:12ff:fe16:ba01/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:968 errors:0 dropped:0 overruns:0 frame:0
TX packets:910 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:150759 (147.2 KiB) TX bytes:65359 (63.8 KiB)
Interrupt:25 Base address:0x8000
eth1 Link encap:Ethernet HWaddr e0:13:12:16:ba:02
inet addr:192.168.2.100 Bcast:192.168.2.255 Mask:255.255.255.0
inet6 addr: fe80::e213:12ff:fe16:ba02/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:401 errors:0 dropped:0 overruns:0 frame:0
TX packets:154 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:29424 (28.7 KiB) TX bytes:11100 (10.8 KiB)
Interrupt:33 Base address:0xc000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:461 errors:0 dropped:0 overruns:0 frame:0
TX packets:461 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:41988 (41.0 KiB) TX bytes:41988 (41.0 KiB)
sit0 Link encap:UNSPEC HWaddr 00-00-00-00-66-65-31-36-00-00-00-00-00-00-00-00
NOARP MTU:1480 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:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
2、设置波特率 250K
ip link set can0 type can bitrate 250000
[root@Jack Jack] i p l i n k s e t c a n 0 t y p e c a n b i t r a t e 250000 [ r o o t @ J a c k J a c k ] ip link set can0 type can bitrate 250000 [root@Jack Jack] iplinksetcan0typecanbitrate250000[root@JackJack]
3、查询can设备参数
ip -details link show can0
[root@Jack Jack]$ip -details link show can0
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 250000 sample-point 0.833
tq 333 prop-seg 4 phase-seg1 5 phase-seg2 2 sjw 1
at91_can: tseg1 4…16 tseg2 2…8 sjw 1…4 brp 2…128 brp-inc 1
clock 66000000
4、使能CAN0设备
ifconfig can0 up
5、查询工作状态
[root@Jack Jack]
i
p
−
d
e
t
a
i
l
s
−
s
t
a
t
i
s
t
i
c
s
l
i
n
k
s
h
o
w
c
a
n
02
:
c
a
n
0
:
<
N
O
A
R
P
,
U
P
,
L
O
W
E
R
U
P
,
E
C
H
O
>
m
t
u
16
q
d
i
s
c
p
f
i
f
o
f
a
s
t
s
t
a
t
e
U
N
K
N
O
W
N
m
o
d
e
D
E
F
A
U
L
T
g
r
o
u
p
d
e
f
a
u
l
t
q
l
e
n
10
l
i
n
k
/
c
a
n
p
r
o
m
i
s
c
u
i
t
y
0
c
a
n
s
t
a
t
e
E
R
R
O
R
−
A
C
T
I
V
E
(
b
e
r
r
−
c
o
u
n
t
e
r
t
x
0
r
x
0
)
r
e
s
t
a
r
t
−
m
s
0
b
i
t
r
a
t
e
250000
s
a
m
p
l
e
−
p
o
i
n
t
0.833
t
q
333
p
r
o
p
−
s
e
g
4
p
h
a
s
e
−
s
e
g
15
p
h
a
s
e
−
s
e
g
22
s
j
w
1
a
t
9
1
c
a
n
:
t
s
e
g
14..16
t
s
e
g
22..8
s
j
w
1..4
b
r
p
2..128
b
r
p
−
i
n
c
1
c
l
o
c
k
66000000
r
e
−
s
t
a
r
t
e
d
b
u
s
−
e
r
r
o
r
s
a
r
b
i
t
−
l
o
s
t
e
r
r
o
r
−
w
a
r
n
e
r
r
o
r
−
p
a
s
s
b
u
s
−
o
f
f
000000
R
X
:
b
y
t
e
s
p
a
c
k
e
t
s
e
r
r
o
r
s
d
r
o
p
p
e
d
o
v
e
r
r
u
n
m
c
a
s
t
000000
T
X
:
b
y
t
e
s
p
a
c
k
e
t
s
e
r
r
o
r
s
d
r
o
p
p
e
d
c
a
r
r
i
e
r
c
o
l
l
s
n
s
000000
[
r
o
o
t
@
J
a
c
k
J
a
c
k
]
ip -details -statistics link show can0 2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 bitrate 250000 sample-point 0.833 tq 333 prop-seg 4 phase-seg1 5 phase-seg2 2 sjw 1 at91_can: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 2..128 brp-inc 1 clock 66000000 re-started bus-errors arbit-lost error-warn error-pass bus-off 0 0 0 0 0 0 RX: bytes packets errors dropped overrun mcast 0 0 0 0 0 0 TX: bytes packets errors dropped carrier collsns 0 0 0 0 0 0 [root@Jack Jack]
ip−details−statisticslinkshowcan02:can0:<NOARP,UP,LOWERUP,ECHO>mtu16qdiscpfifofaststateUNKNOWNmodeDEFAULTgroupdefaultqlen10link/canpromiscuity0canstateERROR−ACTIVE(berr−countertx0rx0)restart−ms0bitrate250000sample−point0.833tq333prop−seg4phase−seg15phase−seg22sjw1at91can:tseg14..16tseg22..8sjw1..4brp2..128brp−inc1clock66000000re−startedbus−errorsarbit−losterror−warnerror−passbus−off000000RX:bytespacketserrorsdroppedoverrunmcast000000TX:bytespacketserrorsdroppedcarriercollsns000000[root@JackJack]
二、驱动验证OK后,编写应用程序代码;
1、初始化函数,可设置ID滤波等参数;
int init_can(char* can) {
int sock;
struct sockaddr_can addr;
//struct ifreq ifr;
sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if(sock < 0) {
printf("error\n");
return -1;
}
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, can );
int ret;
ret = ioctl(sock, SIOCGIFINDEX, &ifr); //get index
if(ret && ifr.ifr_ifindex == 0) {
printf("Can't get interface index for can0, code= %d, can0 ifr_ifindex value: %d, name: %s\n", ret, ifr.ifr_ifindex, ifr.ifr_name);
close(sock);
return -1;
}
printf("%s can_ifindex = %x\n",ifr.ifr_name,ifr.ifr_ifindex);
addr.can_ifindex = ifr.ifr_ifindex;
//ioctl(sock,SIOCGIFNAME,&ifr);
//printf("ret = %d can0 can_ifname = %s\n",ret,ifr.ifr_name);
int recv_own_msgs = 0;//set loop back: 1 enable 0 disable
setsockopt(sock, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,&recv_own_msgs, sizeof(recv_own_msgs));
if (bind(sock,(struct sockaddr*)&addr,sizeof(addr))<0) {
printf("bind error\n");
close(sock);
return -1;
}
return sock;
}
2、CAN接收函数
void Can_Read_thread(void psock)
{
int sock = *(int *)psock;
struct can_frame frame;
while(1) {
memset(&frame,0,sizeof(struct can_frame));
read(sock,&frame,sizeof(struct can_frame));
if(frame.can_dlc > 0) {
printf("%s recv: ID=0x%X DLC=%d data[0]=0x%X\n",ifr.ifr_name,frame.can_id,frame.can_dlc, frame.data[0]);
}
}
}
3、CAN发送函数
int Write_Can_Data(int sock,char* str,int len)
{
struct can_frame frame;
int i;
int nbytes = 0;
frame.can_id = 0x0; //can device id
while(len) {
//nbytes = sendto(sock,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,sizeof(addr));
//memset(&buf,0,sizeof(buf));
//sprintf(buf,"%s%d","hello",i);
//strcpy((char *)frame.data,buf);
if(len > sizeof(frame.data)) {
memset(&frame.data,0,sizeof(frame.data));
memcpy(&frame.data,str,sizeof(frame.data));
//printf("%d,(%s)\r\n",sizeof(frame.data),frame.data);
frame.can_dlc = sizeof(frame.data);
str += sizeof(frame.data);
len -= sizeof(frame.data);
}
else {
memset(&frame.data,0,sizeof(frame.data));
memcpy(&frame.data,str,len);
//printf("%d,(%s)\r\n",len,frame.data);
frame.can_dlc = len;
str = NULL;
len = 0;
}
write(sock, &frame, sizeof(struct can_frame));
usleep(100);
}
}
4、主函数编写
int main(int argc ,char** argv)
{
int sock;
int nbytes;
pthread_t canthreadid;
int ret;
char str[4096];
//addr.can_family = AF_CAN;
//addr.can_ifindex = ifr.ifr_ifindex;
//setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
setsockopt(sock,);
//printf(“ifr.ifr_ifindex = %d \r\n”,ifr.ifr_ifindex);
if(argc < 2) {
printf(“Usage: %s (can0/can1)\n”, argv[0]);
return 0;
}
sock = init_can(argv[1]);
if(sock < 0)
{
return 0;
}
ret=pthread_create(&canthreadid,NULL,Can_Read_thread,&sock);
while(1) {
printf("Please Input string to send to %s\n:",argv[1]);
scanf("%s", str);
if(strlen(str)>0)
Write_Can_Data(sock,str,strlen(str));
}
// struct can_frame frame;
// char buf[20];
// frame.can_id = 0x0; //can device id
// int i;
// for(i=0;i<20;i++)
// {
//nbytes = sendto(sock,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,sizeof(addr));
// memset(&buf,0,sizeof(buf));
// sprintf(buf,"%s%d",“hello”,i);
// strcpy((char *)frame.data,buf);
// frame.can_dlc = strlen(frame.data);
// nbytes = write(sock, &frame, sizeof(struct can_frame));
// printf("%d. %ld bytes has been sent\n", i, nbytes);
// sleep(1);
// }
close(sock);
printf(“ok\n”);
return 0;
}
6、外部接上CAN盒调用驱动
./canTest can0
关注微信公众号,回复“ Linux CAN测试”,免费获取源代码;