CAN 接口测试[通俗易懂]

CAN 接口测试[通俗易懂]CAN测试收发程序can发送测试#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<net/if.h>#include<sys/ioctl.h>#include<sys/socket…

大家好,又见面了,我是你们的朋友全栈君。

CAN 接口测试

一、命令测试

系统下测试会用到candump与cansend

备注:如果没有can命令可以通过编译can-utils获得,can-utils源码:http://sources.buildroot.net/can-utils/
交叉编译:make ARCH=XXXX CC=XXXX-linux-gcc -j4 CFLAGS=-static

测试脚本cantest.sh如下

#!/bin/sh
ifconfig can0 down
ifconfig can1 down
echo cantest recv can0 id
echo cantest send can0 id times data0 data1
echo id -1 means receive all
set -x
/sbin/ip link set can0 type can bitrate 100000
/sbin/ip link set can1 type can bitrate 100000
ifconfig can0 up
ifconfig can1 up
candump can0  &
cansend  can1 123#11223344556677

1.sudo modprobe vcan
加载虚拟can模块
2.sudo ip link add dev vcan0 type vcan
添加vcan0网卡
3.ifconfig -a
可以查到当前can网络 can0 can1,包括收发包数量、是否有错误等等
4.ip link set can0 up type can bitrate 800000
//ip link set can0 type can –help
设置can0的波特率为800kbps,CAN网络波特率最大值为1Mbps
5.ip link set can0 up type can bitrate 800000 loopback on
设置回环模式,自发自收,用于测试是硬件是否正常,loopback不一定支持
6. ip link set can0 down
关闭can0 网络
7.cansend can0 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
发送默认ID为0x1的can标准帧,数据为0x11 22 33 44 55 66 77 88 每次最大8个byte
8.cansend can0 -i 0x800 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 -e
-e 表示扩展帧,CAN_ID最大29bit,标准帧CAN_ID最大11bit
-i表示CAN_ID
9. cansend can0 -i 0x02 0x11 0x12 –loop=20
–loop 表示发送20个包
10.candump can0
接收CAN0数据

二、应用程序测试

1、can发送测试

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

void CANTestMenu(void)
{
    printf("************************************************** \n");
    printf("*  Select CAN bitrate menu \n");
    printf("*  1  5Kbps \n");
    printf("*  2  10Kbps \n");
    printf("*  3  20Kbps \n");
    printf("*  4  50Kbps \n");
    printf("*  5  100Kbps \n");
    printf("*  6  125Kbps \n");
    printf("*  7  250Kbps \n");
    printf("*  8  500Kbps \n");
    printf("*  9  800Kbps \n"); 
    printf("*  10 1000Kbps \n");    
    printf("*  11 exit \n");
    printf("************************************************** \n");

    printf("*  please input CAN bitrate Int Number,press enter end \n");
    printf("************************************************** \n");
}



int CanInit(unsigned int id, unsigned int baud)
{
    int s;
    int ret;
    char dev[8] = {0};
    char cmd[128] = {0};
    struct sockaddr_can addr = {0};
    struct ifreq ifr = {0};

    sprintf(dev, "can%d", id);
    printf("can dev : %s \n", dev);
    
    //关闭can设备
    sprintf(cmd, "ifconfig %s down", dev);
    printf(cmd);printf("\n");
    if(system(cmd) < 0)
    {
        printf("can device shut down failed  \n");
        return -1;
    }

    //设置can设备波特率
    bzero(cmd, sizeof(cmd));
    sprintf(cmd, "/sbin/ip link set %s type can bitrate %d ", dev, baud);
    printf(cmd);printf("\n");
    if(system(cmd) < 0)
    {
        printf("set can device baud rate failed  \n");
        return -1;
    }
    
    //打开can设备
    bzero(cmd, sizeof(cmd));
    sprintf(cmd, "ifconfig %s up", dev);
    printf(cmd);printf("\n");   
    if(system(cmd) < 0)
    {
        printf("can device open failed  \n");
        return -1;
    }

    //创建套接字
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if(s < 0){
        perror("can socket");
        return -1;
    }
    
    strcpy(ifr.ifr_name, "can0" );
    //指定can0 设备
    ret = ioctl(s, SIOCGIFINDEX, &ifr);
    if(ret < 0){
        perror("can ioctl");
        return -1;
    }
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    
    //将套接字与can0 绑定
    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if(ret < 0){
        perror("can bind");
        return -1;
    }

    return s;   
}

int main()
{
    int s, nbytes, n;
    long bitrate;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;

    //CANTestMenu();

    bitrate=100000;
    s = CanInit(0, bitrate);

    if(s < 0){
        printf("CanInit failed \n");
        sleep(1);
        close(s);
        return -1;
    }
    printf("CanInit success\n");

    frame.can_id = 0x123ab|CAN_EFF_FLAG;
    frame.can_dlc = 8;

    frame.data[0] = 0x11;
    frame.data[1] = 0x22;
    frame.data[2] = 0x33;
    frame.data[3] = 0xaa;
    frame.data[4] = 0xbb;
    frame.data[5] = 0xcc;
    frame.data[6] = 0xdd;
    frame.data[7] = 0xee;
    //禁用过滤规则,本进程不接收报文,只负责发送
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);    
    
    while(1)
    {
        nbytes = write(s, &frame, sizeof(frame)); //发送frame
        if(nbytes != sizeof(frame))
        {
            printf("Send Error frame\n!");
//            break; //发送错误,退出
        }
        else
        {
            printf("Send msg success!\n");
        }
        usleep(10000);
    }
    close(s);
    return 0;
}

