am335x Qt SocketCAN Demo hacking

简介: /*********************************************************************************** * am335x Qt SocketCAN Demo hacking * 说明: * 本源代码来自OK335xS,主要是为分析如何在Qt中使用SocketCAN的这种通信方式。
/***********************************************************************************
 *                    am335x Qt SocketCAN Demo hacking
 *  说明:
 *      本源代码来自OK335xS,主要是为分析如何在Qt中使用SocketCAN的这种通信方式。
 *
 *                                          2015-9-12 晴 深圳 南山平山村 曾剑锋
 **********************************************************************************/


cat main.c #include <QtGui/QApplication> #include "mainwindow.h" #include "myinputpanelcontext.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); /** * 创建软键盘 */ MyInputPanelContext *ic = new MyInputPanelContext; /** * This function replaces the QInputContext instance used by the application with inputContext. * Qt takes ownership of the given inputContext. * * 设置软键盘 */ a.setInputContext(ic); //将输入上下文与应用程序关联 MainWindow w; /** * Qt::WindowMaximizeButtonHint: * Adds a maximize button. On some platforms this implies Qt::WindowSystemMenuHint for it to work. * Qt::WindowMinimizeButtonHint: * Adds a minimize button. On some platforms this implies Qt::WindowSystemMenuHint for it to work. */ w.setWindowFlags(w.windowFlags()& ~Qt::WindowMaximizeButtonHint& ~Qt::WindowMinimizeButtonHint); w.showMaximized(); w.show(); return a.exec(); } cat mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QProcess> #include <sys/ioctl.h> #include <net/if.h> #include <linux/can.h> #include "thread.h" #include <QButtonGroup> /** * 引入界面文件生成的UI类 */ namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected: void moveEvent(QMoveEvent *); // 界面移动事件 void resizeEvent(QResizeEvent *); // 界面重绘大小事件 void closeEvent(QCloseEvent *); // 界面关闭事件 private slots: void on_send_clicked(); // 发送按钮点击槽 void msg(QString str); // 信息处理信号槽 void stopcan(int v); // 停止can信号槽 void startcan(int v); // 开始can信号槽 void on_can0_toggled(bool checked); // can0 被点击翻转信号槽 void on_can1_toggled(bool checked); // can1 被点击翻转信号槽 private: Ui::MainWindow *ui; // 声明图形界面指针 int socket; // can socket 描述符 struct sockaddr_can addr; // can socket 地址结构体 Thread *t; // 线程 QButtonGroup* btg; // 按钮 }; #endif // MAINWINDOW_H cat mainwindow.c #include <sys/ioctl.h> #include <fcntl.h> #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <unistd.h> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), // 构造函数初始化父类构造函数 ui(new Ui::MainWindow) // 创建ui实体,并赋值 { ui->setupUi(this); // 设置将图形界面放置在哪个对象上 btg = new QButtonGroup; // 创建分组,多选一 btg->addButton(ui->can0,0); btg->addButton(ui->can1,1); startcan(0); } MainWindow::~MainWindow() { /** * 这里让人怀疑,都已经删除了ui界面,button group又怎么能够获取到ui里面的checkedId呢? * 唯一的解释就是button group里面保存了最后一次toggle事件获取的checkedId值,而不是运行 * checkedId()的时候去获取checkedId */ delete ui; stopcan(btg->checkedId()); } void MainWindow::msg(QString str) { /** * 将获取到的信息放到显示文本框的最后去 */ ui->label->append(str); } void MainWindow::on_send_clicked() { /** * struct can_frame - basic CAN frame structure * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition * @can_dlc: frame payload length in byte (0 .. 8) aka data length code * N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1 * mapping of the 'data length code' to the real payload length * @data: CAN frame payload (up to 8 byte) * * struct can_frame { * canid_t can_id; // 32 bit CAN_ID + EFF/RTR/ERR flags * __u8 can_dlc; // frame payload length in byte (0 .. CAN_MAX_DLEN) * __u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); * }; */ struct can_frame frame; /** * 获取将要发送的文本内容 * Returns a std::string object with the data contained in this QString. * The Unicode data is converted into 8-bit characters using the toUtf8() function. */ std::string str=ui->edit->text().toStdString(); /** * 如果文本的长度大于8,那么将给出提示信息,并直接返回,不发送数据 */ if(str.length() > 8) { QMessageBox::about(this,"error","length of send string must less than 8 bytes"); return; } /** * 默认发送的can id是0x123 * * 扩展格式识别符由 29 位组成。其格式包含两个部分:11 位基本 ID、18 位扩展 ID。 * Controller Area Network Identifier structure: * * bit 0-28 : CAN识别符 (11/29 bit) * bit 29 : 错误帧标志 (0 = data frame, 1 = error frame) * bit 30 : 远程发送请求标志 (1 = rtr frame) * bit 31 : 帧格式标志 (0 = standard 11 bit, 1 = extended 29 bit) * * typedef __u32 canid_t; * * struct can_frame { * canid_t can_id; // 32 bit CAN_ID + EFF/RTR/ERR flags * __u8 can_dlc; // 数据长度: 0 .. 8 * __u8 data[8] __attribute__((aligned(8))); * }; */ frame.can_id = 0x123; /** * Returns a pointer to an array that contains a null-terminated sequence of * characters (i.e., a C-string) representing the current value of the string object. * This array includes the same sequence of characters that make up the value of * the string object plus an additional terminating null-character ('\0') at the end. */ strcpy((char*)frame.data, str.c_str()); /** * 目前猜测:dlc --> data length count * 于是可以很好的解释:can 发送的数据长度,是按字节算的 */ frame.can_dlc = str.length(); /** * Send N bytes of BUF on socket FD to peer at address ADDR (which is * ADDR_LEN bytes long). Returns the number sent, or -1 for errors. * * This function is a cancellation point and therefore not marked with * __THROW. * * extern ssize_t sendto (int __fd, __const void *__buf, size_t __n, * int __flags, __CONST_SOCKADDR_ARG __addr, * socklen_t __addr_len); */ sendto(socket,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,sizeof(addr)); } void MainWindow::moveEvent(QMoveEvent *) { /** * 让测试窗口不会被移动 */ this->move(QPoint(0,0)); } void MainWindow::resizeEvent(QResizeEvent *) { /** * 让窗口最大化显示 */ this->showMaximized(); } void MainWindow::closeEvent(QCloseEvent *) { /** * 直接退出,不用关闭can口么?也就是说程序会在真正推出前,先解析掉所有当前生成的类实体? */ exit(0); } void MainWindow::startcan(int v) { /** * 从提示信息可以看出,使用125000作为默认的波特率 */ if(v == 0) { system("canconfig can0 bitrate 125000 ctrlmode triple-sampling on"); system("canconfig can0 start"); } else { system("canconfig can1 bitrate 125000 ctrlmode triple-sampling on"); system("canconfig can1 start"); } /** * Create a new socket of type TYPE in domain DOMAIN, using * protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. * Returns a file descriptor for the new socket, or -1 for errors. * * extern int socket (int __domain, int __type, int __protocol) __THROW; * * #define PF_CAN 29 // Controller Area Network. * * SOCK_RAW = 3, // Raw protocol interface. * #define SOCK_RAW SOCK_RAW * * particular protocols of the protocol family PF_CAN * #define CAN_RAW 1 // RAW sockets * */ socket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW); /** * struct ifreq * { * # define IFHWADDRLEN 6 * # define IFNAMSIZ IF_NAMESIZE * union * { * char ifrn_name[IFNAMSIZ]; // Interface name, e.g. "en0". * } ifr_ifrn; * * union * { * struct sockaddr ifru_addr; * struct sockaddr ifru_dstaddr; * struct sockaddr ifru_broadaddr; * struct sockaddr ifru_netmask; * struct sockaddr ifru_hwaddr; * short int ifru_flags; * int ifru_ivalue; * int ifru_mtu; * struct ifmap ifru_map; * char ifru_slave[IFNAMSIZ]; // Just fits the size * char ifru_newname[IFNAMSIZ]; * __caddr_t ifru_data; * } ifr_ifru; * }; * # define ifr_name ifr_ifrn.ifrn_name // interface name * # define ifr_hwaddr ifr_ifru.ifru_hwaddr // MAC address * # define ifr_addr ifr_ifru.ifru_addr // address * # define ifr_dstaddr ifr_ifru.ifru_dstaddr // other end of p-p lnk * # define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address * # define ifr_netmask ifr_ifru.ifru_netmask // interface net mask * # define ifr_flags ifr_ifru.ifru_flags // flags * # define ifr_metric ifr_ifru.ifru_ivalue // metric * # define ifr_mtu ifr_ifru.ifru_mtu // mtu * # define ifr_map ifr_ifru.ifru_map // device map * # define ifr_slave ifr_ifru.ifru_slave // slave device * # define ifr_data ifr_ifru.ifru_data // for use by interface * # define ifr_ifindex ifr_ifru.ifru_ivalue // interface index * # define ifr_bandwidth ifr_ifru.ifru_ivalue // link bandwidth * # define ifr_qlen ifr_ifru.ifru_ivalue // queue length * # define ifr_newname ifr_ifru.ifru_newname // New name * # define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0) * # define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0) * # define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0) * * SIOCGIFINDEX: * Retrieve the interface index of the interface into ifr_ifindex. */ struct ifreq ifr; strcpy((char *)(ifr.ifr_name),v == 0 ? "can0" : "can1"); ioctl(socket,SIOCGIFINDEX,&ifr); /** * 绑定socket */ addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(socket,(struct sockaddr*)&addr,sizeof(addr)); /** * 这里是存在问题,每次线程并没有关闭,而是直接不管,可能导致一些问题 * 从后续的代码可以看出,每次都已经停止了线程,delete了对象实体。 */ t = NULL; /** * 创建线程,并将socket文件描述符作为参数传入线程,主要作为接受数据线程 */ t = new Thread(socket); /** * 用于处理线程发出的信号 */ connect(t,SIGNAL(msg(QString)),this,SLOT(msg(QString))); /** * 开启线程 */ t->start(); } void MainWindow::stopcan(int v) { /** * 关闭对应的can之前,先关闭对应socket接受线程 */ if(t) { t->stop(); t->deleteLater(); } /** * 关闭socket文件描述符 */ ::close(socket); /** * 给出相关的提示信息 */ if(v == 0) system("canconfig can0 stop"); else system("canconfig can1 stop"); } void MainWindow::on_can0_toggled(bool checked) { /** * 根据对应的情况,打开,或者关闭对应的can设备 */ if(checked) { stopcan(1); startcan(0); } } void MainWindow::on_can1_toggled(bool checked) { /** * 根据对应的情况,打开,或者关闭对应的can设备 */ if(checked) { stopcan(0); startcan(1); } }

 

