嵌入式爱好者

查看: 21896|回复: 1

[评测] 【飞凌嵌入式 OK3399-C+开发板试用体验】使用QT工程读取DHT11模块的波折经历

[复制链接]

4

主题

4

帖子

64

积分

AM335x通行证i.MX6UL通行证i.MX RT通行证XX18通行证

扫一扫,手机访问本帖
发表于 2020-9-10 09:17:08 | 显示全部楼层 |阅读模式
飞凌嵌入式 OK3399-C+开发板试用体验】使用QT工程读取DHT11模块的波折经历

上一帖中已经成功使用一个简单的main函数成功读取到DHT11的温湿度数据了,虽然读取温湿度数据响应时间很慢,但至少算是成功读取了,这次我就想在QT环境下进行温湿度的读取,结合美观的图形界面呈现出来,同时,还可以以文件形式读取ADC_IN4接口 CPU0温度以及CPU1温度,使用到的QT类为QThread,还有Linux系统自带的pthread。为什么说是波折经历呢,因为DHT11这个器件对主控和系统的实时性要求实在是太高了,如果是直接用单片机主控来读取,那就没任何问题,但是要用到微处理器,哪怕是RK3399这种主频那么高的CPU,读取DHT11依然会出现实时性问题,这就很烦,由于QT的图形化界面用到了QMainWindow类,会占用一定的CPU实时资源,在这一两天的探索过程中,我先后用了QThread pthread QTimer三种方式读取DHT11数据,结果表明,要想稳定读取,只能用pthread进行,QThread这种QT内建的多线程实现类完全无法读取,顶多只能读取已经存在/sys中的实时CPU温度数据和ADC接口数据,而QTimer这种定时器中断类就更不用说了,实时性比QThread还低得多,跟pthread的效率比起来就没法比。我不知道QThread的实现代码是怎么写的,按我理解来说应该也只是对pthread做一定的封装,也没想到实时性/效率差这么远。

首先是读写两个CPUzone的温度,需要读取/sys/class/thermal/thermal_zone0/temp和/sys/class/thermal/thermal_zone1/temp:
  1. int fd_cputemp0,fd_cputemp1;
  2. unsigned char buf_cpu_temp0[5];
  3. unsigned char buf_cpu_temp1[5];

  4. fd_cputemp0 = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);
  5. fd_cputemp1 = open("/sys/class/thermal/thermal_zone1/temp", O_RDONLY);
  6. read(fd_adc4 , buf_adc4 ,5);
  7. read(fd_cputemp0 , buf_cpu_temp0 ,5);
  8. read(fd_cputemp1 , buf_cpu_temp1 ,5);
复制代码
41.jpg

而ADC_IN4则是用同样的方法读取/sys/bus/iio/devices/iio:device0/in_voltage4_raw:
  1. int fd_adc4;
  2. unsigned char buf_adc4[5];
  3. fd_adc4 = open("/sys/bus/iio/devices/iio:device0/in_voltage4_raw", O_RDONLY);
  4. read(fd_adc4 , buf_adc4 ,5);
复制代码
42.jpg

然后是对于DHT11的读取,原本我是打算使用QThread来进行读取了,也写好了QThread类:

  1. #ifndef MY_THREAD_H
  2. #define MY_THREAD_H
  3. #include <QThread>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <sys/time.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include "mainwindow.h"

  12. class MainWindow;

  13. class mythread : public QThread
  14. {
  15. public:
  16.     mythread(QObject *parent);
  17.     void closeThread();
  18.     struct timeval tv1;

  19. protected:
  20.     virtual void run();

  21. private:
  22.     volatile bool isStop;
  23.     MainWindow *m_pMainWindow;
  24.     int fd_cputemp0,fd_cputemp1,fd_adc4;
  25. };

  26. #endif // DHT11_THREAD_H
