搜索
bottom↓
回复: 0

《I.MX6U嵌入式Qt开发指南》第十八章 CAN Bus

[复制链接]

出0入234汤圆

发表于 2021-7-19 15:08:39 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2021-8-11 12:26 编辑

1)实验平台:正点原子i.MX6ULL Linux阿尔法开发板
2)  章节摘自【正点原子】《I.MX6U嵌入式Qt开发指南》
3)购买链接:https://item.taobao.com/item.htm?&id=603672744434
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/arm-linux/zdyz-i.mx6ull.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)
正点原子Linux技术交流群:1027879335    1.png

2.jpg


3.png


第十八章 CAN Bus

       从Qt5.8开始,提供了CAN Bus类,很庆幸,正点原子的I.MX6U出厂系统里Qt版本是QT5.12.9。我们可以直接使用Qt的提供的CAN相关类编程即可。假设您的Qt版本没有CAN Bus,可以参考Linux应用编程来操控开发板的CAN也是可以的,目前我们主要讲解Qt相关的CAN编程。其实Qt也提供了相关的Qt CAN的例子,我们也可以直接参考来编程。编者根据实际情况,化繁为易,直接写了个简单的例子给大家参考。如果让读者直接去参考Qt官方的例子来写程序估计要头大。噢!最重要的一点,读者应会使用CAN相关测试工具,我们应该提前去熟悉,并且读者手上需要有测试CAN的仪器!否则写好程序,却无法测试,这就有些尴尬了。


18.1 资源简介
       正点原子I.MX6U开发板底板上预留了一路CAN接口(6U芯片最大支持两路)。如下图。在正点原子【正点原子】I.MX6U用户快速体验V1.x.pdf里也有相关的CAN测试方法。这里就不多介绍CAN了,编者默认读者是会使用CAN的。同时不对CAN总线协议进行讲解,主要是讲解如何在Qt里对CAN编程。
CAN Bus580.png

18.2 应用实例
       项目简介:本例适用于正点原子I.MX6U开发板。不适用于Windows。因为Windows没有CAN设备。虽然Windows可以外接USB CAN模块,但是这些模块都是某些厂商开发的,需要有相应的固件才能驱动CAN设备。所以编写的例子不一定适用于Windows下的CAN。编者写的例子已经在正点原子I.MX6U开发板上验证了,确保正常使用!
       在正点原子I.MX6U板上,需要使用CAN必须初始化CAN。它的开启与关闭都是由系统完成。I.MX6U为普通CAN,非FD CAN,最大比特率为1000kBit/s。
在系统执行要在100毫秒后自动从“总线关闭”错误中恢复,并以比特率1000000,可以使用以下命令开启CAN。
  1. ip link set up can0 type can bitrate 1000000 restart-ms 100
复制代码

       例04_socketcan,Qt CAN编程(难度:较难)。项目路径为Qt/3/04_ socketcan。
       04_socketcan.pro要想使用Qt的QCanBus,需要在pro项目文件里添加相应的模块支持。同时还需要添加对应的头文件,详细请看项目里的代码。
  1. 1   QT       += core gui serialbus
  2. 2
  3. 3   greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  4. 4
  5. 5   CONFIG += c++11
  6. 6
  7. 7   # The following define makes your compiler emit warnings if you use
  8. 8   # any Qt feature that has been marked deprecated (the exact warnings
  9. 9   # depend on your compiler). Please consult the documentation of the
  10. 10  # deprecated API in order to know how to port your code away from it.
  11. 11  DEFINES += QT_DEPRECATED_WARNINGS
  12. 12
  13. 13  # You can also make your code fail to compile if it uses deprecated APIs.
  14. 14  # In order to do so, uncomment the following line.
  15. 15  # You can also select to disable deprecated APIs only up to a certain version of Qt.
  16. 16  #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
  17. 17
  18. 18  SOURCES += \
  19. 19      main.cpp \
  20. 20      mainwindow.cpp
  21. 21
  22. 22  HEADERS += \
  23. 23      mainwindow.h
  24. 24
  25. 25  # Default rules for deployment.
  26. 26  qnx: target.path = /tmp/${TARGET}/bin
  27. 27  else: unix:!android: target.path = /opt/${TARGET}/bin
  28. 28  !isEmpty(target.path): INSTALLS += target