目录
相关文章
|
4月前
自己动手写QT多线程demo
本文是作者关于如何编写Qt多线程demo的教程,介绍了如何实现多线程功能,包括可暂停和继续的功能。文章提供了部分示例代码,展示了如何创建线程类、启动和管理线程,以及线程间的通信。同时,还提供了相关参考资料和免费下载链接。
103 0
|
Ubuntu 编译器 网络安全
RK3568开发笔记(七):在宿主机ubuntu上搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试
在之前的博文中已经搭建好了一个比较完善的ubuntu宿主机,都很完善了但是发现没有Qt交叉编译开发环境,所以还需要搭建一套Qt交叉编译开发环境。
|
XML 数据管理 编译器
Qt+GDAL开发笔记(二):在windows系统msvc207x64编译GDAL库、搭建开发环境和基础Demo
上一篇使用mingw32版本的gdal,过程曲折,为更好的更方便搭建环境,在windows上msvc方式对于库比较友好。
|
XML 数据管理 Linux
Qt+GDAL开发笔记(一):在windows系统mingw32编译GDAL库、搭建开发环境和基础Demo
麒麟系统上做全球北斗定位终端开发,调试工具要做一个windows版本方便校对,北斗GPS发过来的是大地坐标,应用需要的是经纬度坐标,所以需要转换,可以使用公式转换,但是之前涉及到了另一个shang市公司项目使用WG,最终选择了GDAL库进行转换。
|
Ubuntu IDE Java
Qt+QtWebApp开发笔记(一):QtWebApp介绍、下载和搭建基础封装http轻量级服务器Demo
在arm上做了Qt的应用程序,为了在局域网实现web页的访问方式来配置arm上Qt的程序,局域网轻量级http服务器是很好的实现方式之一,有机会做国产麒麟上Qt的http服务器,正好接触到了QtWebApp可以实现。   本篇实战解说QtWebApp的轻量级Demo。   本篇篇幅较长,为了保持基础的完整性将必要的东西都放在本篇。
|
JavaScript 前端开发 C++
JavaScript 调用 C++/Qt 工程(附有代码 + demo)
JavaScript 调用 C++/Qt 工程(附有代码 + demo)
|
IDE 编译器 开发工具
统信UOS系统开发笔记(四):从Qt源码编译安装之编译安装QtCreator4.11.2,并配置编译测试Demo
上一篇已经从Qt源码编译了Qt,那么Qt开发的IDE为QtCreator,本篇从源码编译安装QtCreator,并配置好构建套件,运行Demo并测试。
|
Java C++
Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试
上一篇使用QtWebApp的基于Qt的轻量级http服务器实现了一个静态网页返回的Demo,网页服务器很重要的就是日志,因为在服务器类上并没有直接返回,所以,本篇先把日志加上。
|
关系型数据库 MySQL 数据库连接
Qt+MySql开发笔记:Qt5.9.3的msvc2017x64版本编译MySql8.0.16版本驱动并Demo连接数据库测试
mysql驱动版本msvc2015x32版本调好, mysql的mingw32版本的驱动上一个版本编译并测试好,有些三方库最低支持vs2017,所以只能使用msvc2017x64,基于Qt5.9.3,于是本篇编译mysql驱动的msvc2017x64版本,满足当前的特定需求,这次过程有点费劲,可能是Qt的版本低于Qt5.12,继续无保留分享出来。   本篇主要描述Qt5.9.3 msvc2017x64 + mysql8.0.16的驱动编译过程。
|
数据可视化
Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解
qt提供了q3d进行三维开发,虽然这个框架没有得到大量运用也不是那么成功,性能上也有很大的欠缺,但是普通的点到为止的应用展示还是可以的。其中就包括华丽绚烂的三维图表,数据量不大的时候是可以使用的。前面介绍了基础的q3d散点图、柱状图,本篇介绍基础的三维曲面图。Q3DSurface类提供了渲染3D曲面图的方法。该类使开发人员能够渲染3D表面图,并通过自由旋转场景来查看它们。可以通过QSurface3DSeries控制曲面的视觉财产,例如绘制模式和着色。