当前位置: 首页 > news >正文

北京电商网站开发价格江苏企业展厅设计公司

北京电商网站开发价格,江苏企业展厅设计公司,友情链接英语,制作一个动态企业网站本文工作#xff1a; 1、Linux驱动与应用程序编写#xff1a;使用了设备树、中断、异步通知知识点#xff0c;实现了红外对射状态的异步信息提醒。 2、QT程序编写#xff1a;自定义了一个“文本指示灯”类#xff0c;并放置在QMainWidget的StatusBus中。 3、C与C混合编程与… 本文工作 1、Linux驱动与应用程序编写使用了设备树、中断、异步通知知识点实现了红外对射状态的异步信息提醒。 2、QT程序编写自定义了一个“文本指示灯”类并放置在QMainWidget的StatusBus中。 3、C与C混合编程与调试将Linux C下的面向过程转化为QT C的面向对象。但是Linux C下signal函数需要使用static函数作为传入参数但是C中static的用法与C语言不一样因此在C中对抽象出的类进行了适配与修改。 参考资料 1、《正点原子I.MX6U嵌入式Linux驱动开发指南V1.6》 2、C/C static关键字详解最全解析static是什么static如何使用static的常考面试题-CSDN博客 3、【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序QT捕获Linux系统信号测试信号通知 - ARM技术论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com) 4、Qt 封装一个简单的LED(指示灯)控件_qt 指示灯-CSDN博客 本文不对基础知识进行讲解因此阅读本文需要一定的驱动/QT基础。 开发板IMX6ULL 内核版本4.1.15 QT版本5.12 一、项目需求与效果 1、项目需求 项目中的一个简单传感器使用红外对射检查物品是否放入了盒子中并在QT界面的statusBus中使用指示灯的形式进行显示与说明。 2、代码效果 红外对射-Linux驱动-QT 代码效果屏幕左下角文本指示灯的变化 二、Linux驱动与应用程序编写 1、使用引脚说明 本次所使用的引脚为GPIO2_2查看了I.MX6ULL核心板对GPIO的描述该引脚可复用到GPIO1_IO02引脚上因此我们需要先修改下设备树的文件。 2、修改设备树文件 在根节点目录下先添加节点 gpio_infrared {compatible csx-gpio-infrared;pinctrl-names default;pinctrl-0 pinctrl_infrared;infrared-gpio gpio1 2 GPIO_ACTIVE_LOW;interrupts IRQ_TYPE_EDGE_BOTH;status okay;}; 项目中我们需要极度关注是否有物体存入进拿进取出都需要通知用户因此需要中断类型使用IRQ_TYPE_EDGE_BOTH。 其中的pinctrl_infrared为 pinctrl_infrared: infraredgrp {fsl,pins MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x10B0;}; 修改完之后执行make dtbs更换开发板的设备树之后我们使用 ls /proc/device-tree查看是否有我们增加的设备树节点。 如上图设备树修改成功接下来就是编写驱动文件。 3、驱动文件编写 1结构体编写 /* 设备中断结构体 */ struct irq_gpio_infrared{int gpio; /* gpio */int irqnum; /* 中断号 */unsigned char value; /* 读取的值 */char name[10]; /* 名字 */irqreturn_t (*handler)(int,void *); /* 中断服务函数 */};/* gpioinfrared设备结构体 */ struct gpio_infrared_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */struct device_node *nd; /* 设备节点 */struct irq_gpio_infrared irqgpioinfrared; /* 中断结构体 */struct fasync_struct *async_queue; /* 异步相关结构体 */ };struct gpio_infrared_dev gpioinfrared; /* infrared设备 */ 代码中我们需要注意的是使用了中断结构体用于红外对射检测到物体时通知用户在各种通知方法中使用异步通知是最可行的其他方法需要占据大量的cpu资源不适合本次的应用场景因此中断服务其实就是使用异步通知对用户进行通知因此我们还需要使用异步通知的结构体。 2获取设备树节点的信息【设备树API、GPIO子系统API】 /* 1、获取设备节点gpioinfrared */gpioinfrared.nd of_find_node_by_path(/gpio_infrared);if(gpioinfrared.nd NULL) {printk(gpioinfrared node not find!\r\n);return -EINVAL;} else {printk(gpioinfrared node find!\r\n);}/* 2、 获取设备树中的gpio属性得到GPIO所使用的编号 */gpioinfrared.irqgpioinfrared.gpio of_get_named_gpio(gpioinfrared.nd, infrared-gpio, 0);if(gpioinfrared.irqgpioinfrared.gpio 0) {printk(cant get infrared-gpio);return -EINVAL;}else{printk(infrared-gpio num %d\r\n, gpioinfrared.irqgpioinfrared.gpio);}/* 3、初始化使用的gpio */memset(gpioinfrared.irqgpioinfrared.name,0,sizeof(gpioinfrared.irqgpioinfrared.name));sprintf(gpioinfrared.irqgpioinfrared.name,gpioinfrared%d,i);ret gpio_direction_input(gpioinfrared.irqgpioinfrared.gpio);if(ret 0) {printk(cant set gpio!\r\n);} 3中断申请 /* 4、设置中断模式返回中断号 */gpioinfrared.irqgpioinfrared.irqnum gpio_to_irq(gpioinfrared.irqgpioinfrared.gpio);printk(gpio:%d,irq:%d,gpioinfrared.irqgpioinfrared.gpio,gpioinfrared.irqgpioinfrared.irqnum);/* 申请中断 */gpioinfrared.irqgpioinfrared.handler goio_infrared_handler;ret request_irq(gpioinfrared.irqgpioinfrared.irqnum, gpioinfrared.irqgpioinfrared.handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,gpioinfrared.irqgpioinfrared.name, gpioinfrared);if(ret 0){printk(irq %d request fail infrared!\r\n, gpioinfrared.irqgpioinfrared.irqnum);printk(irq_name: %s\r\n,gpioinfrared.irqgpioinfrared.name);return -EFAULT;}if (ret-EBUSY){printk(irq already apply\r\n);}4编写红外对射的中断函数 /*GPIO红外中断服务函数用于发送异步信息 */ static irqreturn_t goio_infrared_handler(int irq,void *dev_id) {struct gpio_infrared_dev *dev (struct gpio_infrared_dev *)dev_id;printk(irq happend!\r\n);kill_fasync(dev-async_queue, SIGIO, POLL_IN);return IRQ_RETVAL(IRQ_HANDLED); }如上述所说就是用于发送异步通信的在这里还使用内核进行打印输出方便检测。 5编写异步通信函数 static int imx6uirq_fasync(int fd, struct file *filp, int on) {struct gpio_infrared_dev *dev (struct gpio_infrared_dev *)filp-private_data;return fasync_helper(fd, filp, on, dev-async_queue); }static int imx6uirq_release(struct inode *inode, struct file *filp) {return imx6uirq_fasync(-1, filp, 0); } 6编写用户层数据接口 /** description : 从设备读取数据 * param - filp : 要打开的设备文件(文件描述符)* param - buf : 返回给用户空间的数据缓冲区* param - cnt : 要读取的数据长度* param - offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/ static ssize_t infrared_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) {int ret 0;unsigned char value-1;struct gpio_infrared_dev *dev (struct gpio_infrared_dev *)filp-private_data;value gpio_get_value(dev-irqgpioinfrared.gpio);printk(gpioinfrared read:%d!\r\n,value);ret copy_to_user(buf, value, sizeof(value));return ret; } 重点的内容都介绍完了接下来就是检查下是否正确驱动编写是否正确了make生成.ko文件后传到开发板使用insmod命令会有如下输入 此时我们将红外进行对射后就会有如下输出 即驱动编写正确。接下来我们先编写应用程序的代码接收异步通知的提醒。 4、Linux C应用程序代码编写 应用程序接收异步通知需要以下三个步骤 1使用signal函数设置驱动程序所使用的信号处理函数 2将当前应用程序的内核号告知内核 3开启异步通知 signal(SIGIO, sigio_signal_func); /* 设置信号SIGIO的处理函数 */ fcntl(fd, F_SETOWN, getpid()); /* 设置当前进程接收SIGIO信号 */ flags fcntl(fd, F_GETFL); /* 获取当前的进程状态 */ fcntl(fd, F_SETFL, flags | FASYNC); /* 设置进程启用异步通知功能 */ 在此处的异步处理函数就很简单了使用GPIO子系统的API获取当前的引脚数值但是值得一提的是 signal函数的传入函数必须是使用static进行修饰的在后面与C代码对接时就是因为static增加了不少的限制。 /** SIGIO信号处理函数* param - signum : 信号值* return : 无*/ static void sigio_signal_func(int signum) {int err 0;unsigned int infrared_value 0;err read(fd, infrared_value, sizeof(infrared_value));if(err 0) {/* 读取错误 */printf(read error!\r\n);} else {printf(sigio signal:%d!\r\n,infrared_value);}} 接下来我们在进行交叉编译之后 arm-linux-gnueabihf-gcc infrared_asy.c -o infrared_asy 进行测试一下。 上图所示测试成功 三、C Qt程序编写 1、自定义LedWithText 先根据自己的需要对参考资料第四点对自封装的LED控件进行了简化类名为QSimpleLed QSimpleLed.cpp文件 #include qsimpleled.h#include QGradient #include QPainter #include QDebug #include QColorQSimpleLed::QSimpleLed(QWidget *parent, QColor color,int radius): QLabel(parent), mColor(color) {setMinimumSize(radius, radius);setMaximumSize(radius,radius); }void QSimpleLed::setStates(QSimpleLed::LEDSTATES states) {switch (states) {case ON:resetStatus();mStates ON;break;case OFF:resetStatus();break;case BLINK:resetStatus();if (!mBlinkTimer) {mBlinkTimer new QTimer(this);connect(mBlinkTimer, QTimer::timeout, this, QSimpleLed::onBlinkTimerTimeout);}mBlinkTimer-setInterval(mInterval);mBlinkTimer-start();mStates BLINK;break;default:qDebug() LED - unknown states!!!;}update(); }void QSimpleLed::setColor(QColor color) {mColor color; }void QSimpleLed::paintEvent(QPaintEvent *event) {Q_UNUSED(event);qreal realSize qMin(width(), height());QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing); // 反锯齿painter.translate(width()/2, height()/2); // 绘点移到控件中心处if(blinkState)painter.setBrush(QBrush(QColor(111,111,111)));elsepainter.setBrush(QBrush(mColor));painter.drawEllipse(QPointF(0, 0), realSize/2, realSize/2);}void QSimpleLed::resizeEvent(QResizeEvent *event) {Q_UNUSED(event);update(); }void QSimpleLed::onBlinkTimerTimeout() {blinkState !blinkState;update(); }void QSimpleLed::resetStatus() {if (mBlinkTimer mBlinkTimer-isActive()) {mBlinkTimer-stop();}mStates OFF; }QSimpleLed.h文件 #ifndef QSIMPLELED_H #define QSIMPLELED_H#include QLabel #include QTimer #include QColorclass QSimpleLed : public QLabel {Q_OBJECTpublic:enum LEDSTATES {ON 0,OFF 1,BLINK 2,};QSimpleLed(QWidget *parent nullptr, QColor color Qt::green,int radius16);void setStates(LEDSTATES states);void setInterval(int msec) { mInterval msec; }void setColor(QColor color);protected:virtual void paintEvent(QPaintEvent *event) override;virtual void resizeEvent(QResizeEvent *event) override;private slots:void onBlinkTimerTimeout();private:void resetStatus();LEDSTATES mStates OFF;QColor mColor;QTimer *mBlinkTimer nullptr;int mInterval 500;bool blinkState false;};#endif // QSIMPLELED_H再根据自己的需求自定义一个widget用于存放led左与text右我们在外部只需要传入led的状态、颜色、文本的内容即可该类的名称为LedWithText。 LedWithText.cpp #include ledwithtext.h #include QFont #include QDebugledWithText::ledWithText(QWidget *parent, QColor color, const QString text):QWidget(parent) {ledLabel new QSimpleLed(this);ledLabel-setColor(color); // ledLabel-setStyleSheet(border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0););textLabel new QLabel(text,this);textLabel-adjustSize();textLabel-setAlignment(Qt::AlignVCenter);textLabel-setMinimumHeight(ledLabel-height()5);textLabel-setVisible(!text.isEmpty());QFont ft;ft.setPointSize(14);textLabel-setFont(ft);layout new QHBoxLayout(this);layout-addWidget(ledLabel);layout-addWidget(textLabel);layout-setSpacing(5);setLayout(layout);int adjustWith ledLabel-width()textLabel-width()25;int adjustHeight textLabel-height()10; // qDebug()adjustHeightadjustWith;setGeometry(0,0,adjustWith,adjustHeight); }ledWithText::~ledWithText() {delete ledLabel;delete textLabel; }void ledWithText::setLedColor(QColor color) {ledLabel-setColor(color); }void ledWithText::setLedState(QSimpleLed::LEDSTATES states) {ledLabel-setStates(states); }void ledWithText::setText(const QString text) {textLabel-setText(text);textLabel-adjustSize();textLabel-setVisible(!text.isEmpty());int adjustWith ledLabel-width()textLabel-width()25;int adjustHeight textLabel-height()10;setGeometry(0,0,adjustWith,adjustHeight); }void ledWithText::setTextFontSize(int size) {QFont ft;ft.setPointSize(size);textLabel-setFont(ft);textLabel-adjustSize();int adjustWith ledLabel-width()textLabel-width()25;int adjustHeight textLabel-height()10;setGeometry(0,0,adjustWith,adjustHeight); }LedWithText.h #ifndef LEDWITHTEXT_H #define LEDWITHTEXT_H #include QLabel #include ui_optimize/qsimpleled.h #include QWidget #include QHBoxLayoutclass ledWithText:public QWidget {Q_OBJECT public:ledWithText(QWidget *parent nullptr, QColor color Qt::green, const QString text );~ledWithText();void setLedColor(QColor color);void setLedState(QSimpleLed::LEDSTATES states);void setText(const QString text);void setTextFontSize(int size);private:QSimpleLed *ledLabel;QLabel *textLabel;QHBoxLayout *layout; };#endif // LEDWITHTEXT_H2、使用MainWidget的StatusBus存放文本指示灯 我们要把这些控件放置在状态栏中不管切换到什么界面都可以看到就不需要一直重复写代码了因此我们需要使用MainWidget的StatusBusWidget类没有StatusBus不要用错。 void MainWindow::state_bus_init() {device_connect_label new ledWithText(this,Qt::green,设备正在连接);device_connect_label-setLedColor(Qt::blue);device_connect_label-setLedState(QSimpleLed::BLINK);device_connect_label-setTextFontSize(10);ui-statusbar-addWidget(device_connect_label);device_place_label new ledWithText(this,Qt::green,设备未放置);device_place_label-setTextFontSize(10);ui-statusbar-addWidget(device_place_label); } 就可以看到如下效果了。我们自定义的LedWithText类的效果就显示在左下角了。 3、Qt接受异步通知并根据结果改变文本指示灯 按道理最简单的做法这一步只需要将应用层的代码搬过来就可以但是在上文我们提到在Linux C的应用程序中signal函数需要传入static修饰的函数但是Qt使用C语言想要将其转化为类而不是面向过程就需要解决static在C语言和C的差异。 #include infrareddev.hInfraredDev::InfraredDev(QObject *parent) : QObject(parent) {fd open(DEVNAME, O_RDWR);if (fd 0) {qDebug()Cant open file :DEVNAME;}else{register_infrared_asy();qDebug()infrared:init succeed!;}}InfraredDev::~InfraredDev() {if(fd){close(fd);} }void InfraredDev::set_dev_name(char *name) {dev_name name; }char *InfraredDev::get_dev_name() {return dev_name; }void InfraredDev::setLedWithText(ledWithText *obj) {infrared_ledWithText obj; }void InfraredDev::sigio_signal_func(int signum) {int err 0;unsigned int infrared_value 0;err read(fd, infrared_value, sizeof(infrared_value));if(err 0) { // InfraredDev instance; // 创建对象实例 // emit instance.infraredSignal(infrared_value);/* 读取错误 */infrared_ledWithText-setLedColor(Qt::red);infrared_ledWithText-setLedState(QSimpleLed::BLINK);infrared_ledWithText-setText(获取设备失败);qDebug()infrared:read error!;} else {if(infrared_value0){infrared_ledWithText-setLedColor(Qt::green);infrared_ledWithText-setText(设备已放置);}else if(infrared_value1){infrared_ledWithText-setLedColor(Qt::red);infrared_ledWithText-setLedState(QSimpleLed::BLINK);infrared_ledWithText-setText(设备未放置);}qDebug()infrared:sigio signal!infrared_value;}}void InfraredDev::register_infrared_asy() {int flags 0;/* 设置信号SIGIO的处理函数 */signal(SIGIO, InfraredDev::sigio_signal_func);fcntl(fd, F_SETOWN, getpid()); /* 设置当前进程接收SIGIO信号 */flags fcntl(fd, F_GETFL); /* 获取当前的进程状态 */fcntl(fd, F_SETFL, flags | FASYNC); /* 设置进程启用异步通知功能 */ }int InfraredDev::fd -1; // 初始化为无效的文件描述符 ledWithText *InfraredDev::infrared_ledWithText nullptr;#ifndef INFRAREDDEV_H #define INFRAREDDEV_H#include stdio.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h #include stdlib.h #include string.h #include poll.h #include sys/select.h #include sys/time.h #include linux/ioctl.h #include signal.h#include QObject #include QDebug #include QFile #include QTextStream #include QString#include ui_optimize/ledwithtext.h#define DEVNAME /dev/gpio_infraredclass InfraredDev : public QObject {Q_OBJECT public:explicit InfraredDev(QObject *parent nullptr);~InfraredDev();void set_dev_name(char *name);char * get_dev_name();static ledWithText *infrared_ledWithText;static void setLedWithText(ledWithText *obj);private:static int fd; /* 文件描述符 */static QFile file;char *dev_name;static void sigio_signal_func(int signum);void register_infrared_asy(void);};#endif // INFRAREDDEV_H因为static修饰的成员变量、成员函数并没有this指针因此无法读取其他非static成员只允许读取static变量因此我们需要将fd也需要使用static函数进行修饰并且函数内不能包含其他no-static的变量。 因此在signal函数我们就需要根据C访问静态函数的规则对参数进行传入了修改使用通过类名::静态成员的方式来访问。 signal(SIGIO, InfraredDev::sigio_signal_func); 然后我们需要让QMainwindow类知道接收到异步通信了需要刷新UI了。 1信号机制方法 我一开始是照常使用信号机制定义了信号函数使用emit函数进行发送但是因为异步通知处理函数是static类的无法直接调用其他non-static的成员无法发送信号因此我想是实例化一个类发送类的实例进而发送信号 InfraredDev instance; // 创建对象实例 emit instance.infraredSignal(infrared_value); 代码没报错但是执行过程出错了在开发板上只能读取第一次的数值发送后就无法进行读取由于是在开发板上进行运行的无法进行debug不知道是什么原因如果有大神知道还请不吝赐教 2指针传入做法 之后我看到了参考资料的3的做法就想直接传入界面的指针在异步通知里面直接读取指针进行界面的修改。因此我就根据non-static成员函数可以访问static成员变量的特性对该做法进行了改进。定义了一个设置控件的函数外部传入一个控件指针函数内部设置为static类型因此完美解决了该问题。 void InfraredDev::setLedWithText(ledWithText *obj) {infrared_ledWithText obj; }// 在static函数就可以使用这个static指针进行设置了 void InfraredDev::sigio_signal_func(int signum){......infrared_ledWithText-setLedColor(Qt::red);infrared_ledWithText-setLedState(QSimpleLed::BLINK);infrared_ledWithText-setText(设备未放置);} 在infrared_dev.h中存在该声明为static成员变量 static ledWithText *infrared_ledWithText; 那么我们在外部只需要传入该控件的指针即可 device_connect_label new ledWithText(this,Qt::green,设备正在连接);...... infrared_dev new InfraredDev(); infrared_dev-setLedWithText(device_place_label);
http://www.dnsts.com.cn/news/116054.html

