分享

TX2/Linux下can总线的接收与发送命令和C程序实例_candump命令

 cupid 2023-05-17 发布于广东

使用CAN本人归纳为6个步骤:

0.测试之前最好先下载安装好测试工具can-utils

sudo apt-get install can-utils

1.加载can设备驱动:

  1. sudo modprobe can
  2. sudo modprobe can_raw
  3. sudo modprobe mttcan

2.设置波特率(注意这里不能使能can或者打开can)

  1. sudo ip link set can0 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on
  2. sudo ip link set can1 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on

如果出现了RTNETLINK answers: Device or resource busy 这种情况,则需要使用命令

  1. sudo ip link set down can0
  2. sudo ip link set down can1

来关闭掉;

3.设置为回环模式(因为要测试使用,在不外接can驱动和120欧姆电阻的情况下是可以回环测试的,使用can0设备)

sudo ip link set can0 type can loopback on

如果由外设,可以省略此步骤。

4.开启can设备:

  1. sudo ip link set up can0
  2. sudo ip link set up can1

5.发送和接收:

发送:

cansend can0 123#abcdabcd

cansend是命令,can0是参数,123是ID,#分隔符,abcdabcd是发送数据。

接收:接收需要另外开一个终端

candump can0

candump 是命令,can0是参数,表示哪个设备,这个命令是阻塞型的,会一直等待接收。

6.关闭can设备。

  1. sudo ip link set down can0
  2. sudo ip link set down can1

上面的测试,本人是在tx2上面一会儿就跑通了。但是不满足控制出身的技术人员对于控制的需要,所以需要自己写一个程序来实现接收和发送。使用了实例程序:

两个c文件:1.can_send.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <net/if.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/socket.h>
  8. #include <linux/can.h>
  9. #include <linux/can/raw.h>
  10. int main()
  11. {
  12. int s,nbytes;
  13. struct sockaddr_can addr;
  14. struct ifreq ifr;
  15. struct can_frame frame[2]={{0}};
  16. s=socket(PF_CAN,SOCK_RAW,CAN_RAW);
  17. strcpy(ifr.ifr_name,"can0");
  18. ioctl(s,SIOCGIFINDEX,&ifr);
  19. addr.can_family = AF_CAN;
  20. addr.can_ifindex = ifr.ifr_ifindex;
  21. bind(s,(struct sockaddr*)&addr,sizeof(addr));
  22. setsockopt(s,SOL_CAN_RAW,CAN_RAW_FILTER,NULL,0);
  23. frame[0].can_id = 0x11;
  24. frame[0].can_dlc =1;
  25. frame[0].data[0]= 'Y';
  26. frame[1].can_id = 0x11;//0x33;
  27. frame[1].can_dlc =1;
  28. frame[1].data[0]= 'N';
  29. while(1)
  30. {
  31. nbytes = write(s, &frame[0], sizeof(frame[0]));
  32. printf("nbytes=%d\n",nbytes);
  33. if(nbytes != sizeof(frame[0]))
  34. {
  35. printf("Send Error frame[0]\n!");
  36. break; //发送错误,退出
  37. }
  38. sleep(1);
  39. nbytes = write(s, &frame[1], sizeof(frame[1]));
  40. if(nbytes != sizeof(frame[1]))
  41. {
  42. printf("Send Error frame[1]\n!");
  43. break;
  44. }
  45. sleep(1);
  46. }
  47. close(s);
  48. return 0;
  49. }

2.can_receive.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <net/if.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/socket.h>
  8. #include <linux/can.h>
  9. #include <linux/can/raw.h>
  10. int main()
  11. {
  12. int s, nbytes;
  13. struct sockaddr_can addr;
  14. struct ifreq ifr;
  15. struct can_frame frame;
  16. struct can_filter rfilter[1];
  17. s = socket(PF_CAN, SOCK_RAW, CAN_RAW); //创建套接字
  18. strcpy(ifr.ifr_name, "can0" );
  19. ioctl(s, SIOCGIFINDEX, &ifr); //指定 can0 设备
  20. addr.can_family = AF_CAN;
  21. addr.can_ifindex = ifr.ifr_ifindex;
  22. bind(s, (struct sockaddr *)&addr, sizeof(addr)); //将套接字与 can0 绑定
  23. //定义接收规则,只接收表示符等于 0x11 的报文
  24. rfilter[0].can_id = 0x11;
  25. rfilter[0].can_mask = CAN_SFF_MASK;
  26. //设置过滤规则
  27. setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
  28. while(1)
  29. {
  30. nbytes = read(s, &frame, sizeof(frame));
  31. //接收报文//显示报文
  32. if(nbytes > 0)
  33. {
  34. printf("ID=0x%X DLC=%d data[0]=0x%X\n",frame.can_id,frame.can_dlc,frame.data[0]);
  35. //printf(“ID=0x%X DLC=%d data[0]=0x%X\n”, frame.can_id, frame.can_dlc, frame.data[0]);
  36. }
  37. }
  38. close(s);
  39. return 0;
  40. }

实测也是可以实现发送与接收的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约