Files
checker_host/interface/if_can.cpp
ranchuan cc5b1b7458 广播命令已接收的回复不再触发回调
检测命令0x0c只能使用单播方式,广播方式因为不能即时回复停止信号,回复会出错
  添加电阻测试命令,添加自检命令
2023-12-13 18:29:46 +08:00

344 lines
7.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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()
{
if(can_ !=nullptr){
delete can_;
}
if(timer_ !=nullptr){
delete timer_;
}
}
// 用于返回指定地址的从机对象
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()));
}
emit recv_data_signal(slave_addr,slave.get_data());
}
qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
}
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()));
}
emit recv_data_signal(slave_addr,slave.get_data());
}
qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
}
else
{
qDebug() << "can data from: " << QString::number(slave_addr, 10) << "recv error";
}
}
}
}
int can_host::write(int dst,myarray data)
{
qDebug()<<"can send to:"<<dst<<data.toHex(' ');
append(dst, 1, data);
// qDebug("can send end.");
return data.size();
}
// 群发消息
void can_host::send_data_mul_slot(QList<int> addrs, QByteArray data)
{
for (int i = 0; i < addrs.size(); i++)
append(addrs[i], 1, 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)
{
// qDebug("wait for written.");
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);