在can设备树的修改成功后,利用QT5的QCanBusDevice模块创建一个can的调试模块(注意这个例程是由野火linux_can摘抄而来,自己做了一点修改)
直接上代码:socketcan.pro:
QT += core gui serialbus
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCanBusDevice>
#include <QCanBus>
#include <QPushButton>
#include <QTextBrowser>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QLabel>
#include <QComboBox>
#include <QGridLayout>
#include <QMessageBox>
#include <QDebug>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QCanBusDevice *canDevice;
QTextBrowser *textBrowser;
QLineEdit *lineEdit;
QPushButton *pushButton[2];
QComboBox *comboBox[3];
QLabel *label[4];
QVBoxLayout *vboxLayout;
QGridLayout *gridLayout;
QWidget *mainWidget;
QWidget *funcWidget;
void layoutInit();
void pluginItemInit();
void bitrateItemInit();
private slots:
void sendFrame();
void receivedFrames();
void pluginChanged(int);
void canDeviceErrors(QCanBusDevice::CanBusError) const;
void connectDevice();
};
#endif
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
system("ifconfig can0 down");
system("ip link set up can0 type can bitrate 500000 restart-ms 100");
layoutInit();
pluginItemInit();
pluginChanged(comboBox[0]->currentIndex());
bitrateItemInit();
}
MainWindow::~MainWindow()
{
}
static QString frameFlags(const QCanBusFrame &frame)
{
QString result = QLatin1String(" --- ");
if (frame.hasBitrateSwitch())
result[1] = QLatin1Char('B');
if (frame.hasErrorStateIndicator())
result[2] = QLatin1Char('E');
if (frame.hasLocalEcho())
result[3] = QLatin1Char('L');
return result;
}
void MainWindow::sendFrame()
{
if (!canDevice)
return;
QString str = lineEdit->text();
QByteArray data = 0;
QString strTemp = nullptr;
QStringList strlist = str.split(' ');
for (int i = 1; i < strlist.count(); i++) {
strTemp = strTemp + strlist[i];
}
data = QByteArray::fromHex(strTemp.toLatin1());
bool ok;
int framId = strlist[0].toInt(&ok, 16);
QCanBusFrame frame = QCanBusFrame(framId, data);
canDevice->writeFrame(frame);
}
void MainWindow::receivedFrames()
{
if (!canDevice)
return;
while (canDevice->framesAvailable()) {
const QCanBusFrame frame = canDevice->readFrame();
QString view;
if (frame.frameType() == QCanBusFrame::ErrorFrame)
view = canDevice->interpretErrorFrame(frame);
else
view = frame.toString();
const QString time = QString::fromLatin1("%1.%2 ")
.arg(frame.timeStamp()
.seconds(), 10, 10, QLatin1Char(' '))
.arg(frame.timeStamp()
.microSeconds() / 100, 4, 10, QLatin1Char('0'));
const QString flags = frameFlags(frame);
textBrowser->insertPlainText(time + flags + view + "\n");
textBrowser->moveCursor(QTextCursor::End);
}
}
void MainWindow::layoutInit()
{
QList <QScreen *> list_screen = QGuiApplication::screens();
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
this->resize(800, 480);
textBrowser = new QTextBrowser();
lineEdit = new QLineEdit();
vboxLayout = new QVBoxLayout();
funcWidget = new QWidget();
mainWidget = new QWidget();
gridLayout = new QGridLayout();
QList <QString> list1;
list1<<"插件类型:"<<"可用接口:"<<"比特率bits/sec:";
for (int i = 0; i < 3; i++) {
label[i] = new QLabel(list1[i]);
label[i]->setMinimumSize(120, 30);
label[i]->setMaximumHeight(50);
label[i]->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
gridLayout->addWidget(label[i], 0, i);
}
label[3] = new QLabel();
label[3]->setMaximumHeight(30);
for (int i = 0; i < 3; i++) {
comboBox[i] = new QComboBox();
comboBox[i]->setMinimumSize(120, 30);
comboBox[i]->setMaximumHeight(50);
comboBox[i]->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
gridLayout->addWidget(comboBox[i], 1, i);
}
QList <QString> list2;
list2<<"发送"<<"连接CAN";
for (int i = 0; i < 2; i++) {
pushButton[i] = new QPushButton(list2[i]);
pushButton[i]->setMinimumSize(120, 30);
pushButton[i]->setMaximumHeight(50);
pushButton[i]->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
gridLayout->addWidget(pushButton[i], i, 3);
}
pushButton[0]->setEnabled(false);
vboxLayout->addWidget(textBrowser);
vboxLayout->addWidget(lineEdit);
funcWidget->setLayout(gridLayout);
vboxLayout->addWidget(funcWidget);
vboxLayout->addWidget(label[3]);
mainWidget->setLayout(vboxLayout);
this->setCentralWidget(mainWidget);
textBrowser->setPlaceholderText("系统时间 帧ID 长度 数据");
lineEdit->setText("123 aa 77 66 55 44 33 22 11");
label[3]->setText(tr("未连接!"));
connect(pushButton[1], SIGNAL(clicked()),
this, SLOT(connectDevice()));
connect(pushButton[0], SIGNAL(clicked()),
this, SLOT(sendFrame()));
}
void MainWindow::pluginItemInit()
{
comboBox[0]->addItems(QCanBus::instance()->plugins());
for (int i = 0; i < QCanBus::instance()->plugins().count(); i++) {
if (QCanBus::instance()->plugins().at(i) == "socketcan")
comboBox[0]->setCurrentIndex(i);
}
connect(comboBox[0], SIGNAL(currentIndexChanged(int)),
this, SLOT(pluginChanged(int)));
}
void MainWindow::pluginChanged(int)
{
QList<QCanBusDeviceInfo> interfaces;
comboBox[1]->clear();
interfaces = QCanBus::instance()
->availableDevices(comboBox[0]->currentText());
for (const QCanBusDeviceInfo &info : qAsConst(interfaces)) {
comboBox[1]->addItem(info.name());
}
}
void MainWindow::bitrateItemInit()
{
const QList<int> rates = {
10000, 20000, 50000, 100000, 125000,
250000, 500000, 800000, 1000000
};
for (int rate : rates)
comboBox[2]->addItem(QString::number(rate), rate);
comboBox[2]->setCurrentIndex(6);
}
void MainWindow::connectDevice()
{
if (pushButton[1]->text() == "连接CAN") {
QString cmd1 = tr("ifconfig %1 down")
.arg(comboBox[1]->currentText());
QString cmd2 =
tr("ip link set up %1 type can bitrate %2 restart-ms 100")
.arg(comboBox[1]->currentText())
.arg(comboBox[2]->currentText());
system(cmd1.toStdString().c_str());
system(cmd2.toStdString().c_str());
QString errorString;
canDevice = QCanBus::instance()->
createDevice(comboBox[0]->currentText(),
comboBox[1]->currentText(),
&errorString);
if (!canDevice) {
label[3]->setText(
tr("Error creating device '%1', reason: '%2'")
.arg(comboBox[0]->currentText())
.arg(errorString));
return;
}
if (!canDevice->connectDevice()) {
label[3]->setText(tr("Connection error: %1")
.arg(canDevice->errorString()));
delete canDevice;
canDevice = nullptr;
return;
}
connect(canDevice, SIGNAL(framesReceived()),
this, SLOT(receivedFrames()));
connect(canDevice,
SIGNAL(errorOccurred(QCanBusDevice::CanBusError)),
this,
SLOT(canDeviceErrors(QCanBusDevice::CanBusError)));
label[3]->setText(
tr("插件类型为: %1, 已连接到 %2, 比特率为 %3 kBit/s")
.arg(comboBox[0]->currentText())
.arg(comboBox[1]->currentText())
.arg(comboBox[2]->currentText().toInt() / 1000));
pushButton[1]->setText("断开CAN");
pushButton[0]->setEnabled(true);
comboBox[0]->setEnabled(false);
comboBox[1]->setEnabled(false);
comboBox[2]->setEnabled(false);
} else {
if (!canDevice)
return;
canDevice->disconnectDevice();
delete canDevice;
canDevice = nullptr;
pushButton[1]->setText("连接CAN");
pushButton[0]->setEnabled(false);
label[3]->setText(tr("未连接!"));
comboBox[0]->setEnabled(true);
comboBox[1]->setEnabled(true);
comboBox[2]->setEnabled(true);
}
}
void MainWindow::canDeviceErrors(QCanBusDevice::CanBusError error) const
{
switch (error) {
case QCanBusDevice::ReadError:
case QCanBusDevice::WriteError:
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
label[3]->setText(canDevice->errorString());
break;
default:
break;
}
}
编译后生成socketcan上传给开发板,运行程序:
[root@ok3568:/test]# ./socket_can
QStandardPaths: wrong permissions on runtime directory /var/run, 7755 instead of 7700
[ 956.007316] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
qt.qpa.wayland: No shell integration named "xdg-shell" found
到此,我们在OK3568上用python跟QT、C、shell都实现了对CAN总线的操作。可以说这款芯片,对can的支持非常好,特别适合在汽车领域,或者是工程机领域。