相关文章:

  • 网站权重排行校园门户网站开发需求分析
  • 莱芜金点子下载哪些网站可以seo
  • 2003 您的安全设置不允许网站使用安装郑州企业建筑资质多少钱
  • 杭州建设网站四平做网站
  • 肥东建设网站化妆品产品的自建网站哟哪些
  • 各大网站域名大全网站产品优化
  • 试用型网站html电影网页制作模板
  • 网站招聘顾问做啥的江门网站建设方案报价
  • 凡科建站是永久的吗建设营销型网站
  • 网站源码和模板免费模板简历在哪下
  • 网站商城开发公司在线视频网站怎么做
  • 上海长宁网站建设怎么做自动下单网站
  • 佛山网站建设thualwordpress和dede seo
  • aspnet网站开发实例网站网站建设专业
  • 百度收录快的发帖网站php订餐网站开发文献
  • 网站二级页面设计要求浙江做网站多少钱
  • 湟源县wap网站建设公司常州微信网站建设
  • 郑州网站制作咨询求手机网站
  • 建设网站号码是多少钱南京网站建设外贸
  • 网站 被 抄袭建站之星模板好吗
  • 百度蜘蛛抓取新网站网站开发服务转包合同
  • 周年庆网站要怎么做重庆市工程建设信息网成绩查询
  • 网站设计做什么的怎么用php自己做网站
  • 海珠区网站建设集团网站建设教程
  • 商业店铺设计网站制作优化全包
  • 酒店网站建设案例网站空间大小 论坛
  • 重庆网站推广运营公司qq营销软件
  • 浙江网站建设广告语wordpress 打开好慢
  • 甘肃省城乡与建设厅网站首页wordpress 布局调整
  • 云浮网站建设兼职html5网站后台制作