复制代码

      第1行,添加的serialbus就是添加串口模块的支持。
      在头文件“mainwindow.h”的代码如下。一些声明。        
  1. /******************************************************************
  2.     Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
  3.     * @projectName   04_socketcan
  4.     * @brief         mainwindow.h
  5.     * @author        Deng Zhimao
  6.     * @email         <a href="mailto:1252699831@qq.com">1252699831@qq.com</a>
  7.     * @net            <a href="www.openedv.com" target="_blank">www.openedv.com</a>
  8.     * @date           2021-03-15
  9.     *******************************************************************/
  10. 1   #ifndef MAINWINDOW_H
  11. 2   #define MAINWINDOW_H
  12. 3
  13. 4   #include <QMainWindow>
  14. 5   #include <QCanBusDevice>
  15. 6   #include <QCanBus>
  16. 7   #include <QPushButton>
  17. 8   #include <QTextBrowser>
  18. 9   #include <QLineEdit>
  19. 10  #include <QVBoxLayout>
  20. 11  #include <QLabel>
  21. 12  #include <QComboBox>
  22. 13  #include <QGridLayout>
  23. 14  #include <QMessageBox>
  24. 15  #include <QDebug>
  25. 16
  26. 17  class MainWindow : public QMainWindow
  27. 18  {
  28. 19      Q_OBJECT
  29. 20
  30. 21  public:
  31. 22      MainWindow(QWidget *parent = nullptr);
  32. 23      ~MainWindow();
  33. 24
  34. 25  private:
  35. 26      /* CAN设备 */
  36. 27      QCanBusDevice *canDevice;
  37. 28
  38. 29      /* 用作接收数据 */
  39. 30      QTextBrowser *textBrowser;
  40. 31
  41. 32      /* 用作发送数据 */
  42. 33      QLineEdit *lineEdit;
  43. 34
  44. 35      /* 按钮 */
  45. 36      QPushButton *pushButton[2];
  46. 37
  47. 38      /* 下拉选择盒子 */
  48. 39      QComboBox *comboBox[3];
  49. 40
  50. 41      /* 标签 */
  51. 42      QLabel *label[4];
  52. 43
  53. 44      /* 垂直布局 */
  54. 45      QVBoxLayout *vboxLayout;
  55. 46
  56. 47      /* 网络布局 */
  57. 48      QGridLayout *gridLayout;
  58. 49
  59. 50      /* 主布局 */
  60. 51      QWidget *mainWidget;
  61. 52
  62. 53      /* 设置功能区域 */
  63. 54      QWidget *funcWidget;
  64. 55
  65. 56      /* 布局初始化 */
  66. 57      void layoutInit();
  67. 58
  68. 59      /* 插件类型项初始化 */
  69. 60      void pluginItemInit();
  70. 61
  71. 62      /* 比牲率项初始化 */
  72. 63      void bitrateItemInit();
  73. 64
  74. 65  private slots:
  75. 66      /* 发送消息 */
  76. 67      void sendFrame();
  77. 68
  78. 69      /* 接收消息 */
  79. 70      void receivedFrames();
  80. 71
  81. 72      /* 插件发生改变 */
  82. 73      void pluginChanged(int);
  83. 74
  84. 75      /* 处理can错误 */
  85. 76      void canDeviceErrors(QCanBusDevice::CanBusError) const;
  86. 77
  87. 78      /* 连接或者断开can */
  88. 79      void connectDevice();
  89. 80  };
  90. 81  #endif // MAINWINDOW_H
  91. 82