复制代码

  1. #include "mythread.h"
  2. #include "mainwindow.h"
  3. #include <ui_mainwindow.h>

  4. mythread::mythread(QObject *parent)
  5. {
  6.     isStop = false;
  7.     m_pMainWindow = qobject_cast<MainWindow*>(parent);
  8. }

  9. void mythread::closeThread()
  10. {
  11.     isStop = true;
  12. }

  13. extern float dht11_temp,dht11_humi;

  14. void mythread::run()
  15. {
  16.     int i=0;
  17.     unsigned char buf_adc4[5];
  18.     unsigned char buf_cpu_temp0[5];
  19.     unsigned char buf_cpu_temp1[5];
  20.     while (1)
  21.     {
  22.         if(isStop)
  23.             return;

  24.         //gettimeofday(&tv1, NULL);
  25.         //qDebug("tv1=%d\n",tv1.tv_usec);

  26.         fd_adc4 = open("/sys/bus/iio/devices/iio:device0/in_voltage4_raw", O_RDONLY);
  27.         fd_cputemp0 = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);
  28.         fd_cputemp1 = open("/sys/class/thermal/thermal_zone1/temp", O_RDONLY);
  29.         read(fd_adc4 , buf_adc4 ,5);
  30.         read(fd_cputemp0 , buf_cpu_temp0 ,5);
  31.         read(fd_cputemp1 , buf_cpu_temp1 ,5);
  32.         buf_adc4[4]=0;

  33.         m_pMainWindow->ui->L1->setText(QString("%1").arg(dht11_temp));
  34.         m_pMainWindow->ui->L2->setText(QString("%1").arg(dht11_humi));
  35.         m_pMainWindow->ui->L3->setText(QString((char*)buf_adc4));
  36.         m_pMainWindow->ui->L4->setText(QString((char*)buf_cpu_temp0));
  37.         m_pMainWindow->ui->L5->setText(QString((char*)buf_cpu_temp1));

  38.         sleep(1);
  39.     }
  40. }
复制代码

谁知道读取不成功,估计是read函数所在线程被CPU打断了,无奈之下只能换成Linux最基本的pthread实现方式:
  1. struct dht11_data
  2. {
  3.     unsigned short temp;
  4.     unsigned short hum;
  5. }curdht11_data;

  6. float dht11_temp,dht11_humi;

  7. pthread_t id;
  8. int fd_dht11;

  9. void *Thread_CPU_Temp(void *arg)
  10. {
  11.     int retval;
  12.     while(1)
  13.     {
  14.         retval = read ( fd_dht11 , &curdht11_data , sizeof(curdht11_data) );
  15.         if ( retval == -1 )
  16.         {
  17.             printf ( "read dht11 error" ) ;
  18.         }
  19.         if(curdht11_data.temp != 0xffff)
  20.         {
  21.             if(0 < (curdht11_data.temp>>8) && (curdht11_data.temp>>8) < 85)
  22.             {
  23.                 dht11_temp = (curdht11_data.temp >> 8) + (curdht11_data.temp & 0xff) * 0.01;
  24.                 dht11_humi = (curdht11_data.hum >> 8) + (curdht11_data.hum & 0xff) * 0.01;
  25.                 printf("---- %f %f-----\n",dht11_temp,dht11_humi);
  26.             }
  27.         }
  28.         //sleep(1);
  29.     }
  30. }
复制代码


这样的话可以正常读取,由此判断pthread实现方式能抢占到更多的CPU资源,并且pthread线程创建必须在MainWindow主窗口之前:
  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     fd_dht11 = open ( "/dev/dht11" , O_RDONLY) ;
  5.     if ( fd_dht11 == -1 )
  6.     {
  7.         perror ( "open dht11 error\n" ) ;
  8.     }
  9.     printf ( "open /dev/dht11 successfully\n" ) ;
  10.     pthread_create(&id , NULL , Thread_CPU_Temp , NULL);
  11.     printf ( "create pthread successfully\n" ) ;
  12.     MainWindow w;
  13.     w.show();

  14.     return a.exec();
  15. }
复制代码

QThread线程就只拿来读取CPU0温度,CPU1温度和ADC_IN4通道,Qthread线程的运行和暂停又一个按钮来控制:
  1. void MainWindow::on_PB1_clicked()
  2. {
  3.     disconnect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked()));
  4.     connect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked_2()));
  5.     ui->PB1->setText("Pause");
  6.     thread1->start();

  7. }

  8. void MainWindow::on_PB1_clicked_2()
  9. {
  10.     disconnect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked_2()));
  11.     connect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked()));
  12.     ui->PB1->setText("Start");
  13.     thread1->closeThread();
  14.     thread1->wait();
  15. }
复制代码
43.jpg



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2024-11-22 05:13

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

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