纯C++写的、Linux下 的CAN报文发送、接收类
2023-12-20 06:53:50
commonToolkits_global.h?
#ifndef COMMONTOOLKITS_GLOBAL_H
#define COMMONTOOLKITS_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(COMMONTOOLKITS_LIBRARY)
# define COMMONTOOLKITS_EXPORT Q_DECL_EXPORT
#else
# define COMMONTOOLKITS_EXPORT Q_DECL_IMPORT
#endif
#endif // COMMONTOOLKITS_GLOBAL_H
cansocketlinux.h
#ifndef _CANSOCKET_H
#define _CANSOCKET_H
// The order of the following includes is mandatory, because some
// distributions use sa_family_t in can.h without including socket.h
#include <sys/socket.h>
#include <sys/uio.h>
#include <linux/can.h>
#include <sys/time.h>
#include "commonToolkits_global.h"
#include <string>
#include <vector>
struct CanFrame
{
uint32_t frameId; // 帧id
uint8_t dataLen{0}; // 帧数据包长度
uint8_t data[8]{0}; // 存放can帧的数据包缓冲区
};
class COMMONTOOLKITS_EXPORT CanSocket
{
public:
CanSocket(const std::string &name, bool bInit = false);
~CanSocket();
void initCan(); // 初始化can,主要是设置波特率
bool open(); // 打开can
void close(); // 关闭can
bool writeFrame(const CanFrame& frame); // 发送can数据到can总线
std::vector<CanFrame> readSocket(); // 获取CAN总线的数据包
public:
bool getState() {
if(canSocket == -1) {
return false;
}
return true;
}
private:
bool connectSocket();
sockaddr_can m_address;
char m_ctrlmsg[CMSG_SPACE(sizeof(timeval)) + CMSG_SPACE(sizeof(__u32))];
int canSocket = -1;
std::string canSocketName;
bool canFdOptionEnabled = false;
std::string errMsg;
};
cansocketlinux.cpp?
#include "cansocketlinux.h"
#include "memory.h"
#include "stddef.h"
#include <string>
#include "qglobal.h"
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
const std::string CAN0_OPEN = "ifconfig can0 up";
const std::string CAN0_CLOSE = "ifconfig can0 down";
const std::string CAN0_CONFIG = "ip link set can0 type can bitrate 250000 triple-sampling on";
const std::string CAN1_OPEN = "ifconfig can1 up";
const std::string CAN1_CLOSE = "ifconfig can1 down";
const std::string CAN1_CONFIG = "ip link set can1 type can bitrate 250000 triple-sampling on";
void CanSocket::initCan()
{
system(CAN0_CONFIG.data());
system(CAN0_OPEN.data());
system(CAN1_CONFIG.data());
system(CAN1_OPEN.data());
}
CanSocket::CanSocket(const std::string &name, bool bInit = false):
canSocketName(name)
{
if(bInit)
{
initCan();
}
}
CanSocket::~CanSocket()
{
close();
}
bool CanSocket::open()
{
if (canSocket == -1) {
if (!connectSocket()) {
close(); // sets UnconnectedState
return false;
}
}
return true;
}
void CanSocket::close()
{
::close(canSocket);
canSocket = -1;
}
bool CanSocket::writeFrame(const CanFrame &frame)
{
if (canSocket== -1)
return false;
if(frame.dataLen > 8) {
return false;
}
canid_t canId = frame.frameId;
canId |= CAN_EFF_FLAG;
int64_t bytesWritten = 0;
can_frame sendframe;
::memset(&sendframe, 0, sizeof(sendframe));
sendframe.can_dlc = frame.dataLen;
sendframe.can_id = canId;
::memcpy(sendframe.data, frame.data, sendframe.can_dlc);
bytesWritten = ::write(canSocket, &sendframe, sizeof(sendframe));
if (bytesWritten < 0) {
return false;
}
return true;
}
std::vector<CanFrame> CanSocket::readSocket()
{
std::vector<CanFrame> newFrames;
for (;;) {
struct can_frame frame;
const int bytesReceived = ::read(canSocket, &frame, sizeof(frame));
if (bytesReceived != sizeof(frame)) {
break;
}
struct timeval timeStamp;
if (ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0) {
::memset(&timeStamp, 0, sizeof(timeStamp));
}
CanFrame bufferedFrame;
bufferedFrame.frameId = (frame.can_id & CAN_EFF_MASK);
bufferedFrame.dataLen = frame.can_dlc;
if(frame.can_dlc > 8) {
continue;
}
memcpy(bufferedFrame.data, frame.data, frame.can_dlc);
newFrames.push_back(std::move(bufferedFrame));
}
return newFrames;
}
bool CanSocket::connectSocket()
{
struct ifreq interface;
if ((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0) {
//errMsg = errno;
return false;
}
int loopback = 0;
setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));
strcpy(interface.ifr_name, canSocketName.data());
if (ioctl(canSocket, SIOCGIFINDEX, &interface) < 0) {
//errMsg = errno;
return false;
}
m_address.can_addr.tp.rx_id = 0;
m_address.can_addr.tp.tx_id = 0;
m_address.can_family = AF_CAN;
m_address.can_ifindex = interface.ifr_ifindex;
if (bind(canSocket, (struct sockaddr *)(&m_address), sizeof(m_address)) < 0) {
//qDebug("%s", qt_error_string(errno).toLatin1().data());
//errMsg = std::string(qt_error_string(errno).toLocal8Bit().constData());
return false;
}
return true;
}
说明:
- 仅仅用到了Qtcore,如果你不想依赖Qt,可以把代码中qt的全部去掉,其实qt的东西也不多。
- initCan()用于初始化CAN的波特率。一般波特率设置在开机自启动的脚本中;也可以通过构造函数的第二个设置为true,让程序来设置CAN波特率。
- 主要接口功能见头文件注释。
文章来源:https://blog.csdn.net/danshiming/article/details/135075832
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!