Files
checker_host/interface/if_can.cpp

370 lines
7.9 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_old;
typedef struct
{
uint32_t SegNum : 8;
uint32_t Reserve0 : 2;
uint32_t ACK : 1;
uint32_t FunClass : 6;
uint32_t SegFlag : 2;
uint32_t destMACID : 5;
uint32_t srcMACID : 5;
uint32_t Reserve1 : 3;
} YeCanID_st;
typedef union
{
uint32_t Exide;
YeCanID_st yecanid;
YeCanID_st_old yecanid_old;
} 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;
recv_cb_fun=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;
uint8_t dst_addr;
uint8_t seg_flag;
int seg_num;
if(frame_id.yecanid.Reserve0==0){
slave_addr = frame_id.yecanid_old.srcMACID;
dst_addr = frame_id.yecanid_old.destMACID;
seg_flag = frame_id.yecanid_old.SegFlag;
seg_num = frame_id.yecanid_old.SegNum;
}else{
slave_addr = frame_id.yecanid.srcMACID;
dst_addr = frame_id.yecanid.destMACID;
seg_flag = frame_id.yecanid.SegFlag;
seg_num = frame_id.yecanid.SegNum;
}
can_slave &slave = get_slave_by_addr(slave_addr);
if (seg_flag == 0x00){
// 不分段
slave.clear();
slave.append(payload);
// qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
if (dst_addr == 0){
if (irq_fun){
irq_fun(myarray(slave.get_data()));
}
if(recv_cb_fun){
recv_cb_fun(slave_addr,myarray(slave.get_data()));
}
emit recv_data_signal(slave_addr,slave.get_data());
}
}
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){
// qDebug()<<"can recv from:"<<slave_addr<<slave.get_data().toHex(' ');
if (dst_addr == 0){
if (irq_fun){
irq_fun(myarray(slave.get_data()));
}
if(recv_cb_fun){
recv_cb_fun(slave_addr,myarray(slave.get_data()));
}
emit recv_data_signal(slave_addr,slave.get_data());
}
}
else{
qDebug() << "can data from: " << slave_addr << "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_old.destMACID = addr;
frameId.yecanid_old.srcMACID = 0;
frameId.yecanid_old.FunClass = fun_class;
frameId.yecanid_old.SegFlag = 0;
frameId.yecanid_old.SegNum = 0;
// frameId.yecanid.Reserve0=1;// 使用新协议
// 单包发送
if (data.size() <= 8)
{
frameId.yecanid_old.SegFlag = 0x0;
frameId.yecanid_old.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_old.SegFlag = 0x1;
}
else if (data.size() > 8)
{
frameId.yecanid_old.SegFlag = 0x2;
}
else
{
frameId.yecanid_old.SegFlag = 0x3;
}
frameId.yecanid_old.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);