CAN卡SOCKET接口编程头文件

#include <iostream>
#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>
#include <thread>

CAN和FD模式使用的头文件一样,CAN报文用struct can_frame存储,FD报文用struct canfd_frame存储。六叶树USB转CAN和USB转FD的适配器都已支持SOCKET接口。

六叶树USBCAN2专业版

/**
******************************************************************************
* @file    socketCanTest.cpp
* @author  lys
* @version V1.1.0
* @date    2023
* @brief  
*
* @note
* SOCKET CAN收发使用用例
* 准备条件:
* 1.设备驱动已安装好,ifconfig -a 能够查看can0设备
* 2.已通过命令ip link配置好波特率并开启
    ip link set can0 type can bitrate 500000
    ip link set up can0
* 用法:
* write:发送can数据,使用结构体can_frame
* read:接收can数据,使用结构体can_frame
* 代码功能:
* 程序运行,初始化了socket,设置了过滤器功能(setsockopt),只接收0x590的报文,发送了1帧0x610
* 报文,接收到0x590的报文接收线程会自动退出,整个程序退出。
* @endverbatim
******************************************************************************
* 版权:长沙六叶树教育科技有限公司
* 官网:www.liuyeshu.cn
* 更多资料教程下载见官网
******************************************************************************
修改日期    版本号   修改者   功能描述
2018.11.10 V1.1.0  LYS
----------------------------------------------------------------------------
******************************************************************************
*/
#include <iostream>
#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>
#include <thread>

/**
* @输入参数: 无
* @输出参数: 无
* @返 回 值: 无
* @说    明:接收线程函数
* 接收到1帧数据自动退出
*/
void receiveThread(int socket)
{
    struct can_frame frame;

    std::cout << "Info: read start...\n";
    
    int nbytes = read(socket, &frame, sizeof(struct can_frame));

    if (nbytes < 0) 
    {
        std::cout << "Error: can raw socket read.\n";
        return;
    }

    if (nbytes < sizeof(struct can_frame)) 
    {
        std::cout << "Error: read incomplete CAN frame.\n";
        return;
    }

    printf("Receive OK\n");

    // 打印接收到的报文数据
    printf("ID=0x%X DLC=%d Data: ", frame.can_id, frame.can_dlc);
    for (uint8_t i = 0; i < frame.can_dlc; ++i)
    {
        printf("0x%02X ", frame.data[i]);
    }
    printf("\n");
}

int main()
{
    int nbytes;
    struct sockaddr_can socketCan0Addr;
    struct ifreq ifr;
    struct can_frame frame = {0};
    
    int socketFd = socket(PF_CAN, SOCK_RAW, CAN_RAW);

    // 获取can0的接口索引
    strcpy(ifr.ifr_name, "can0");
    ioctl(socketFd, SIOCGIFINDEX, &ifr);

    socketCan0Addr.can_family = AF_CAN;
    //把can0的接口索引赋值给socketCan0Addr
    socketCan0Addr.can_ifindex = ifr.ifr_ifindex; 

    // 把socketCan0Addr绑定到socket上
    bind(socketFd, (struct sockaddr *)&socketCan0Addr, sizeof(socketCan0Addr));

    /*设置过滤,只接收id是0x590的CAN报文,如果需要接收所有数据
    ,不执行CAN_RAW_FILTER操作即可*/
    struct can_filter rfilter;
    rfilter.can_id = 0x590;
    rfilter.can_mask = CAN_SFF_MASK;
    setsockopt(socketFd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

    // 开启接收回复的线程
    std::thread t(receiveThread, socketFd);

    // 准备数据
    frame.can_id = 0x610;
    //扩展帧
    frame.can_id |= CAN_EFF_FLAG;
    frame.can_dlc = 8; 
    frame.data[0] = 0x40;
    frame.data[1] = 0x01;
    frame.data[2] = 0x10;
    frame.data[3] = 0x00;
    frame.data[4] = 0x00;
    frame.data[5] = 0x00;
    frame.data[6] = 0x00;
    frame.data[7] = 0x00;

    // 发送数据
    nbytes = write(socketFd, &frame, sizeof(frame));
    if (nbytes != sizeof(frame))
    {
        std::cout << "Send Error\n";
    }

    //等待接收线程结束
    t.join(); 

    //程序退出
    return 0;
}
  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值