复制代码

       上面代码是在mianwindow.h里声明需要用到的变量,方法及槽函数。
       mainwindow.cpp的代码如下。
  1. /******************************************************************
  2.     Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
  3.     * @projectName   04_socketcan
  4.     * @brief         mainwindow.cpp
  5.     * @author        Deng Zhimao
  6.     * @email         <a href="mailto:1252699831@qq.com" style="">1252699831@qq.com</a>
  7.     * @net            <a href="www.openedv.com" target="_blank" style="">www.openedv.com</a>
  8.     * @date           2021-03-15
  9.     *******************************************************************/
  10. 1   #include "mainwindow.h"
  11. 2   #include <QGuiApplication>
  12. 3   #include <QScreen>
  13. 4  
  14. 5   MainWindow::MainWindow(QWidget *parent)
  15. 6       : QMainWindow(parent)
  16. 7   {
  17. 8       /* 使用系统指令比牲率初始化CAN,默认为1000000bits/s */
  18. 9       system("ifconfig can0 down");
  19. 10      system("ip link set up can0 type can bitrate 1000000 restart-ms 100");
  20. 11
  21. 12      /* 布局初始化 */
  22. 13      layoutInit();
  23. 14
  24. 15      /* 可用插件初始化 */
  25. 16      pluginItemInit();
  26. 17
  27. 18      /* 可用接口项初始化 */
  28. 19      pluginChanged(comboBox[0]->currentIndex());
  29. 20
  30. 21      /* 比特率项初始化 */
  31. 22      bitrateItemInit();
  32. 23  }
  33. 24
  34. 25  MainWindow::~MainWindow()
  35. 26  {
  36. 27  }
  37. 28
  38. 29  static QString frameFlags(const QCanBusFrame &frame)
  39. 30  {
  40. 31      /* 格式化接收到的消息 */
  41. 32      QString result = QLatin1String(" --- ");
  42. 33
  43. 34      if (frame.hasBitrateSwitch())
  44. 35          result[1] = QLatin1Char('B');
  45. 36      if (frame.hasErrorStateIndicator())
  46. 37          result[2] = QLatin1Char('E');
  47. 38      if (frame.hasLocalEcho())
  48. 39          result[3] = QLatin1Char('L');
  49. 40
  50. 41      return result;
  51. 42  }
  52. 43
  53. 44  /* 发送消息 */
  54. 45  void MainWindow::sendFrame()
  55. 46  {
  56. 47      if (!canDevice)
  57. 48          return;
  58. 49      /* 读取QLineEdit的文件 */
  59. 50      QString str = lineEdit->text();
  60. 51      QByteArray data = 0;
  61. 52      QString strTemp = nullptr;
  62. 53      /* 以空格分隔lineEdit的内容,并存储到字符串链表中 */
  63. 54      QStringList strlist = str.split(' ');
  64. 55      for (int i = 1; i < strlist.count(); i++) {
  65. 56          strTemp = strTemp + strlist;
  66. 57      }
  67. 58      /* 将字符串的内容转为QByteArray类型 */
  68. 59      data = QByteArray::fromHex(strTemp.toLatin1());
  69. 60
  70. 61      bool ok;
  71. 62      /* 以16进制读取要发送的帧内容里第一个数据,并作为帧ID */
  72. 63      int framId = strlist[0].toInt(&ok, 16);
  73. 64      QCanBusFrame frame = QCanBusFrame(framId, data);
  74. 65      /* 写入帧 */
  75. 66      canDevice->writeFrame(frame);
  76. 67  }
  77. 68
  78. 69  /* 接收消息 */
  79. 70  void MainWindow::receivedFrames()
  80. 71  {
  81. 72      if (!canDevice)
  82. 73          return;
  83. 74
  84. 75      /* 读取帧 */
  85. 76      while (canDevice->framesAvailable()) {
  86. 77          const QCanBusFrame frame = canDevice->readFrame();
  87. 78          QString view;
  88. 79          if (frame.frameType() == QCanBusFrame::ErrorFrame)
  89. 80              view = canDevice->interpretErrorFrame(frame);
  90. 81          else
  91. 82              view = frame.toString();
  92. 83
  93. 84          const QString time = QString::fromLatin1("%1.%2  ")
  94. 85                  .arg(frame.timeStamp()
  95. 86                       .seconds(), 10, 10, QLatin1Char(' '))
  96. 87                  .arg(frame.timeStamp()
  97. 88                       .microSeconds() / 100, 4, 10, QLatin1Char('0'));
  98. 89
  99. 90          const QString flags = frameFlags(frame);
  100. 91          /* 接收消息框追加接收到的消息 */
  101. 92          textBrowser->insertPlainText(time + flags + view + "\n");
  102. 93      }
  103. 94  }
  104. 95
  105. 96  void MainWindow::layoutInit()
  106. 97  {
  107. 98      /* 获取屏幕的分辨率,Qt官方建议使用这
  108. 99       * 种方法获取屏幕分辨率,防上多屏设备导致对应不上
  109. 100      * 注意,这是获取整个桌面系统的分辨率
  110. 101      */
  111. 102     QList <QScreen *> list_screen =  QGuiApplication::screens();
  112. 103
  113. 104     /* 如果是ARM平台,直接设置大小为屏幕的大小 */
  114. 105 #if __arm__
  115. 106     /* 重设大小 */
  116. 107     this->resize(list_screen.at(0)->geometry().width(),
  117. 108                  list_screen.at(0)->geometry().height());
  118. 109 #else
  119. 110     /* 否则则设置主窗体大小为800x480 */
  120. 111     this->resize(800, 480);
  121. 112 #endif
  122. 113     /* 对象初始化 */
  123. 114     textBrowser = new QTextBrowser();
  124. 115     lineEdit = new QLineEdit();
  125. 116     vboxLayout = new QVBoxLayout();
  126. 117     funcWidget = new QWidget();
  127. 118     mainWidget = new QWidget();
  128. 119     gridLayout = new QGridLayout();
  129. 120
  130. 121     /* QList链表,字符串类型 */
  131. 122     QList <QString> list1;
  132. 123     list1<<"插件类型:"<<"可用接口:"<<"比特率bits/sec:";
  133. 124
  134. 125     for (int i = 0; i < 3; i++) {
  135. </font><span style="font-style: italic;"><font size="2"><span style="font-style: normal;">126         label = new QLabel(list1</span><span style="font-style: normal;">);
  136. 127         /* 设置最小宽度与高度 */
  137. 128         label</span><span style="font-style: normal;">->setMinimumSize(120, 30);
  138. 129         label</span><span style="font-style: normal;">->setMaximumHeight(50);
  139. 130         /* 自动调整label的大小 */
  140. 131         label</span><span style="font-style: normal;">->setSizePolicy(QSizePolicy::Expanding,
  141. 132                                 QSizePolicy::Expanding);
  142. 133         /* 将label</span><span style="font-style: normal;">添加至网格的坐标(0, i) */
  143. 134         gridLayout->addWidget(label</span><span style="font-style: normal;">, 0, i);
  144. 135     }
  145. 136     label[3] = new QLabel();
  146. 137     label[3]->setMaximumHeight(30);
  147. 138
  148. 139     for (int i = 0; i < 3; i++) {
  149. 140         comboBox</span><span style="font-style: normal;"> = new QComboBox();
  150. 141         comboBox</span><span style="font-style: normal;">->setMinimumSize(120, 30);
  151. 142         comboBox</span><span style="font-style: normal;">->setMaximumHeight(50);
  152. 143         /* 自动调整label的大小 */
  153. 144         comboBox</span><span style="font-style: normal;">->setSizePolicy(QSizePolicy::Expanding,
  154. 145                                    QSizePolicy::Expanding);
  155. 146         /* 将comboBox</span><span style="font-style: normal;">添加至网格的坐标(1, i) */
  156. 147         gridLayout->addWidget(comboBox</span><span style="font-style: normal;">, 1, i);
  157. 148     }
  158. 149
  159. 150     /* QList链表,字符串类型 */
  160. 151     QList <QString> list2;
  161. 152     list2<<"发送"<<"连接CAN";
  162. 153
  163. 154     for (int i = 0; i < 2; i++) {
  164. 155         pushButton</span><span style="font-style: normal;"> = new QPushButton(list2</span><span style="font-style: normal;">);
  165. 156         pushButton</span><span style="font-style: normal;">->setMinimumSize(120, 30);
  166. 157         pushButton</span><span style="font-style: normal;">->setMaximumHeight(50);
  167. 158         /* 自动调整label的大小 */
  168. 159         pushButton</span><span style="font-style: normal;">->setSizePolicy(QSizePolicy::Expanding,
  169. 160                                      QSizePolicy::Expanding);
  170. 161         /* 将pushButton[0]添加至网格的坐标(i, 3) */
  171. 162         gridLayout->addWidget(pushButton</span></font><span style="font-style: normal;"><font size="2">, i, 3);
  172. 163     }
  173. 164     pushButton[0]->setEnabled(false);
  174. 165
  175. 166     /* 布局 */
  176. 167     vboxLayout->addWidget(textBrowser);
  177. 168     vboxLayout->addWidget(lineEdit);
  178. 169     funcWidget->setLayout(gridLayout);
  179. 170     vboxLayout->addWidget(funcWidget);
  180. 171     vboxLayout->addWidget(label[3]);
  181. 172     mainWidget->setLayout(vboxLayout);
  182. 173     this->setCentralWidget(mainWidget);
  183. 174
  184. 175     /* 设置文本 */
  185. 176     textBrowser->setPlaceholderText("系统时间 帧ID 长度 数据");
  186. 177     lineEdit->setText("123 aa 77 66 55 44 33 22 11");
  187. 178     label[3]->setText(tr("未连接!"));
  188. 179
  189. 180     connect(pushButton[1], SIGNAL(clicked()),
  190. 181             this, SLOT(connectDevice()));
  191. 182     connect(pushButton[0], SIGNAL(clicked()),
  192. 183             this, SLOT(sendFrame()));
  193. 184 }
  194. 185
  195. 186 /* 从系统中读取可用的插件,并显示到comboBox[0] */
  196. 187 void MainWindow::pluginItemInit()
  197. 188 {
  198. 189     comboBox[0]->addItems(QCanBus::instance()->plugins());
  199. 190     for (int i = 0; i < QCanBus::instance()->plugins().count(); i++) {
  200. 191         if (QCanBus::instance()->plugins().at(i) == "socketcan")
  201. 192             comboBox[0]->setCurrentIndex(i);
  202. 193     }
  203. 194     connect(comboBox[0], SIGNAL(currentIndexChanged(int)),
  204. 195             this, SLOT(pluginChanged(int)));
  205. 196 }
  206. 197
  207. 198 /* 插件类型改变 */
  208. 199 void MainWindow::pluginChanged(int)
  209. 200 {
  210. 201     QList<QCanBusDeviceInfo> interfaces;
  211. 202     comboBox[1]->clear();
  212. 203     /* 当我们改变插件时,我们同时需要将可用接口,从插件类型中读取出来 */
  213. 204     interfaces = QCanBus::instance()
  214. 205             ->availableDevices(comboBox[0]->currentText());
  215. 206     for (const QCanBusDeviceInfo &info : qAsConst(interfaces)) {
  216. 207         comboBox[1]->addItem(info.name());
  217. 208     }
  218. 209 }
  219. 210
  220. 211 /* 初始化一些常用的比特率,can的比特率不是随便设置的,有相应的计算公式 */
  221. 212 void MainWindow::bitrateItemInit()
  222. 213 {
  223. 214     const QList<int> rates = {
  224. 215         10000, 20000, 50000, 100000, 125000,
  225. 216         250000, 500000, 800000, 1000000
  226. 217     };
  227. 218
  228. 219     for (int rate : rates)
  229. 220         comboBox[2]->addItem(QString::number(rate), rate);
  230. 221
  231. 222     /* 默认初始化以1000000比特率 */
  232. 223     comboBox[2]->setCurrentIndex(8);
  233. 224 }
  234. 225
  235. 226 /* 连接或断开CAN */
  236. 227 void MainWindow::connectDevice()
  237. 228 {
  238. 229     if (pushButton[1]->text() == "连接CAN") {
  239. 230         /* Qt中的QCanBusDevice::BitRateKey不能设置比特率 */
  240. 231         QString cmd1 = tr("ifconfig %1 down")
  241. 232                 .arg(comboBox[1]->currentText());
  242. 233         QString cmd2 =
  243. 234                 tr("ip link set up %1 type can bitrate %2 restart-ms 100")
  244. 235                 .arg(comboBox[1]->currentText())
  245. 236                 .arg(comboBox[2]->currentText());
  246. 237         /* 使用系统指令以设置的比牲率初始化CAN */
  247. 238         system(cmd1.toStdString().c_str());
  248. 239         system(cmd2.toStdString().c_str());
  249. 240
  250. 241         QString errorString;
  251. 242         /* 以设置的插件名与接口实例化canDevice */
  252. 243         canDevice = QCanBus::instance()->
  253. 244                 createDevice(comboBox[0]->currentText(),
  254. 245                 comboBox[1]->currentText(),
  255. 246                 &errorString);
  256. 247
  257. 248         if (!canDevice) {
  258. 249             label[3]->setText(
  259. 250                         tr("Error creating device '%1', reason: '%2'")
  260. 251                         .arg(comboBox[0]->currentText())
  261. 252                     .arg(errorString));
  262. 253             return;
  263. 254         }
  264. 255
  265. 256         /* 连接CAN */
  266. 257         if (!canDevice->connectDevice()) {
  267. 258             label[3]->setText(tr("Connection error: %1")
  268. 259                               .arg(canDevice->errorString()));
  269. 260             delete canDevice;
  270. 261             canDevice = nullptr;
  271. 262
  272. 263             return;
  273. 264         }
  274. 265
  275. 266         connect(canDevice, SIGNAL(framesReceived()),
  276. 267                 this, SLOT(receivedFrames()));
  277. 268         connect(canDevice,
  278. 269                 SIGNAL(errorOccurred(QCanBusDevice::CanBusError)),
  279. 270                 this,
  280. 271                 SLOT(canDeviceErrors(QCanBusDevice::CanBusError)));
  281. 272         /* 将连接信息插入到label */
  282. 273         label[3]->setText(
  283. 274                     tr("插件类型为: %1, 已连接到 %2, 比特率为 %3 kBit/s")
  284. 275                     .arg(comboBox[0]->currentText())
  285. 276                 .arg(comboBox[1]->currentText())
  286. 277                 .arg(comboBox[2]->currentText().toInt() / 1000));
  287. 278         pushButton[1]->setText("断开CAN");
  288. 279         /* 使能/失能 */
  289. 280         pushButton[0]->setEnabled(true);
  290. 281         comboBox[0]->setEnabled(false);
  291. 282         comboBox[1]->setEnabled(false);
  292. 283         comboBox[2]->setEnabled(false);
  293. 284     } else {
  294. 285         if (!canDevice)
  295. 286             return;
  296. 287
  297. 288         /* 断开连接 */
  298. 289         canDevice->disconnectDevice();
  299. 290         delete canDevice;
  300. 291         canDevice = nullptr;
  301. 292         pushButton[1]->setText("连接CAN");
  302. 293         pushButton[0]->setEnabled(false);
  303. 294         label[3]->setText(tr("未连接!"));
  304. 295         comboBox[0]->setEnabled(true);
  305. 296         comboBox[1]->setEnabled(true);
  306. 297         comboBox[2]->setEnabled(true);
  307. 298     }
  308. 299 }
  309. 300
  310. 301 void MainWindow::canDeviceErrors(QCanBusDevice::CanBusError error) const
  311. 302 {
  312. 303     /* 错误处理 */
  313. 304     switch (error) {
  314. 305     case QCanBusDevice::ReadError:
  315. 306     case QCanBusDevice::WriteError:
  316. 307     case QCanBusDevice::ConnectionError:
  317. 308     case QCanBusDevice::ConfigurationError:
  318. 309     case QCanBusDevice::UnknownError:
  319. 310         label[3]->setText(canDevice->errorString());
  320. 311         break;
  321. 312     default:
  322. 313         break;
  323. 314     }
  324. 315 }
  325. 316</font>
  326. </span></span>
