首页 资讯 应用 高压 设计 行业 低压 电路图 关于

通信网络

旗下栏目: 电力电子 通信网络 RFID LED/LCD

linux socket can程序cantool

通信网络 | 发布时间:2018-02-27 | 人气: | #评论# | 本文关键字:CAN,linux
摘要:最近写了个自认为不错的基于linux socket can程序,主要功能: 程序具备全部CAN功能,包括CAN标准帧/扩展帧接收与发送、CAN总线错误判断、环回等功能 适用基于LINUX SOCKET机制实现的CAN接口,可用

最近写了个自认为不错的基于linux socket can程序,主要功能:

  1. 程序具备全部CAN功能,包括CAN标准帧/扩展帧接收与发送、CAN总线错误判断、环回等功能

  2. 适用基于LINUX SOCKET机制实现的CAN接口,可用于嵌入式LINUX的CAN测试

  3. 程序采用标准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 组合键结束程序运行

部分源码w plain copy

  1. int main(int argc, char **argv)  

  2. {  

  3.     S_CanFrame sendframe, recvframe;  

  4.     byte *psendframe = (byte *)&sendframe;  

  5.     byte *precvframe = (byte *)&recvframe;  

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

  7.     const int can_frame_len = sizeof(S_CanFrame);   

  8.   

  9.     pid_t pid = -1;  

  10.     int   status;  

  11.   

  12.     int  ret = 0;  

  13.     char buf[128] = {0};  

  14.     bool carry_bit = false;// 进位标志  

  15.   

  16.     int segment_id;//id for shared memo  

  17.   

  18.   

  19.     if (parse_options(argc, argv))  

  20.     {  

  21.         usage();    return  0;  

  22.     }  

  23.   

  24.     if (!find_can(port))  

  25.     {  

  26.         sprintf(buf, "\n\t错误:CAN%d设备不存在\n\n", port + 1);  

  27.         panic(buf);  

  28.         return  -1;  

  29.     }  

  30.   

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

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

  33.     open_can(port, bitrate);  

  34.   

  35.     send_socket_fd = socket_connect(port);  

  36.     recv_socket_fd = socket_connect(port);  

  37.     //printf("send_socket_fd = %d, recv_socket_fd = %d\n", send_socket_fd, recv_socket_fd);  

  38.     if (send_socket_fd < 0 || send_socket_fd < 0)  

  39.     {  

  40.         disconnect(&send_socket_fd);  

  41.         disconnect(&recv_socket_fd);  

  42.         panic("\n\t打开socket can错误\n\n");  

  43.         return  -1;  

  44.     }  

  45.     set_can_filter();  

  46.     set_can_loopback(send_socket_fd, lp);  

  47.   

  48.     printf_head();  

  49.   

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

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

  52.   

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

  54.     {  

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

  56.     }   

  57.     else  

  58.     {  

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

  60.     }  

  61.     sendframe.can_dlc = dlc;  

  62.     memcpy(sendframe.data, send_frame_data, dlc);  

  63.   

  64.       

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

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

  67.     if (pframeno == NULL)  

  68.     {  

  69.         panic("\n\t创建共享内存失败\n\n");  

  70.         return  -1;  

  71.     }  

  72.     *pframeno = 1;  

  73.   

  74.     run = true;  

  75.   

  76.     pid = fork();  

  77.     if(pid == -1)   

  78.     {   

  79.         panic("\n\t创建进程失败\n\n");  

  80.         return  -1;  

  81.     }  

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

  83.     {  

  84.         while (run && (send_frame_times > 0))  

  85.         {  

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

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

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

  89.                 ret > 0 ? true : false,   

  90.                 true);  

  91.             delay_ms(send_frame_freq_ms);  

  92.   

  93.             if (send_frame_id_inc_en)  

  94.             {  

  95.                 sendframe.can_id++;  

  96.                 if (extended_frame)  

  97.                 {  

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

  99.                 }   

  100.                 else  

  101.                 {  

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

  103.                 }  

  104.             }  

  105.   

  106.             if (send_frame_data_inc_en && dlc > 0)  

  107.             {  

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

  109.                 {  

  110.                     carry_bit = true;// 发生进位  

  111.                 }  

  112.                 psend_data->s.dl++;  

  113.   

  114.                 if (dlc <= 4)  

  115.                 {  

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

  117.                     {  

  118.                         psend_data->s.dl = 0;  

  119.                     }  

  120.                 }  

  121.                 else if (dlc <= 8)  

  122.                 {  

  123.                     if (carry_bit)  

  124.                     {  

  125.                         psend_data->s.dh++;  

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

  127.                         {  

  128.                             psend_data->s.dh = 0;  

  129.                         }  

  130.   

  131.                         carry_bit = false;  

  132.                     }  

  133.                 }  

  134.             }  

  135.   

  136.             send_frame_times--;  

  137.         }  

  138.   

  139.         exit(0);  

  140.     }  

  141.     else // 父进程,接收CAN帧  

  142.     {  

  143.         install_sig();  

  144.   

  145.         while (run)  

  146.         {  

  147.             memset(precvframe, 0x00, can_frame_len);  

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

  149.             if (ret > 0)  

  150.             {  

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

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

  153.                     true,   

  154.                     false);  

  155.             }  

  156.         }  

  157.   

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

  159.         {  

  160.             delay_ms(10);  

  161.         }  

  162.     }  

  163.   

  164.     disconnect(&send_socket_fd);  

  165.     disconnect(&recv_socket_fd);  

  166.   

  167.     shmdt(pframeno);// detach memo  

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

  169.   

  170.     return  0;  

  171. }  

使用示例
20151120172556777.png


责任编辑:网络

热门文章

首页 | 电气资讯 | 应用技术 | 高压电器 | 电气设计 | 行业应用 | 低压电器 | 电路图 | 关于我们 | 版权声明

Copyright 2017-2018 电气自动化网 版权所有 辽ICP备17010593号-1

电脑版 | 移动版 原创声明:本站大部分内容为原创,转载请注明电气自动化网转载;部分内容来源网络,如侵犯您的权益请发送邮件到[email protected]联系我们删除。