转自:http://velep.com/archives/1177.html最近写了个自认为不错的基于linux socket can程序,主要功能:
- 程序具备全部CAN功能,包括CAN标准帧/扩展帧接收与发送、CAN总线错误判断、环回等功能
- 适用基于LINUX SOCKET机制实现的CAN接口,可用于嵌入式LINUX的CAN测试
- 程序采用标准LINUX命令行参数选项形式,接受用户参数
现把源码进行分享
功能介绍SOCKET CAN工具程序 – Ver1.0 Build Nov 20 2015, COPYRIGHT (C) 2015 reille @ http://velep.com/介绍:
本SOCKET CAN程序具备全部CAN功能,包括CAN标准帧/扩展帧接收与发送、CAN总线错误判断、环回等功能
适用基于LINUX SOCKET机制实现的CAN接口,可用于嵌入式LINUX中的CAN测试程序
程序采用标准LINUX命令行参数选项形式,接受用户参数用法: ./cantool [选项]…选项:
-p, –port=CAN接口号 指定CAN接口号,从1开始, 默认为 1(即CAN1接口)
-b, –baud=波特率 指定CAN通讯波特率,单位Kbps,默认为 250 Kbps
可用波特率:5,10,20,40,50,80,100,125,200,250,400,500,666,800,1000-i, –frame-id=帧ID 指定CAN发送帧ID(Hex格式), 默认为1801F456
-d, –data=数据 指定CAN发送帧数据, 默认为:00 01 FF FF FF FF FF FF,字节数据间以空格隔开
-f, –freq=间隔 指定CAN帧发送间隔,单位ms, 默认为250ms, 最小值为1ms
-t, –times=次数 指定CAN帧发送次数, 默认为0次
-s, 指定CAN发送帧为标准帧, 默认为发送扩展帧
-I, 帧ID每发送一帧递增, 默认不递增
-g, 发送数据每发送一帧递增, 默认不递增
-l, 发送数据时本地环回, 默认不环回–help 显示此帮助信息并退出注意,以下CAN帧ID作为系统使用:
0x00000001 – TX timeout (by netdevice driver)
0x00000002 – lost arbitration / data[0]
0x00000004 – controller problems / data[1]
0x00000008 – protocol violations / data[2..3]
0x00000010 – transceiver status / data[4]
0x00000020 – received no ACK on transmission
0x00000040 – bus off
0x00000080 – bus error (may flood!)
0x00000100 – controller restarted使用 Ctrl^C 组合键结束程序运行
部分源码001
int
main(
int
argc,
char
**argv)
002
{
003
S_CanFrame sendframe, recvframe;
004
byte *psendframe = (byte *)&sendframe;
005
byte *precvframe = (byte *)&recvframe;
006
u_canframe_data_t *psend_data = (u_canframe_data_t *)sendframe.data;
007
const
int
can_frame_len =
sizeof
(S_CanFrame);
008
009
pid_t pid = -1;
010
int
status;
011
012
int
ret = 0;
013
char
buf[128] = {0};
014
bool
carry_bit =
false
;
015
016
int
segment_id;
017
018
019
if
(parse_options(argc, argv))
020
{
021
usage();
return
0;
022
}
023
024
if
(!find_can(port))
025
{
026
sprintf
(buf,
"
错误:CAN%d设备不存在
"
, port + 1);
027
panic(buf);
028
return
-1;
029
}
030
031
close_can(port);
032
set_bitrate(port, bitrate);
033
open_can(port, bitrate);
034
035
send_socket_fd = socket_connect(port);
036
recv_socket_fd = socket_connect(port);
037
038
if
(send_socket_fd < 0 || send_socket_fd < 0)
039
{
040
disconnect(&send_socket_fd);
041
disconnect(&recv_socket_fd);
042
panic(
"
打开socket can错误
"
);
043
return
-1;
044
}
045
set_can_filter();
046
set_can_loopback(send_socket_fd, lp);
047
048
printf_head();
049
050
memset
(&sendframe, 0x00,
sizeof
(sendframe));
051
memset
(&recvframe, 0x00,
sizeof
(recvframe));
052
053
if
(extended_frame)
054
{
055
sendframe.can_id = (send_frame_id & CAN_EFF_MASK) | CAN_EFF_FLAG;
056
}
057
else
058
{
059
sendframe.can_id = (send_frame_id & CAN_SFF_MASK);
060
}
061
sendframe.can_dlc = dlc;
062
memcpy
(sendframe.data, send_frame_data, dlc);
063