linux socket版本 can,linux socket can程序cantool

最近写了个自认为不错的基于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 组合键结束程序运行

部分源码

int main(int argc, char **argv)

{

S_CanFrame sendframe, recvframe;

byte *psendframe = (byte *)&sendframe;

byte *precvframe = (byte *)&recvframe;

u_canframe_data_t *psend_data = (u_canframe_data_t *)sendframe.data;

const int can_frame_len = sizeof(S_CanFrame);

pid_t pid = -1;

int status;

int ret = 0;

char buf[128] = {0};

bool carry_bit = false;// 进位标志

int segment_id;//id for shared memo

if (parse_options(argc, argv))

{

usage(); return 0;

}

if (!find_can(port))

{

sprintf(buf, "

错误:CAN%d设备不存在

", port + 1);

panic(buf);

return -1;

}

close_can(port);// 必须先关闭CAN,才能成功设置CAN波特率

set_bitrate(port, bitrate);// 操作CAN之前,先要设置波特率

open_can(port, bitrate);

send_socket_fd = socket_connect(port);

recv_socket_fd = socket_connect(port);

//printf("send_socket_fd = %d, recv_socket_fd = %d

", send_socket_fd, recv_socket_fd);

if (send_socket_fd < 0 || send_socket_fd < 0)

{

disconnect(&send_socket_fd);

disconnect(&recv_socket_fd);

panic("

打开socket can错误

");

return -1;

}

set_can_filter();

set_can_loopback(send_socket_fd, lp);

printf_head();

memset(&sendframe, 0x00, sizeof(sendframe));

memset(&recvframe, 0x00, sizeof(recvframe));

if (extended_frame) // 指定发送帧类型:扩展帧或标准帧

{

sendframe.can_id = (send_frame_id & CAN_EFF_MASK) | CAN_EFF_FLAG;

}

else

{

sendframe.can_id = (send_frame_id & CAN_SFF_MASK);

}

sendframe.can_dlc = dlc;

memcpy(sendframe.data, send_frame_data, dlc);

segment_id = shmget(IPC_PRIVATE, sizeof(int), S_IRUSR | S_IWUSR);// allocate memo

pframeno = (int *)shmat(segment_id, NULL, 0);// attach the memo

if (pframeno == NULL)

{

panic("

创建共享内存失败

");

return -1;

}

*pframeno = 1;

run = true;

pid = fork();

if(pid == -1)

{

panic("

创建进程失败

");

return -1;

}

else if(pid == 0) // 子进程,用于发送CAN帧

{

while (run && (send_frame_times > 0))

{

ret = send_frame(send_socket_fd, (char *)&sendframe, sizeof(sendframe));

printf_frame(sendframe.can_id & CAN_EFF_MASK, sendframe.data, sendframe.can_dlc,

((sendframe.can_id & CAN_EFF_FLAG) ? true : false),

ret > 0 ? true : false,

true);

delay_ms(send_frame_freq_ms);

if (send_frame_id_inc_en)

{

sendframe.can_id++;

if (extended_frame)

{

sendframe.can_id = (sendframe.can_id & CAN_EFF_MASK) | CAN_EFF_FLAG;

}

else

{

sendframe.can_id = (sendframe.can_id & CAN_SFF_MASK);

}

}

if (send_frame_data_inc_en && dlc > 0)

{

if (dlc > 4 && psend_data->s.dl == ((__u32)0xFFFFFFFF))

{

carry_bit = true;// 发生进位

}

psend_data->s.dl++;

if (dlc <= 4)

{

if (psend_data->s.dl >= (1 << (dlc * 8)))

{

psend_data->s.dl = 0;

}

}

else if (dlc <= 8)

{

if (carry_bit)

{

psend_data->s.dh++;

if (psend_data->s.dh >= (1 << ((dlc - 4) * 8)))

{

psend_data->s.dh = 0;

}

carry_bit = false;

}

}

}

send_frame_times--;

}

exit(0);

}

else // 父进程,接收CAN帧

{

install_sig();

while (run)

{

memset(precvframe, 0x00, can_frame_len);

ret = recv_frame(recv_socket_fd, precvframe, can_frame_len, 5 * 1000);

if (ret > 0)

{

printf_frame(recvframe.can_id & CAN_EFF_MASK, recvframe.data, recvframe.can_dlc,

((recvframe.can_id & CAN_EFF_FLAG) ? true : false),

true,

false);

}

}

while(((pid = wait(&status)) == -1) && (errno == EINTR))

{

delay_ms(10);

}

}

disconnect(&send_socket_fd);

disconnect(&recv_socket_fd);

shmdt(pframeno);// detach memo

shmctl(segment_id, IPC_RMID, NULL);// remove

return 0;

}使用示例

3f288ee285423cc6e29fa526842ca321.png

程序源码

下载地址:linux socket can程序cantool

如果觉得好用,记得给个好评!

» 本文地址: http://velep.com/archives/1177.html

» 文章出处: reille博客—http://velep.com ,

如果没有特别声明,文章均为reille博客原创作品

» 郑重声明: 原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值