ARM40-A5D27应用程序——CAN总线应用程序示例

ARM40-A5D27应用程序——CAN总线应用程序示例

 本文为CAN总线应用程序示例,测试板为ARM40-A5D27.

一、在shell中测试

 把can0的TX与CAN1的TX连接,CAN0的RX和CAN1的RX连接,然后:

# ifconfig can0 down
//配置can0的波特率为250Kbps
# ip link set can0 type can bitrate 250000
# ifconfig can0 up

# ifconfig can1 down
//配置can1的波特率为250Kbps
# ip link set can1 type can bitrate 250000
# ifconfig can1 up

# candump can1 &								// 将CAN1设置为接收(后台接收)
# cansend can0 5A1#11.2233.44556677.88		// CAN0发数据

二、CAN总线发送/接收C代码

 CAN总线发送,文件名为 test_canrecv.c,代码见本文附录(1)。
 CAN总线接收,文件名为 test_cansend.c,代码见本文附录(2)。

三、交叉编译

arm-linux-gnueabihf-gcc -o test_canrecv test_canrecv.c 
arm-linux-gnueabihf-gcc -o test_cansend test_cansend.c 

四、执行程序

 将ARM40-A5D27的CAN总线连接到PC(周立功USB CAN盒子),设置PC端USBCAN波特率为250k.
 配置如下:

# ifconfig can0 down
//配置can0的波特率为250Kbps
# ip link set can0 type can bitrate 250000
# ifconfig can0 up

4.1、CAN总线接收测试:

//在PC端周立功USB CAN上发送数据,ARM40-A5D27上可以接收到数据
# ./test_canrecv

在这里插入图片描述
在这里插入图片描述### 4.2、CAN总线发送测试:

//在ARM40-A5D27上发送数据,在PC端周立功USB CAN上可以接收到数据
# ./test_cansend

在这里插入图片描述
在这里插入图片描述

参考文章:

http://lxr.linux.no/linux+v2.6.34/Documentation/networking/can.txt
Low Level CAN Framework Application Programmers Interface
http://www.emtronix.com/article/article2013603.html
https://blog.csdn.net/jirryzhang/article/details/79417986
http://velep.com/archives/1181.html
http://blog.chinaunix.net/uid-13889805-id-3072479.html
https://github.com/linux-can/can-utils
荟聚计划:共商 共建 共享 Grant

附:

(1)test_canrecv.c 的代码

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

int main( int argc,char* argv[] )
{
        int i, ret;
        int nbytes;
        int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
        char *interface = "can0";

        int can_fd = -1;
        struct sockaddr_can addr;
        struct ifreq ifr;
        struct can_frame frame_rev;

        printf("SocketCAN Test V1.0\n");

        can_fd = socket(family, type, proto);                // 创建SocketCAN 套接字
        printf("SOCK_RAW can sockfd:%d\n", can_fd);
        if( can_fd < 0 )
        {
                perror("socket");
                return can_fd;
        }

        int loopback = 0;         // 0 = disabled, 1 = enabled (default)
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

        strcpy(ifr.ifr_name, interface);        // 指定 can0 设备 strcpy(ifr.ifr_name, "can0" );
        ret = ioctl(can_fd, SIOCGIFINDEX, &ifr);        // 指定 can0 设备
        if(ret) {
                perror("ioctl:interface");
                goto abort;
        }

        addr.can_family = family;
        addr.can_ifindex = ifr.ifr_ifindex;
        ret = bind(can_fd, (struct sockaddr *)&addr, sizeof(addr));        // 将套接字与 can0 绑定
        if (ret)        {
                perror("bind\n");
                goto abort;
        }

        // 设置过滤规则,只接收表示符等于 0x123 的报文,如果没有这段,则接受所有报文
        struct can_filter rfilter;
        rfilter.can_id = 0x123;
        rfilter.can_mask = CAN_SFF_MASK;     // #define CAN_SFF_MASK 0x000007FFU
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));        //设置过滤规则
/*
在极端情况下,如果应用程序不需要接收报文,可以禁用过滤规则。这样的话,原始套接字就会忽略所有接收到的报文。在这种仅仅发送数据的应用中,可以在内核中省略接收队列,以此减少 CPU 资源的消耗。禁用方法如下:
setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);     //禁用过滤规则
*/
        memset(&frame_rev,0x0,sizeof(frame_rev));
        while(1) {
                nbytes = read(can_fd, &frame_rev, sizeof(frame_rev));        //接收报文
                if(nbytes < 0){
                        perror("read");
                        goto abort;
                }

                if(nbytes < sizeof(struct can_frame)){
                        printf("read:incomplete can frame\n");
                        goto abort;
                }

                printf("ID=0x%X,DLC=%d",frame_rev.can_id,frame_rev.can_dlc);        //显示报文
                for(i=0; i<frame_rev.can_dlc; i++)
                        printf(",data[%d]=%x", i,frame_rev.data[i]);
                printf("\n");

                memset(&frame_rev,0x0,sizeof(frame_rev));
        }
        close(can_fd);
        return 0;

abort:
        close(can_fd);
        return ret;
}

(2)test_cansend.c 的代码

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


int main( int argc,char* argv[] )
{
        int i, ret;
        int nbytes;
        int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
        char *interface = "can0";

        int can_fd = -1;
        struct sockaddr_can addr;
        struct ifreq ifr;
        struct can_frame frame_send;


        printf("SocketCAN Test V1.0\n");

        can_fd = socket(family, type, proto);                // 创建SocketCAN 套接字
        printf("SOCK_RAW can sockfd:%d\n", can_fd);
        if( can_fd < 0 )
        {
                perror("socket");
                return can_fd;
        }

        int loopback = 0; // 0 = disabled, 1 = enabled (default)
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

        strcpy(ifr.ifr_name, interface);        // 指定 can0 设备 strcpy(ifr.ifr_name, "can0" );
        ret = ioctl(can_fd, SIOCGIFINDEX, &ifr);        // 指定 can0 设备
        if(ret)
        {
                perror("ioctl:SIOCGIFINDEX");
                goto abort;
        }

        addr.can_family = family;
        addr.can_ifindex = ifr.ifr_ifindex;
        ret = bind(can_fd, (struct sockaddr *)&addr, sizeof(addr));        // 将套接字与 can0 绑定
        if(ret) {
                perror("bind\n");
                goto abort;
        }

/*    // 发送一个字节的情况
        frame_send.can_id = 0x00;
        frame_send.can_dlc = 1;
        frame_send.data[0] = 'Y';
*/
        frame_send.can_id = 0x123;
        frame_send.can_dlc = 8;        // 发送8个字节,一次最多发8个字节
        for(i=0; i<8; ++i)      {    
                frame_send.data[i] = i;
        }
        //strncpy(frame_send.data,"12345678",8);

        nbytes = write(can_fd, &frame_send, sizeof(frame_send));        //发送
        if(nbytes <0 ){
                perror("write");
                goto abort;
        }

        // 打印发送的字节
        printf("write %d bytes frame:can_id=0x%x,can_dlc=%d\n", i,frame_send.can_id,frame_send.can_dlc);
        for(i=0; i<frame_send.can_dlc; i++)
                        printf(",data[%d]=%x", i,frame_send.data[i]);
        printf("\n");

        close(can_fd);
        return 0;

abort:
        close(can_fd);
        return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值