2023-11-29 15:36:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "interface/if_can.h"
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
#include "QTimer"
|
|
|
|
|
#include "base/crc.h"
|
|
|
|
|
#include <QtEndian>
|
|
|
|
|
#include "QThread"
|
|
|
|
|
#include "base/mycfg.h"
|
|
|
|
|
|
|
|
|
|
#define QT_NO_DEBUG_OUTPUT
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint32_t Reserve1 : 3;
|
|
|
|
|
uint32_t srcMACID : 5;
|
|
|
|
|
uint32_t Reserve0 : 2;
|
|
|
|
|
uint32_t destMACID : 5;
|
|
|
|
|
uint32_t ACK : 1;
|
|
|
|
|
uint32_t FunClass : 6;
|
|
|
|
|
uint32_t SegFlag : 2;
|
|
|
|
|
uint32_t SegNum : 8;
|
|
|
|
|
} YeCanID_st;
|
|
|
|
|
|
|
|
|
|
typedef union
|
|
|
|
|
{
|
|
|
|
|
uint32_t Exide;
|
|
|
|
|
YeCanID_st yecanid;
|
|
|
|
|
} YeCanID_un;
|
|
|
|
|
|
|
|
|
|
can_slave::can_slave()
|
|
|
|
|
{
|
|
|
|
|
addr = 0;
|
|
|
|
|
recv_pack_num = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义带参的沟道函数,供QList调用
|
|
|
|
|
can_slave::can_slave(const can_slave &b) : QObject()
|
|
|
|
|
{
|
|
|
|
|
this->addr = b.addr;
|
|
|
|
|
this->recv_data = b.recv_data;
|
|
|
|
|
this->recv_pack_num = b.recv_pack_num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
can_slave::~can_slave()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
can_slave &can_slave::operator=(const can_slave &b)
|
|
|
|
|
{
|
|
|
|
|
this->addr = b.addr;
|
|
|
|
|
this->recv_data = b.recv_data;
|
|
|
|
|
this->recv_pack_num = b.recv_pack_num;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_slave::append(QByteArray data)
|
|
|
|
|
{
|
|
|
|
|
recv_data.append(data);
|
|
|
|
|
recv_pack_num++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray can_slave::get_data()
|
|
|
|
|
{
|
|
|
|
|
return recv_data;
|
|
|
|
|
}
|
|
|
|
|
int can_slave::get_pack_num()
|
|
|
|
|
{
|
|
|
|
|
return recv_pack_num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_slave::clear()
|
|
|
|
|
{
|
|
|
|
|
recv_data.clear();
|
|
|
|
|
recv_pack_num = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
can_host::can_host(int bitrate)
|
|
|
|
|
{
|
|
|
|
|
this->bitrate = bitrate;
|
|
|
|
|
this->can_ = nullptr;
|
|
|
|
|
timer_ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
can_host::~can_host()
|
|
|
|
|
{
|
2023-12-02 11:27:25 +08:00
|
|
|
|
if(can_ !=nullptr){
|
|
|
|
|
delete can_;
|
|
|
|
|
}
|
|
|
|
|
if(timer_ !=nullptr){
|
|
|
|
|
delete timer_;
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用于返回指定地址的从机对象
|
|
|
|
|
can_slave &can_host::get_slave_by_addr(uint8_t addr)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < slaves.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (slaves[i].addr == addr)
|
|
|
|
|
return slaves[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果没有对应地址的从机,则添加一个
|
|
|
|
|
can_slave c;
|
|
|
|
|
c.addr = addr;
|
|
|
|
|
slaves.append(c);
|
|
|
|
|
return slaves[slaves.size() - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_host::init()
|
|
|
|
|
{
|
|
|
|
|
QTimer::singleShot(0, this, &can_host::init_cb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_host::init_cb()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (nullptr == can_)
|
|
|
|
|
{
|
|
|
|
|
/* 先关闭can0 */
|
|
|
|
|
system("ifconfig can0 down");
|
|
|
|
|
QString cmd = tr("ip link set up can0 type can bitrate %1 restart-ms 100").arg(bitrate);
|
|
|
|
|
/* 使用系统指令以设置的比特率初始化CAN */
|
|
|
|
|
// qDebug()<< "can cmd:"<<cmd<<endl;
|
|
|
|
|
system(cmd.toStdString().c_str());
|
|
|
|
|
system("echo 4096 > /sys/class/net/can0/tx_queue_len");
|
|
|
|
|
|
|
|
|
|
QString errorString;
|
|
|
|
|
can_ = QCanBus::instance()->createDevice("socketcan", "can0", &errorString);
|
|
|
|
|
if (!can_)
|
|
|
|
|
{
|
|
|
|
|
qWarning() << "Error creating device can0,reson:" << errorString;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* 连接CAN */
|
|
|
|
|
if (!can_->connectDevice())
|
|
|
|
|
{
|
|
|
|
|
qWarning() << "device can0 Connection error:" << can_->errorString();
|
|
|
|
|
delete can_;
|
|
|
|
|
can_ = nullptr;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 连接收到数据信号和错误信号
|
|
|
|
|
connect(can_, SIGNAL(framesReceived()), this, SLOT(recv_data_cb()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送完成回调
|
|
|
|
|
void can_host::freams_sent_cb(qint64 count)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(count);
|
|
|
|
|
qDebug() << "freams sent.count=" << count;
|
|
|
|
|
if (!send_packets.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
QCanBusFrame f = send_packets.at(0);
|
|
|
|
|
if (can_->writeFrame(f) == true)
|
|
|
|
|
send_packets.removeAt(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 收到can数据的回调
|
|
|
|
|
void can_host::recv_data_cb()
|
|
|
|
|
{
|
|
|
|
|
YeCanID_un frame_id;
|
|
|
|
|
while (can_->framesAvailable())
|
|
|
|
|
{
|
|
|
|
|
const QCanBusFrame frame = can_->readFrame();
|
|
|
|
|
frame_id.Exide = frame.frameId();
|
|
|
|
|
if (frame_id.Exide == 0x000000)
|
|
|
|
|
return;
|
|
|
|
|
QByteArray payload = frame.payload();
|
|
|
|
|
uint8_t slave_addr = frame_id.yecanid.srcMACID;
|
|
|
|
|
uint8_t dst_addr = frame_id.yecanid.destMACID;
|
|
|
|
|
uint8_t seg_flag = frame_id.yecanid.SegFlag;
|
|
|
|
|
int seg_num = frame_id.yecanid.SegNum;
|
|
|
|
|
can_slave &slave = get_slave_by_addr(slave_addr);
|
|
|
|
|
if (seg_flag == 0x00)
|
|
|
|
|
{
|
|
|
|
|
// 不分段
|
|
|
|
|
slave.clear();
|
|
|
|
|
slave.append(payload);
|
|
|
|
|
if (dst_addr == 0){
|
|
|
|
|
if (irq_fun)
|
|
|
|
|
{
|
|
|
|
|
irq_fun(myarray(slave.get_data()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
|
|
|
|
else if (seg_flag == 0x01)
|
|
|
|
|
{
|
|
|
|
|
// 首段
|
|
|
|
|
slave.clear();
|
|
|
|
|
slave.append(payload);
|
|
|
|
|
}
|
|
|
|
|
else if (seg_flag == 0x02)
|
|
|
|
|
{
|
|
|
|
|
// 中段
|
|
|
|
|
slave.append(payload);
|
|
|
|
|
}
|
|
|
|
|
else if (seg_flag == 0x03)
|
|
|
|
|
{
|
|
|
|
|
// 尾段
|
|
|
|
|
slave.append(payload);
|
|
|
|
|
if (slave.get_pack_num() - 1 == seg_num)
|
|
|
|
|
{
|
|
|
|
|
if (dst_addr == 0){
|
|
|
|
|
if (irq_fun)
|
|
|
|
|
{
|
|
|
|
|
irq_fun(myarray(slave.get_data()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
qDebug() << "can data from: " << QString::number(slave_addr, 10) << "recv error";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int can_host::write(int dst,myarray data)
|
|
|
|
|
{
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug()<<"can send to:"<<dst<<data.toHex(' ');
|
2023-11-29 15:36:45 +08:00
|
|
|
|
append(dst, 1, data);
|
|
|
|
|
return data.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void can_host::send_data_cb(uint8_t dst, int fun_class, QByteArray data)
|
|
|
|
|
{
|
|
|
|
|
append(dst, fun_class, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 群发消息
|
|
|
|
|
void can_host::send_data_mul_cb(QList<uint8_t> dst, int fun_class, QByteArray data)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < dst.size(); i++)
|
|
|
|
|
append(dst[i], fun_class, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_host::append(uint8_t addr, uint8_t fun_class, QByteArray data)
|
|
|
|
|
{
|
|
|
|
|
YeCanID_un frameId;
|
|
|
|
|
frameId.Exide = 0;
|
|
|
|
|
frameId.yecanid.destMACID = addr;
|
|
|
|
|
frameId.yecanid.srcMACID = 0;
|
|
|
|
|
frameId.yecanid.FunClass = fun_class;
|
|
|
|
|
frameId.yecanid.SegFlag = 0;
|
|
|
|
|
frameId.yecanid.SegNum = 0;
|
|
|
|
|
|
|
|
|
|
// 单包发送
|
|
|
|
|
if (data.size() <= 8)
|
|
|
|
|
{
|
|
|
|
|
frameId.yecanid.SegFlag = 0x0;
|
|
|
|
|
frameId.yecanid.SegNum = 0;
|
|
|
|
|
QCanBusFrame frame = QCanBusFrame(frameId.Exide, data.left(8));
|
|
|
|
|
while (can_->writeFrame(frame) != true)
|
|
|
|
|
{
|
|
|
|
|
can_->waitForFramesWritten(1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 按8字节分包发送
|
|
|
|
|
for (int i = 0; !data.isEmpty(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
|
|
|
|
{
|
|
|
|
|
frameId.yecanid.SegFlag = 0x1;
|
|
|
|
|
}
|
|
|
|
|
else if (data.size() > 8)
|
|
|
|
|
{
|
|
|
|
|
frameId.yecanid.SegFlag = 0x2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
frameId.yecanid.SegFlag = 0x3;
|
|
|
|
|
}
|
|
|
|
|
frameId.yecanid.SegNum = (uint8_t)i;
|
|
|
|
|
QCanBusFrame frame = QCanBusFrame(frameId.Exide, data.left(8));
|
|
|
|
|
while (can_->writeFrame(frame) != true)
|
|
|
|
|
{
|
|
|
|
|
can_->waitForFramesWritten(1000);
|
|
|
|
|
}
|
|
|
|
|
data.remove(0, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void can_host::on_error_cb(QCanBusDevice::CanBusError err)
|
|
|
|
|
{
|
|
|
|
|
switch (err)
|
|
|
|
|
{
|
|
|
|
|
case QCanBusDevice::ReadError:
|
|
|
|
|
qWarning() << "ReadError" << can_->errorString();
|
|
|
|
|
break;
|
|
|
|
|
case QCanBusDevice::WriteError:
|
|
|
|
|
qWarning() << "WriteError" << can_->errorString();
|
|
|
|
|
break;
|
|
|
|
|
case QCanBusDevice::ConnectionError:
|
|
|
|
|
qWarning() << "ConnectionError" << can_->errorString();
|
|
|
|
|
break;
|
|
|
|
|
case QCanBusDevice::ConfigurationError:
|
|
|
|
|
qWarning() << "ConfigurationError" << can_->errorString();
|
|
|
|
|
break;
|
|
|
|
|
case QCanBusDevice::UnknownError:
|
|
|
|
|
qWarning() << "UnknowError" << can_->errorString();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
InterFace *if_can_get()
|
|
|
|
|
{
|
|
|
|
|
static InterFace *if_ = nullptr;
|
|
|
|
|
if (if_ == nullptr)
|
|
|
|
|
{
|
|
|
|
|
int bsp=200000;
|
|
|
|
|
if(syscfg()->can_bitrate!=0){
|
|
|
|
|
bsp=syscfg()->can_bitrate;
|
|
|
|
|
}
|
|
|
|
|
if_ = new can_host(bsp);
|
|
|
|
|
QTimer::singleShot(0, if_, &InterFace::init);
|
|
|
|
|
}
|
|
|
|
|
return if_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if_export(can, if_can_get);
|
|
|
|
|
|
|
|
|
|
|