设为首页收藏本站
查看: 564|回复: 0

Remi_Pi瑞米派linux开发板的CAN扩展板学习记录_20240807

[复制链接]

1

主题

0

回帖

7

积分

新手上路

积分
7
EcellentSNEK666 发表于 2024-8-7 23:04:56 | 显示全部楼层 |阅读模式
学习记录
前言:168买了一块瑞米派,因为从事汽车电子行业需要学一下CAN,所以当时为了实操申请了一块瑞米派的CAN扩展版。扩展版是通过SPI通信控制CAN通信从而发送CAN信号。虽然发货很及时,但我的Linux技术有限,在回来的时候CAN已经学会了。后面再拿出来在开发板的Linux系统上实操一下。
扩展版资料需要的在下面链接
2-CH CAN HAT - Waveshare Wiki

截图202408080851368917.jpg

这个扩展版兼容树莓派,看教程是有树莓派的c例程和python例程。瑞米派自带系统也有python3的环境,但c例程需要在ubuntu下交叉编译然后移植到开发板然后跑通。

截图202408080851493386.png
截图202408080851572839.png
硬件连接,通过对比Remi_Pi电路图与扩展版电路图,定义一致,可以直接连接。
截图202408080852077529.png
因为我尝试使用c例程,所以放C的例程代码。
思路1:
1.移植交叉编译器
2.在ubuntu下编译c代码,然后移植到开发板跑例程。但是需要两个扩展版,所以可以使用第一个发,想办法再建立一个终端和账号然后运行收的C例程。可以实现自收自发。
思路2:
可以直接调用现有系统的例程和命令,进行CAN发送。目前走的这一条,但是没法接收数据,可以通过连接CAN盒查看收的ID和数据。目前可以发送。
截图202408080852254514.png
使用linux软件评估文档中的内容,用命令行配置CAN,然后调用系统函数CAN外发。



先把CAN关闭,然后配置为CANFD,然后调用cansend 发送ID为100,数据为11.22.33.44的消息。最后统计CAN0接口的数据,发送16个包,128个字节。证明可以发送。目前手头没有CAN盒,但使用CAN盒必须使用支持CANFD的CAN盒,我使用1610不支持CAN FD 所以下面只放了CAN外发数据的统计内容。

截图202408080852319612.png

后面是例程的源码,也是同样的调用系统函数和发送信息。但需要先移植交叉编译器再ubuntu系统编译后移植再跑程序。

can_receive.c

#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 main()
{
    int ret;
    int s, nbytes;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;

    memset(&frame, 0, sizeof(struct can_frame));

    system("sudo ip link set can0 type can bitrate 100000");
    system("sudo ifconfig can0 up");
    printf("this is a can receive demo\r\n");

    //1.Create socket
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s < 0) {
        perror("socket PF_CAN failed");
        return 1;
    }

    //2.Specify can0 device
    strcpy(ifr.ifr_name, "can0");
    ret = ioctl(s, SIOCGIFINDEX, &ifr);
    if (ret < 0) {
        perror("ioctl failed");
        return 1;
    }

    //3.Bind the socket to can0
    addr.can_family = PF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0) {
        perror("bind failed");
        return 1;
    }

    //4.Define receive rules
    struct can_filter rfilter[1];
    rfilter[0].can_id = 0x123;
    rfilter[0].can_mask = CAN_SFF_MASK;
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

    //5.Receive data and exit
    while(1) {
        nbytes = read(s, &frame, sizeof(frame));
        if(nbytes > 0) {
            printf("can_id = 0x%X\r\ncan_dlc = %d \r\n", frame.can_id, frame.can_dlc);
            int i = 0;
            for(i = 0; i < 8; i++)
                printf("data[%d] = %d\r\n", i, frame.data);
            break;
        }
    }

    //6.Close the socket and can0
    close(s);
    system("sudo ifconfig can0 down");

    return 0;
}


can_send.c

#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 main()
{
    int ret;
    int s, nbytes;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;
    memset(&frame, 0, sizeof(struct can_frame));

    system("sudo ip link set can0 type can bitrate 100000");
    system("sudo ifconfig can0 up");
    printf("this is a can send demo\r\n");

    //1.Create socket
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s < 0) {
        perror("socket PF_CAN failed");
        return 1;
    }

    //2.Specify can0 device
    strcpy(ifr.ifr_name, "can0");
    ret = ioctl(s, SIOCGIFINDEX, &ifr);
    if (ret < 0) {
        perror("ioctl failed");
        return 1;
    }

    //3.Bind the socket to can0
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0) {
        perror("bind failed");
        return 1;
    }

    //4.Disable filtering rules, do not receive packets, only send
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

    //5.Set send data
    frame.can_id = 0x123;
    frame.can_dlc = 8;
    frame.data[0] = 1;
    frame.data[1] = 2;
    frame.data[2] = 3;
    frame.data[3] = 4;
    frame.data[4] = 5;
    frame.data[5] = 6;
    frame.data[6] = 7;
    frame.data[7] = 8;

    printf("can_id  = 0x%X\r\n", frame.can_id);
    printf("can_dlc = %d\r\n", frame.can_dlc);
    int i = 0;
    for(i = 0; i < 8; i++)
        printf("data[%d] = %d\r\n", i, frame.data);

    //6.Send message
    nbytes = write(s, &frame, sizeof(frame));
    if(nbytes != sizeof(frame)) {
        printf("Send Error frame[0]!\r\n");
        system("sudo ifconfig can0 down");
    }

    //7.Close the socket and can0
    close(s);
    system("sudo ifconfig can0 down");
    return 0;
}





截图202408080851323232.jpg
回复

使用道具 举报

您需要登录后才可以回帖 登录

本版积分规则

Archiver|手机版|小黑屋|米尔科技论坛   

GMT+8, 2024-12-21 19:56 , Processed in 0.115273 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表