这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 【瑞芯微3399开发板试用体验】使用QT工程读取DHT11模块的波折经历

共4条 1/1 1 跳转至

【瑞芯微3399开发板试用体验】使用QT工程读取DHT11模块的波折经历

助工
2021-09-30 10:35:52     打赏

在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:int fd_cputemp0,fd_cputemp1;unsigned char buf_cpu_temp0[5];unsigned char buf_cpu_temp1[5];fd_cputemp0 = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);fd_cputemp1 = open("/sys/class/thermal/thermal_zone1/temp", O_RDONLY);read(fd_adc4 , buf_adc4 ,5);read(fd_cputemp0 , buf_cpu_temp0 ,5);read(fd_cputemp1 , buf_cpu_temp1 ,5);


而ADC_IN4则是用同样的方法读取/sys/bus/iio/devices/iio:device0/in_voltage4_raw:int fd_adc4;unsigned char buf_adc4[5];fd_adc4 = open("/sys/bus/iio/devices/iio:device0/in_voltage4_raw", O_RDONLY);read(fd_adc4 , buf_adc4 ,5);



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

#ifndef MY_THREAD_H#define MY_THREAD_H#include <QThread>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "mainwindow.h"class MainWindow;class mythread : public QThread{public:    mythread(QObject *parent);    void closeThread();    struct timeval tv1;protected:    virtual void run();private:    volatile bool isStop;    MainWindow *m_pMainWindow;    int fd_cputemp0,fd_cputemp1,fd_adc4;};#endif // DHT11_THREAD_H
#include "mythread.h"#include "mainwindow.h"#include <ui_mainwindow.h>mythread::mythread(QObject *parent){    isStop = false;    m_pMainWindow = qobject_cast<MainWindow*>(parent);}void mythread::closeThread(){    isStop = true;}extern float dht11_temp,dht11_humi;void mythread::run(){    int i=0;    unsigned char buf_adc4[5];    unsigned char buf_cpu_temp0[5];    unsigned char buf_cpu_temp1[5];    while (1)    {        if(isStop)            return;        //gettimeofday(&tv1, NULL);        //qdebug("tv1=%d\n",tv1.tv_usec);        fd_adc4 = open("/sys/bus/iio/devices/iio:device0/in_voltage4_raw", O_RDONLY);        fd_cputemp0 = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);        fd_cputemp1 = open("/sys/class/thermal/thermal_zone1/temp", O_RDONLY);        read(fd_adc4 , buf_adc4 ,5);        read(fd_cputemp0 , buf_cpu_temp0 ,5);        read(fd_cputemp1 , buf_cpu_temp1 ,5);        buf_adc4[4]=0;        m_pMainWindow->ui->L1->setText(QString("%1").arg(dht11_temp));        m_pMainWindow->ui->L2->setText(QString("%1").arg(dht11_humi));        m_pMainWindow->ui->L3->setText(QString((char*)buf_adc4));        m_pMainWindow->ui->L4->setText(QString((char*)buf_cpu_temp0));        m_pMainWindow->ui->L5->setText(QString((char*)buf_cpu_temp1));        sleep(1);    }}
谁知道读取不成功,估计是read函数所在线程被CPU打断了,无奈之下只能换成Linux最基本的pthread实现方式:struct dht11_data{    unsigned short temp;    unsigned short hum;}curdht11_data;float dht11_temp,dht11_humi;pthread_t id;int fd_dht11;void *Thread_CPU_Temp(void *arg){    int retval;    while(1)    {        retval = read ( fd_dht11 , &curdht11_data , sizeof(curdht11_data) );        if ( retval == -1 )        {            printf ( "read dht11 error" ) ;        }        if(curdht11_data.temp != 0xffff)        {            if(0 < (curdht11_data.temp>>8) && (curdht11_data.temp>>8) < 85)            {                dht11_temp = (curdht11_data.temp >> 8) + (curdht11_data.temp & 0xff) * 0.01;                dht11_humi = (curdht11_data.hum >> 8) + (curdht11_data.hum & 0xff) * 0.01;                printf("---- %f %f-----\n",dht11_temp,dht11_humi);            }        }        //sleep(1);    }}
这样的话可以正常读取,由此判断pthread实现方式能抢占到更多的CPU资源,并且pthread线程创建必须在MainWindow主窗口之前:int main(int argc, char *argv[]){    QApplication a(argc, argv);    fd_dht11 = open ( "/dev/dht11" , O_RDONLY) ;    if ( fd_dht11 == -1 )    {        perror ( "open dht11 error\n" ) ;    }    printf ( "open /dev/dht11 successfully\n" ) ;    pthread_create(&id , NULL , Thread_CPU_Temp , NULL);    printf ( "create pthread successfully\n" ) ;    MainWindow w;    w.show();    return a.exec();}
QThread线程就只拿来读取CPU0温度,CPU1温度和ADC_IN4通道,Qthread线程的运行和暂停又一个按钮来控制:void MainWindow::on_PB1_clicked(){    disconnect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked()));    connect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked_2()));    ui->PB1->setText("Pause");    thread1->start();}void MainWindow::on_PB1_clicked_2(){    disconnect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked_2()));    connect(ui->PB1,SIGNAL(clicked()),this,SLOT(on_PB1_clicked()));    ui->PB1->setText("Start");    thread1->closeThread();    thread1->wait();}

原文链接:https://www.forlinx.com/article_view_530.html



高工
2021-09-30 10:40:47     打赏
2楼

这是个啥啊~~~


专家
2021-09-30 10:43:56     打赏
3楼

感谢分享 


院士
2021-09-30 10:41:55     打赏
4楼

这排版,厉害了


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]