复制代码

       第9~10行,使用系统的CAN硬件,必须初始化系统的CAN。在项目里添加相应的开启CAN的指令。第一个指令是先关闭本地的CAN,因为只有关闭CAN,才能以新的速率再开启。
       第12~22行,构造函数里界面初始化,以及QComboBox里的项初始化。
       第29~42行,格式化帧处理函数。        
       第45~67行,发送消息,将lineEdit的文本进行处理后,第一个作为CAN的帧ID,后面8个数据作为需要要发送的数据。每帧只能发送8个数据。
       第70~94行,接收消息,读取帧并格式化处理,显示到textBrowser里。
       第96~184行,界面布局初始化设置,在嵌入式里,根据实际的屏的大小,设置全屏显示。其中我们用到垂直布局和网格布局,如果布局这方面内容理解不了,请回到第七章7.5小节学习布局内容。
       第187~196行,可用插件初始化,检查系统QCanBus提供的插件。在Linux里使用的插件类型是SocketCAN, SocketCAN插件支持Linux内核和用于所用CAN硬件的SocketCAN设备驱动程序。下面程序遍历可用的CAN插件,并设置socketcan为当前插件。注意,只能使用SocketCAN访问本地硬件CAN,其他插件是不同类型的CAN驱动程序所使用的。请自行测试。
       第199~209行,当插件类型改变时,我们需要更新可用接口。
第212~224行,常用的比特率初始化。
       第227~299行,连接/断开CAN,很遗憾Qt的QCanBusDevice::BitRateKey不能设置比特率,因为系统的CAN需要使用ip指令以一个比特率才能进行初始化,Qt需要系统CAN起来才能进行操作。所以需要使用了系统系统指令设置CAN。
       第301~315行,错误处理,CAN设备可能遇到错误,打印错误的信息。
18.3 程序运行效果
       在Ubuntu上运行 界面效果如下,因为Ubutnu没有CAN设备,所以在可用接口处是不可选的。请把程序交叉编译到开发板上运行。与CAN仪器以相同的比特率通信,插件类型默认是(必须是)socketcan,可用接口为can0,即可发送消息与接收消息。
       下图最上面的是接收消息框,“123 aa 77 66 55 44 33 22 11”这个是需要发送的帧,“123”为帧ID,后面的为8个字节数据,每个字节需要以空格隔开。点击连接后,发送按钮才能使用。

CAN Bus16230.png

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 22:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表