六叶树USBCAN1适配器升级版,代码用例。
通过setsockopt函数设置,代码如下:
/**
******************************************************************************
* @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;
}