2、can接收测试

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>


int CanInit(unsigned int id, unsigned int baud)
{
    int s;
    int ret;
    char dev[8] = {0};
    char cmd[128] = {0};
    struct sockaddr_can addr = {0};
    struct ifreq ifr = {0};

    sprintf(dev, "can%d", id);
    printf("can dev : %s \n", dev);
    
    //关闭can设备
    sprintf(cmd, "ifconfig %s down", dev);
    printf(cmd);printf("\n");
    if(system(cmd) < 0)
    {
        printf("can device shut down failed  \n");
        return -1;
    }
    
    //设置can设备波特率
    bzero(cmd, sizeof(cmd));
    sprintf(cmd, "ip link set %s type can bitrate %d ", dev, baud);
    printf(cmd);printf("\n");
    if(system(cmd) < 0)
    {
        printf("set can device baud rate failed  \n");
        return -1;
    }
    
    //打开can设备
    bzero(cmd, sizeof(cmd));
    sprintf(cmd, "ifconfig %s up", dev);
    printf(cmd);printf("\n");   
    if(system(cmd) < 0)
    {
        printf("can device open failed  \n");
        return -1;
    }
    
    //创建套接字
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if(s < 0){
        perror("can socket");
        return -1;
    }
    
    strcpy(ifr.ifr_name, "can0" );
    //指定can0 设备
    ret = ioctl(s, SIOCGIFINDEX, &ifr);
    if(ret < 0){
        perror("can ioctl");
        return -1;
    }
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    
    //将套接字与can0 绑定
    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if(ret < 0){
        perror("can bind");
        return -1;
    }

    return s;
}

int main()
{
    int s, nbytes;
    struct can_frame frame;
    struct can_filter rfilter[1];
    
    s = CanInit(0, 100000);
    //定义接收规则,只接收表示符等于0x11 的报文
    rfilter[0].can_id = 0x11;
    rfilter[0].can_mask = CAN_SFF_MASK;
    //设置过滤规则
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
    
    while(1)
    {
        nbytes = read(s, &frame, sizeof(frame)); //接收报文
        //显示报文
        if(nbytes > 0)
        {
            printf("ID=0x%x, DLC=%d, data[0]=0x%x \n", frame.can_id, frame.can_dlc, frame.data[0]);
        }
    }
    close(s);
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/147680.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 磁盘阵列恢复方法以及注意事项

    磁盘阵列恢复方法以及注意事项想要弄清楚磁盘阵列恢复,首先就得知道什么是磁盘阵列,磁盘阵列多用于存储服务器,数据服务器等企业级大数据存储领域,磁盘阵列是把多块独立的物理硬盘按不同方式组合起来形成一个逻辑硬盘,当磁盘瘫痪或硬件损坏后,为了恢复存储在阵列平台的数据被称之为磁盘阵列数据恢复,而磁盘阵列能够提供比单个硬盘有着更高的性能和提供数据冗余的技术。  对于做数据恢复人员来讲,最怕的是什么,那就是在客户发现数据丢失后,没有停

    2022年4月29日
    91
  • java是值传递还是引用传递 知乎_按值调用和按引用调用

    java是值传递还是引用传递 知乎_按值调用和按引用调用最近整理面试题,整理到值传递、引用传递,到网上搜了一圈,争议很大。带着一脸蒙圈,线上线下查了好多资料。最终有所收获,所以分享给大家,希望能对你有所帮助。首先说下我的感受,这个题目出的很好,但是在Java中这个题目是有问题的(在下面我会解释)。并且,有很多结论是Java中只有值传递。我认为这样说不够严谨。当然如果针对Java语言本身来讲,Java中只有值传递,没有…

    2025年8月14日
    5
  • random函数的用法

    random函数的用法用法:1、random.random()随机生成(0,1)之间的浮点数2、random.randint(上限,下限)随机生成在范围之内的整数,两个参数分别表示上限和下限3、random.randrange(,,)在指定范围内,按指定基数递增的集合中获得一个随机数,有三个参数,前两个参数代表范围上限和下限,第三个参数是递增增量,不包括下限,包括上限使用方式如下:random.r…

    2022年6月12日
    57
  • Ubuntu18.04的网络配置

    Ubuntu18.04的网络配置1、网络配置1首先打开虚拟网络编辑器进行配置,会加载几秒钟2点击更改设置1.3选择添加网络,添加一个Vment0,并设置为桥接模式,桥接到处设置为自动即可,如下图所示注意:这里有可能会出现问题:无法将网络更改为桥接状态,没有未桥接的主机网络适配器,解决办法请查看我的另外一章博客:https://blog.csdn.net/weixin_42108484/arti…

    2022年6月4日
    35
  • 检测网络接口

    检测网络接口

    2021年12月30日
    43
  • Java static(三) – 静态代码块

    Java static(三) – 静态代码块静态代码块static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内JVM加载类时会执行这些静态代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们每个静态代码块只会被执行一次实例说明//父类publicclassParentStatic{privatestaticStringpstr=”父类静态变量”;static{System.o.

    2022年7月16日
    20

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号